Revision 1849

View differences:

org.gvsig.geoprocess/trunk/org.gvsig.geoprocess/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.groupby/src/main/java/org/gvsig/geoprocess/algorithm/groupby/GroupByAlgorithm.java
72 72
import es.unex.sextante.gui.algorithm.GeoAlgorithmParametersPanel;
73 73
import es.unex.sextante.outputs.OutputVectorLayer;
74 74
import java.sql.Timestamp;
75
import java.util.HashSet;
76
import org.gvsig.expressionevaluator.ExpressionBuilder;
77
import org.gvsig.fmap.geom.GeometryUtils;
78
import org.gvsig.tools.namestranslator.NamesTranslator;
79
import org.gvsig.tools.util.CompareUtils;
75 80

  
76 81
/**
77 82
 * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
78 83
 */
79 84
public class GroupByAlgorithm extends AbstractSextanteGeoProcess {
80 85

  
81
	public static final String         RESULT            = "RESULT";
82
	public static final String         LAYER             = "LAYER";
83
	public static final String         FIELD             = "FIELD";
84
	public static final String         FIELD_DATE        = "FIELD_DATE";
85
	public static final String         FIELD_LIST        = "FIELD_LIST";
86
	public static final String         LAYER_NAME        = "LAYER_NAME";
87
	/**
88
	 * <P>Possible values</P>
89
	 * <UL>
90
	 * <LI>-1: Without geometry</LI>
91
	 * <LI>0: First geometry </LI>
92
	 * <LI>1: Creates a multigeometry </LI>
93
	 * <LI>2: Fusion of polygons </LI>
94
	 * </UL>
95
	 **/
96
	public static final String         GEOM_OPTION       = "GEOM_OPTION";
97
	public static final String         FUNCTION_LIST     = "FUNCTION_LIST";
98
	public static final String         Summary[]         = {"Min", "Max", "Sum", "Avg", "Last", "Any"};
99
	 
100
	/*
86
    public static final String RESULT = "RESULT";
87
    public static final String LAYER = "LAYER";
88
    public static final String FIELD = "FIELD";
89
    public static final String FIELD_DATE = "FIELD_DATE";
90
    public static final String FIELD_LIST = "FIELD_LIST";
91
    public static final String LAYER_NAME = "LAYER_NAME";
92
    /**
93
     * <P>
94
     * Possible values</P>
95
     * <UL>
96
     * <LI>-1: Without geometry</LI>
97
     * <LI>0: First geometry </LI>
98
     * <LI>1: Creates a multigeometry </LI>
99
     * <LI>2: Fusion of polygons </LI>
100
     * </UL>
101
	 *
102
     */
103
    public static final String GEOM_OPTION = "GEOM_OPTION";
104
    public static final String FUNCTION_LIST = "FUNCTION_LIST";
105
    public static final String Summary[] = {"Min", "Max", "Sum", "Avg", "Last", "Any"};
106

  
107
    /*
101 108
	 * (non-Javadoc)
102 109
	 * @see es.unex.sextante.core.GeoAlgorithm#defineCharacteristics()
103
	 */
104
	public void defineCharacteristics(){
110
     */
111
    public void defineCharacteristics() {
105 112
        setName(getTranslation("groupby"));
106 113
        setGroup(getTranslation("basic_vect_algorithms"));
107 114
        // setGeneratesUserDefinedRasterOutput(false);
108
		try {
109
			m_Parameters.addInputVectorLayer(LAYER, getTranslation("Input_layer"), IVectorLayer.SHAPE_TYPE_WRONG, true);
110
			m_Parameters.addString(FIELD, getTranslation("Field"));
111
			m_Parameters.addString(FIELD_DATE, getTranslation("Field_date"));
112
			m_Parameters.addString(FIELD_LIST, getTranslation("Field_list"));
113
			m_Parameters.addString(FUNCTION_LIST, getTranslation("Function_list"));
114
			m_Parameters.addString(LAYER_NAME, getTranslation("Layer_name"));
115
			m_Parameters.addNumericalValue(GEOM_OPTION, getTranslation("Geom"), -1, AdditionalInfoNumericalValue.NUMERICAL_VALUE_INTEGER);
116
			addOutputVectorLayer(RESULT, getTranslation("group_by"), OutputVectorLayer.SHAPE_TYPE_UNDEFINED);
117
		} catch (RepeatedParameterNameException e) {
118
			Sextante.addErrorToLog(e);
119
		}
120
	}
121
	
122
	/*
115
        try {
116
            m_Parameters.addInputVectorLayer(LAYER, getTranslation("Input_layer"), IVectorLayer.SHAPE_TYPE_WRONG, true);
117
            m_Parameters.addString(FIELD, getTranslation("Field"));
118
            m_Parameters.addString(FIELD_DATE, getTranslation("Field_date"));
119
            m_Parameters.addString(FIELD_LIST, getTranslation("Field_list"));
120
            m_Parameters.addString(FUNCTION_LIST, getTranslation("Function_list"));
121
            m_Parameters.addString(LAYER_NAME, getTranslation("Layer_name"));
122
            m_Parameters.addNumericalValue(GEOM_OPTION, getTranslation("Geom"), -1, AdditionalInfoNumericalValue.NUMERICAL_VALUE_INTEGER);
123
            addOutputVectorLayer(RESULT, getTranslation("group_by"), OutputVectorLayer.SHAPE_TYPE_UNDEFINED);
124
        } catch (RepeatedParameterNameException e) {
125
            Sextante.addErrorToLog(e);
126
        }
127
    }
128

  
129
    /*
123 130
	 * (non-Javadoc)
124 131
	 * @see es.unex.sextante.core.GeoAlgorithm#processAlgorithm()
125
	 */
126
	public boolean processAlgorithm() throws GeoAlgorithmExecutionException {
127
		if(existsOutPutFile(GroupByAlgorithm.RESULT, 0)) {
128
    		throw new GeoAlgorithmExecutionException(getTranslation("file_exists"));
129
    	}
130
		IVectorLayer layer = m_Parameters.getParameterValueAsVectorLayer(LAYER);
131
		String groupByField = m_Parameters.getParameterValueAsString(FIELD);
132
		String fieldDate = m_Parameters.getParameterValueAsString(FIELD_DATE);
133
		String fieldsString = m_Parameters.getParameterValueAsString(FIELD_LIST);
134
		String functionsString = m_Parameters.getParameterValueAsString(FUNCTION_LIST);
135
		String layerName = m_Parameters.getParameterValueAsString(LAYER_NAME);
136
		int geomOption = m_Parameters.getParameterValueAsInt(GEOM_OPTION);
137
		int inputShapeType = layer.getShapeType();
138
		
139
		String[] funcList = functionsString.split(";");
140
		String[] fieldList = null;
141
		if(!fieldsString.equals(""))
142
			fieldList = fieldsString.split(";");
143
		
144
		if(fieldList != null && funcList != null) {
145
			if(fieldList.length != funcList.length) {
146
				Sextante.addErrorToLog("invalid_input_parameters");
147
			}
148
		}
149
		
150
		FeatureStore featureStore = null;
151
		if(layer instanceof FlyrVectIVectorLayer)
152
			featureStore = ((FlyrVectIVectorLayer)layer).getFeatureStore();
153
		else
154
			return false;
155
		
156
		try {
157
			FeatureType featureType = featureStore.getDefaultFeatureType();
158
			FeatureAttributeDescriptor desc = featureType.getAttributeDescriptor(groupByField);
159
			String fieldNameGrouped = desc.getName();
160
			FeatureStore outFeatStore = buildOutPutStore(featureType, 
161
														layerName, 
162
														groupByField, 
163
														fieldList, 
164
														funcList, 
165
														geomOption,
166
														inputShapeType);
167
			
168
			Set<String> list = getGroupedValues(featureStore, groupByField);
169
			int numberOfFeatures = list.size();
170
			if (getStatus() != null) {
171
				getStatus().setRangeOfValues(0, numberOfFeatures);
172
	        }
173
			int cont = 0;
174
			Iterator<String> it = list.iterator();
175
			while( it.hasNext() ) {
176
				if (getStatus() != null) {
177
					getStatus().setCurValue(cont);
178
		        }	
179
				setProgress(cont, numberOfFeatures);
180
				String groupedValue = it.next();
181
				loadFeature(featureStore, 
182
						outFeatStore, 
183
						fieldNameGrouped, 
184
						fieldDate, 
185
						groupedValue, 
186
						fieldList, 
187
						funcList,
188
						geomOption);
189
				cont++;
190
			}
191
			
192
			outFeatStore.finishEditing();
193
		} catch (DataException e) {
194
			Sextante.addErrorToLog(e);
195
		}
196
		
197
		return true;
198
	}
199
	
200
	private void loadFeature(FeatureStore inStore, 
201
			FeatureStore outStore, 
202
			String fieldNameGrouped,
203
			String fieldDate,
204
			String groupedValue, 
205
			String[] fieldList, 
206
			String[] funcList,
207
			int geomOption) throws DataException {
208
		DataManager manager = DALLocator.getDataManager();
209
		
210
		EditableFeature feat = outStore.createNewFeature(outStore.getDefaultFeatureType(), true);
132
     */
133
    public boolean processAlgorithm() throws GeoAlgorithmExecutionException {
134
        if (existsOutPutFile(GroupByAlgorithm.RESULT, 0)) {
135
            throw new GeoAlgorithmExecutionException(getTranslation("file_exists"));
136
        }
137
        IVectorLayer layer = m_Parameters.getParameterValueAsVectorLayer(LAYER);
138
        String groupByField = m_Parameters.getParameterValueAsString(FIELD);
139
        String fieldDate = m_Parameters.getParameterValueAsString(FIELD_DATE);
140
        String fieldsString = m_Parameters.getParameterValueAsString(FIELD_LIST);
141
        String functionsString = m_Parameters.getParameterValueAsString(FUNCTION_LIST);
142
        String layerName = m_Parameters.getParameterValueAsString(LAYER_NAME);
143
        int geomOption = m_Parameters.getParameterValueAsInt(GEOM_OPTION);
144
        int inputShapeType = layer.getShapeType();
211 145

  
212
		FeatureQuery query = inStore.createFeatureQuery();
213
		Evaluator filter = manager.createExpresion(fieldNameGrouped + " = '" + groupedValue + "'");
214
		query.setFilter(filter);
215
		FeatureSet featSet = inStore.getFeatureSet(query);
216
		Iterator it = featSet.iterator();
217
		List<Geometry> geomList = new ArrayList<Geometry>();
218
		
219
		Object[] values = null;
220
		if(fieldList != null)
221
			values = new Object[fieldList.length];
222
		int nFeaturesByGroup = 0;
223
		Date lastDate = null;
146
        String[] funcList = functionsString.split(";");
147
        String[] fieldList = null;
148
        if (!fieldsString.equals("")) {
149
            fieldList = fieldsString.split(";");
150
        }
224 151

  
225
		while(it.hasNext()) {
226
			Feature feature = (Feature)it.next();
152
        if (fieldList != null && funcList != null) {
153
            if (fieldList.length != funcList.length) {
154
                Sextante.addErrorToLog("invalid_input_parameters");
155
            }
156
        }
227 157

  
228
			if(fieldList != null) {
229
				for (int i = 0; i < fieldList.length; i++) {
230
					Object v = feature.get(fieldList[i]);
231
					//Class<?> c = inStore.getDefaultFeatureType().getAttributeDescriptor(funcList[i]).getClassOfValue();
232
					if(v instanceof Number) {
233
						if(funcList[i].compareToIgnoreCase("Min") == 0) {
234
							if(values[i] == null) 
235
								values[i] = Double.POSITIVE_INFINITY;
236
							values[i] = updateMinimum((Double)values[i], v);
237
						}
238
						if(funcList[i].compareToIgnoreCase("Max") == 0) {
239
							if(values[i] == null) 
240
								values[i] = Double.NEGATIVE_INFINITY;
241
							values[i] = updateMaximum((Double)values[i], v);
242
						}
243
						if(funcList[i].compareToIgnoreCase("Sum") == 0 || funcList[i].compareToIgnoreCase("Average") == 0) {
244
							if(values[i] == null) 
245
								values[i] = new Double(0D);
246
							values[i] = sum((Double)values[i], v);
247
						}
248
					}
249
					if(funcList[i].compareToIgnoreCase("First") == 0) {
250
						if(values[i] == null) 
251
							values[i] = objectConversion(v);
252
					}
253
					if(funcList[i].compareToIgnoreCase("Last") == 0 && fieldDate != null) {
254
						if(lastDate == null || values[i] == null || lastDate.getTime() > feature.getTimestamp(fieldDate).getTime()) {
255
							lastDate = feature.getTimestamp(fieldDate);
256
							values[i] = objectConversion(v);
257
						}
258
					}
259
				}
260
			}
261
			
262
			if(geomOption >= 0) {
263
				switch (geomOption) {
264
				case 0: //Adds only the first geometry
265
					if(nFeaturesByGroup == 0) { //If is the first feature
266
						Geometry g = feature.getDefaultGeometry();
267
						if(!(g instanceof MultiPrimitive)) {
268
							List<Geometry> gList = new ArrayList<Geometry>();
269
							gList.add(g);
270
							g = buildMultiGeometry(gList);
271
						}
272
						feat.set(outStore.getDefaultFeatureType().getDefaultGeometryAttributeName(), g);
273
					}
274
					break;
275
				case 1: //Multigeometry with all geometries
276
				case 2: //Union among all geometries
277
					geomList.add(feature.getDefaultGeometry().cloneGeometry());
278
					break;
279
				}
280
			}
281
			nFeaturesByGroup ++;
282
		}
158
        FeatureStore featureStore = null;
159
        if (layer instanceof FlyrVectIVectorLayer) {
160
            featureStore = ((FlyrVectIVectorLayer) layer).getFeatureStore();
161
        } else {
162
            return false;
163
        }
283 164

  
165
        try {
166
            FeatureType featureType = featureStore.getDefaultFeatureType();
167
            FeatureAttributeDescriptor desc = featureType.getAttributeDescriptor(groupByField);
168
            String fieldNameGrouped = desc.getName();
169
            FeatureStore outFeatStore = buildOutPutStore(featureType,
170
                    layerName,
171
                    groupByField,
172
                    fieldList,
173
                    funcList,
174
                    geomOption,
175
                    inputShapeType);
176
            
177
            Set<Object> groupedValues = getGroupedValues(featureStore, groupByField);
178
            int numberOfFeatures = groupedValues.size();
179
            if (getStatus() != null) {
180
                getStatus().setRangeOfValues(0, numberOfFeatures);
181
            }
182
            int cont = 0;
183
            Iterator<Object> it = groupedValues.iterator();
184
            while (it.hasNext()) {
185
                if (getStatus() != null) {
186
                    getStatus().setCurValue(cont);
187
                }
188
                setProgress(cont, numberOfFeatures);
189
                Object groupedValue = it.next();
190
                loadFeature(featureStore,
191
                        outFeatStore,
192
                        fieldNameGrouped,
193
                        fieldDate,
194
                        groupedValue,
195
                        fieldList,
196
                        funcList,
197
                        geomOption);
198
                cont++;
199
            }
200

  
201
            outFeatStore.finishEditing();
202
        } catch (DataException e) {
203
            Sextante.addErrorToLog(e);
204
        }
205

  
206
        return true;
207
    }
208

  
209
    private void loadFeature(FeatureStore inStore,
210
            FeatureStore outStore,
211
            String fieldNameGrouped,
212
            String fieldDate,
213
            Object groupedValue,
214
            String[] fieldList,
215
            String[] funcList,
216
            int geomOption) throws DataException {
217
        DataManager manager = DALLocator.getDataManager();
218

  
219
        EditableFeature feat = outStore.createNewFeature(outStore.getDefaultFeatureType(), true);
220

  
221
        FeatureQuery query = inStore.createFeatureQuery();
222
        ExpressionBuilder expressionBuilder = outStore.createExpressionBuilder();
223
        Evaluator filter = manager.createFilter(expressionBuilder.column(fieldNameGrouped) + " = " + expressionBuilder.constant(groupedValue) );
224
        query.setFilter(filter);
225
        query.retrievesAllAttributes();
226
        FeatureSet featSet = inStore.getFeatureSet(query);
227
        Iterator it = featSet.iterator();
228
        List<Geometry> geomList = new ArrayList<Geometry>();
229

  
230
        Object[] values = null;
231
        if (fieldList != null) {
232
            values = new Object[fieldList.length];
233
        }
234
        int nFeaturesByGroup = 0;
235
        Date lastDate = null;
236

  
237
        while (it.hasNext()) {
238
            Feature feature = (Feature) it.next();
239

  
240
            if (fieldList != null) {
241
                for (int i = 0; i < fieldList.length; i++) {
242
                    Object v = feature.get(fieldList[i]);
243
                    //Class<?> c = inStore.getDefaultFeatureType().getAttributeDescriptor(funcList[i]).getClassOfValue();
244
                    if (v instanceof Number) {
245
                        if (funcList[i].compareToIgnoreCase("Min") == 0) {
246
                            if (values[i] == null) {
247
                                values[i] = Double.POSITIVE_INFINITY;
248
                            }
249
                            values[i] = updateMinimum(values[i], v);
250
                        }
251
                        if (funcList[i].compareToIgnoreCase("Max") == 0) {
252
                            if (values[i] == null) {
253
                                values[i] = Double.NEGATIVE_INFINITY;
254
                            }
255
                            values[i] = updateMaximum(values[i], v);
256
                        }
257
                        if (funcList[i].compareToIgnoreCase("Sum") == 0 || funcList[i].compareToIgnoreCase("Average") == 0) {
258
                            if (values[i] == null) {
259
                                values[i] = 0L;
260
                            }
261
                            values[i] = sum(values[i], v);
262
                        }
263
                    }
264
                    if (funcList[i].compareToIgnoreCase("First") == 0) {
265
                        if (values[i] == null) {
266
                            values[i] = objectConversion(v);
267
                        }
268
                    }
269
                    if (funcList[i].compareToIgnoreCase("Last") == 0 && fieldDate != null) {
270
                        if (lastDate == null || values[i] == null || lastDate.getTime() > feature.getTimestamp(fieldDate).getTime()) {
271
                            lastDate = feature.getTimestamp(fieldDate);
272
                            values[i] = objectConversion(v);
273
                        }
274
                    }
275
                }
276
            }
277

  
278
            if (geomOption >= 0) {
279
                switch (geomOption) {
280
                    case 0: //Adds only the first geometry
281
                        if (nFeaturesByGroup == 0) { //If is the first feature
282
                            Geometry g = feature.getDefaultGeometry();
283
                            if (!(g instanceof MultiPrimitive)) {
284
                                List<Geometry> gList = new ArrayList<Geometry>();
285
                                gList.add(g);
286
                                g = buildMultiGeometry(gList);
287
                            }
288
                            feat.set(outStore.getDefaultFeatureType().getDefaultGeometryAttributeName(), g);
289
                        }
290
                        break;
291
                    case 1: //Multigeometry with all geometries
292
                    case 2: //Union among all geometries
293
                        geomList.add(feature.getDefaultGeometry().cloneGeometry());
294
                        break;
295
                }
296
            }
297
            nFeaturesByGroup++;
298
        }
299

  
284 300
//		it.dispose();
285
		featSet.dispose();
286
		feat.set(fieldNameGrouped, groupedValue);
287
		
288
		//Se asignan los campos calculados
289
		if(fieldList != null) {
290
			for (int i = 0; i < values.length; i++) {
291
				if(funcList[i].compareToIgnoreCase("Average") == 0) {
292
					values[i] = ((Double)values[i]).doubleValue() / nFeaturesByGroup; 
293
				} 
294
				feat.set(i + 1, values[i]);					
295
			}
296
		}
297
		
298
		//Si hay que convertir a multigeometr?a
299
		if(geomOption == 1 && geomList.size() > 0)
300
			feat.set(outStore.getDefaultFeatureType().getDefaultGeometryAttributeName(), buildMultiGeometry(geomList));
301
		if(geomOption == 2 && geomList.size() > 0)
302
			feat.set(outStore.getDefaultFeatureType().getDefaultGeometryAttributeName(), computesUnion(geomList));
303
		outStore.update(feat);
304
	}
305
	
306
	private Object objectConversion(Object obj) {
307
		if(obj instanceof Instant) 
308
			return convertInstantToDate((Instant)obj);
309
		return obj;
310
	}
311
	
312
	/**
313
	 * Converts an Instant to Date. This is useful to save a Instant in a DBF file
314
	 * @param instant
315
	 * @return
316
	 */
317
	private Date convertInstantToDate(Instant instant) {
318
		if(instant instanceof AbsoluteInstant) {
319
			int year = ((AbsoluteInstant)instant).getYears();
320
			int month = ((AbsoluteInstant)instant).getMonths();
321
			int day = ((AbsoluteInstant)instant).getDays();
322
			int min = ((AbsoluteInstant)instant).getMinutes();
323
			int hour = ((AbsoluteInstant)instant).getHours();
324
			int second = ((AbsoluteInstant)instant).getSeconds();
325
			int millis = ((AbsoluteInstant)instant).getMillis();
326
			Calendar c = Calendar.getInstance();
327
			c.set(year, month, day, hour, min);
328
			return new Date(c.getTimeInMillis() + (second * 1000) + millis);
329
		}
330
		if(instant instanceof RelativeInstant) {
331
			return new Date(((RelativeInstant)instant).toMillis());
332
		}
333
		return null;
334
	}
335
	
336
	/**
337
	 * Builds a unique geometry with all geometries in the list
338
	 * @param geomList
339
	 * @return
340
	 */
341
	private Geometry buildMultiGeometry(List<Geometry> geomList) {
342
		Geometry newGeom = null;
343
		for (int i = 0; i < geomList.size(); i++) {
344
			if(i == 0) {
345
				try {
346
					if(geomList.get(0).getType() == TYPES.POINT || geomList.get(0).getType() == TYPES.MULTIPOINT)
347
						newGeom = (MultiPoint)geomManager.create(TYPES.MULTIPOINT, SUBTYPES.GEOM2D);
348
					if(geomList.get(0).getType() == TYPES.CURVE || geomList.get(0).getType() == TYPES.MULTICURVE)
349
						newGeom = (MultiCurve)geomManager.create(TYPES.MULTICURVE, SUBTYPES.GEOM2D);
350
					if(geomList.get(0).getType() == TYPES.SURFACE || geomList.get(0).getType() == TYPES.MULTISURFACE)
351
						newGeom = (MultiSurface)geomManager.create(TYPES.MULTISURFACE, SUBTYPES.GEOM2D);
352
				} catch (CreateGeometryException e) {
353
				}	
354
			}
301
        featSet.dispose();
302
        feat.set(fieldNameGrouped, groupedValue);
355 303

  
356
			if(geomList.get(i) instanceof Surface) {
357
				((MultiSurface)newGeom).addPrimitive((Surface)geomList.get(i));
358
			} 
359
			if(geomList.get(i) instanceof MultiSurface) {
360
				int nPrimitives = ((MultiSurface)geomList.get(i)).getPrimitivesNumber();
361
				for (int iPrimitive = 0; iPrimitive < nPrimitives; iPrimitive++) {
362
					((MultiSurface)newGeom).addPrimitive(((MultiSurface)geomList.get(i)).getSurfaceAt(iPrimitive));
363
				}
364
			}
365
			if(geomList.get(i) instanceof Curve) {
366
				((MultiCurve)newGeom).addPrimitive((Curve)geomList.get(i));
367
			} 
368
			if(geomList.get(i) instanceof MultiCurve) {
369
				int nPrimitives = ((MultiSurface)geomList.get(i)).getPrimitivesNumber();
370
				for (int iPrimitive = 0; iPrimitive < nPrimitives; iPrimitive++) {
371
					((MultiCurve)newGeom).addPrimitive(((MultiCurve)geomList.get(i)).getCurveAt(iPrimitive));
372
				}
373
			}
374
			if(geomList.get(i) instanceof Point) {
375
				((MultiPoint)newGeom).addPrimitive((Point)geomList.get(i));
376
			} 
377
			if(geomList.get(i) instanceof MultiPoint) {
378
				int nPrimitives = ((MultiPoint)geomList.get(i)).getPrimitivesNumber();
379
				for (int iPrimitive = 0; iPrimitive < nPrimitives; iPrimitive++) {
380
					((MultiPoint)newGeom).addPrimitive(((MultiPoint)geomList.get(i)).getPointAt(iPrimitive));
381
				}
382
			}
304
        //Se asignan los campos calculados
305
        if (fieldList != null) {
306
            for (int i = 0; i < values.length; i++) {
307
                if (funcList[i].compareToIgnoreCase("Average") == 0) {
308
                    values[i] = ((Number) values[i]).doubleValue() / nFeaturesByGroup;
309
                }
310
                feat.set(i + 1, values[i]);
311
            }
312
        }
383 313

  
384
		}
314
        //Si hay que convertir a multigeometr?a
315
        if (geomOption == 1 && geomList.size() > 0) {
316
            feat.set(outStore.getDefaultFeatureType().getDefaultGeometryAttributeName(), buildMultiGeometry(geomList));
317
        }
318
        if (geomOption == 2 && geomList.size() > 0) {
319
            feat.set(outStore.getDefaultFeatureType().getDefaultGeometryAttributeName(), computesUnion(geomList));
320
        }
321
        outStore.insert(feat);
322
    }
385 323

  
386
		return newGeom;
387
	}
388
	
389
	/**
390
	 * Computes the union of gemetries in the list
391
	 * @param listInput
392
	 * @return
393
	 */
394
	private Geometry computesUnion(List<Geometry> listInput) {
395
		List<com.vividsolutions.jts.geom.Geometry> listResult = new ArrayList<com.vividsolutions.jts.geom.Geometry>();
396
		for (int i = listInput.size() - 1; i >= 0; i--) {
397
			listResult.add(GeometryUtil.geomToJTS(listInput.get(i)));
398
			listInput.remove(i);
399
		}
400
		com.vividsolutions.jts.geom.Geometry newGeom = listResult.size() > 0 ? listResult.get(0) : null;
401
		while(listResult.size() > 1) {
402
			List<com.vividsolutions.jts.geom.Geometry> list = new ArrayList<com.vividsolutions.jts.geom.Geometry>();
403
			for (int i = 0; i < listResult.size(); i = i + 2) {
404
				if(i == (listResult.size() - 1))
405
					list.add(listResult.get(i));
406
				else {
407
					newGeom = JTSFacade.union(listResult.get(i), listResult.get(i + 1));
408
					list.add(newGeom);
409
				}
410
			}
411
			listResult = list;
412
		}
413
		return GeometryUtil.jtsToGeom(newGeom);
414
	}
324
    private Object objectConversion(Object obj) {
325
        if (obj instanceof Instant) {
326
            return convertInstantToDate((Instant) obj);
327
        }
328
        return obj;
329
    }
415 330

  
416
	private Double updateAny(Double min, Object value) {
417
		if(value instanceof Double)
418
			return (Double)value;
419
		else if(value instanceof Integer)
420
			return ((Integer)value).doubleValue();
421
		return min;
422
	}
423
	
424
	private Double updateMinimum(Double min, Object value) {
425
		if(value instanceof Double && ((Double)value).doubleValue() < min)
426
			return (Double)value;
427
		else if(value instanceof Integer && ((Integer)value).intValue() < min)
428
			return ((Integer)value).doubleValue();
429
		return min;
430
	}
431
	
432
	private Double updateMaximum(Double max, Object value) {
433
		if(value instanceof Double && ((Double)value).doubleValue() > max)
434
			return (Double)value;
435
		else if(value instanceof Integer && ((Integer)value).intValue() > max)
436
			return ((Integer)value).doubleValue();
437
		return max;
438
	}
439
	
440
	private Double sum(Double current, Object value) {
441
		if(value instanceof Double)
442
			return ((Double)value) + current;
443
		else if(value instanceof Integer)
444
			return ((Integer)value) + current;
445
		return current;
446
	}
331
    /**
332
     * Converts an Instant to Date. This is useful to save a Instant in a DBF
333
     * file
334
     *
335
     * @param instant
336
     * @return
337
     */
338
    private Date convertInstantToDate(Instant instant) {
339
        if (instant instanceof AbsoluteInstant) {
340
            int year = ((AbsoluteInstant) instant).getYears();
341
            int month = ((AbsoluteInstant) instant).getMonths();
342
            int day = ((AbsoluteInstant) instant).getDays();
343
            int min = ((AbsoluteInstant) instant).getMinutes();
344
            int hour = ((AbsoluteInstant) instant).getHours();
345
            int second = ((AbsoluteInstant) instant).getSeconds();
346
            int millis = ((AbsoluteInstant) instant).getMillis();
347
            Calendar c = Calendar.getInstance();
348
            c.set(year, month, day, hour, min);
349
            return new Date(c.getTimeInMillis() + (second * 1000) + millis);
350
        }
351
        if (instant instanceof RelativeInstant) {
352
            return new Date(((RelativeInstant) instant).toMillis());
353
        }
354
        return null;
355
    }
447 356

  
448
	/**
449
	 * Gets the list of grouped values
450
	 * @param featureStore
451
	 * @param groupByField
452
	 * @return
453
	 * @throws DataException
454
	 */
455
	private Set<String> getGroupedValues(FeatureStore featureStore, String groupByField) throws DataException {
456
		HashMap<String, String> valueGrouped = new HashMap<String, String>();
457
		FeatureSet featureSet = featureStore.getFeatureSet();
458
		Iterator it = featureSet.iterator();
459
		while( it.hasNext() ) {
460
			Feature feature = (Feature)it.next();
461
			Object obj = feature.get(groupByField);
462
			String s = null;
463
			if(obj instanceof String)
464
				s = new String(((String)obj));
465
			else if(obj instanceof Double)
466
				s = String.valueOf((Double)obj);
467
			else if(obj instanceof Integer)
468
				s = String.valueOf((Integer)obj);
469
			else if(obj instanceof Float)
470
				s = String.valueOf((Float)obj);
471
			else if(obj instanceof Boolean)
472
				s = String.valueOf((Boolean)obj);
473
			else if(obj instanceof Long)
474
				s = String.valueOf((Long)obj);
475
			else if(obj instanceof Byte)
476
				s = String.valueOf((Byte)obj);
477
			else if(obj instanceof Date)
478
				s = ((Date)obj).toString();
479
			if(valueGrouped.get(s) == null) {
480
				valueGrouped.put(s, s);
481
			}
482
		}
357
    /**
358
     * Builds a unique geometry with all geometries in the list
359
     *
360
     * @param geomList
361
     * @return
362
     */
363
    private Geometry buildMultiGeometry(List<Geometry> geomList) {
364
        Geometry newGeom = null;
365
        for (int i = 0; i < geomList.size(); i++) {
366
            if (i == 0) {
367
                try {
368
                    int geomType = geomList.get(0).getType();
369
                    int geomSubtype = geomList.get(0).getGeometryType().getSubType();
370
                    if (GeometryUtils.isSubtype(TYPES.POINT, geomType) || GeometryUtils.isSubtype(TYPES.MULTIPOINT, geomType)) {
371
                        newGeom = (MultiPoint) geomManager.create(TYPES.MULTIPOINT, geomSubtype);
372
                    } else if (GeometryUtils.isSubtype(TYPES.CURVE, geomType) || GeometryUtils.isSubtype(TYPES.MULTICURVE, geomType)) {
373
                        newGeom = (MultiCurve) geomManager.create(TYPES.MULTILINE, geomSubtype);
374
                    } else if (GeometryUtils.isSubtype(TYPES.SURFACE, geomType) || GeometryUtils.isSubtype(TYPES.MULTISURFACE, geomType)) {
375
                        newGeom = (MultiSurface) geomManager.create(TYPES.MULTISURFACE, geomSubtype);
376
                    }
377
                } catch (CreateGeometryException e) {
378
                    LOGGER.warn("Can't create geometry.", e);
379
                }
380
            }
381
            
382
            Geometry geom = geomList.get(i);
383
            ((MultiPrimitive)newGeom).addPrimitives(geom);
384
//            if (geom instanceof Surface) {
385
//                ((MultiSurface) newGeom).addPrimitives(geom);
386
//            }
387
//            if (geomList.get(i) instanceof MultiSurface) {
388
//                int nPrimitives = ((MultiSurface) geomList.get(i)).getPrimitivesNumber();
389
//                for (int iPrimitive = 0; iPrimitive < nPrimitives; iPrimitive++) {
390
//                    ((MultiSurface) newGeom).addPrimitive(((MultiSurface) geomList.get(i)).getSurfaceAt(iPrimitive));
391
//                }
392
//            }
393
//            if (geomList.get(i) instanceof Curve) {
394
//                ((MultiCurve) newGeom).addPrimitive((Curve) geomList.get(i));
395
//            }
396
//            if (geomList.get(i) instanceof MultiCurve) {
397
//                int nPrimitives = ((MultiSurface) geomList.get(i)).getPrimitivesNumber();
398
//                for (int iPrimitive = 0; iPrimitive < nPrimitives; iPrimitive++) {
399
//                    ((MultiCurve) newGeom).addPrimitive(((MultiCurve) geomList.get(i)).getCurveAt(iPrimitive));
400
//                }
401
//            }
402
//            if (geomList.get(i) instanceof Point) {
403
//                ((MultiPoint) newGeom).addPrimitive((Point) geomList.get(i));
404
//            }
405
//            if (geomList.get(i) instanceof MultiPoint) {
406
//                int nPrimitives = ((MultiPoint) geomList.get(i)).getPrimitivesNumber();
407
//                for (int iPrimitive = 0; iPrimitive < nPrimitives; iPrimitive++) {
408
//                    ((MultiPoint) newGeom).addPrimitive(((MultiPoint) geomList.get(i)).getPointAt(iPrimitive));
409
//                }
410
//            }
411

  
412
        }
413

  
414
        return newGeom;
415
    }
416

  
417
    /**
418
     * Computes the union of gemetries in the list
419
     *
420
     * @param listInput
421
     * @return
422
     */
423
    private Geometry computesUnion(List<Geometry> listInput) {
424
        List<com.vividsolutions.jts.geom.Geometry> listResult = new ArrayList<com.vividsolutions.jts.geom.Geometry>();
425
        for (int i = listInput.size() - 1; i >= 0; i--) {
426
            listResult.add(GeometryUtil.geomToJTS(listInput.get(i)));
427
            listInput.remove(i);
428
        }
429
        com.vividsolutions.jts.geom.Geometry newGeom = listResult.size() > 0 ? listResult.get(0) : null;
430
        while (listResult.size() > 1) {
431
            List<com.vividsolutions.jts.geom.Geometry> list = new ArrayList<com.vividsolutions.jts.geom.Geometry>();
432
            for (int i = 0; i < listResult.size(); i = i + 2) {
433
                if (i == (listResult.size() - 1)) {
434
                    list.add(listResult.get(i));
435
                } else {
436
                    newGeom = JTSFacade.union(listResult.get(i), listResult.get(i + 1));
437
                    list.add(newGeom);
438
                }
439
            }
440
            listResult = list;
441
        }
442
        return GeometryUtil.jtsToGeom(newGeom);
443
    }
444

  
445
    private Double updateAny(Double min, Object value) {
446
        if (value instanceof Double) {
447
            return (Double) value;
448
        } else if (value instanceof Integer) {
449
            return ((Integer) value).doubleValue();
450
        }
451
        return min;
452
    }
453

  
454
    private Object updateMinimum(Object min, Object value) {
455
        if (value instanceof Comparable && min instanceof Comparable && CompareUtils.compare((Comparable)value, (Comparable)min) < 0) {
456
            return value;
457
        }
458
        return min;
459
    }
460

  
461
    private Object updateMaximum(Object max, Object value) {
462
        if (value instanceof Comparable && max instanceof Comparable && CompareUtils.compare((Comparable)value, (Comparable)max) > 0) {
463
            return value;
464
        }
465
        return max;
466
    }
467

  
468
    private Object sum(Object current, Object value) {
469
        if(!(current instanceof Number) || !(value instanceof Number)){
470
            return current;
471
        }
472
        if(current instanceof Double || value instanceof Double){
473
            return ((Number) value).doubleValue() + ((Number)current).doubleValue();
474
        }
475
        if(current instanceof Float || value instanceof Float){
476
            return ((Number) value).floatValue()+ ((Number)current).floatValue();
477
        }
478
        return ((Number) value).longValue()+ ((Number)current).longValue();
479
    }
480

  
481
    /**
482
     * Gets the list of grouped values
483
     *
484
     * @param featureStore
485
     * @param groupByField
486
     * @return
487
     * @throws DataException
488
     */
489
    private Set<Object> getGroupedValues(FeatureStore featureStore, String groupByField) throws DataException {
490
        Set<Object> valueGrouped = new HashSet<>();
491
        FeatureSet featureSet = featureStore.getFeatureSet();
492
        Iterator it = featureSet.iterator();
493
        while (it.hasNext()) {
494
            Feature feature = (Feature) it.next();
495
            Object obj = feature.get(groupByField);
496
            valueGrouped.add(obj);
497
//            String s = null;
498
//            if (obj instanceof String) {
499
//                s = new String(((String) obj));
500
//            } else if (obj instanceof Double) {
501
//                s = String.valueOf((Double) obj);
502
//            } else if (obj instanceof Integer) {
503
//                s = String.valueOf((Integer) obj);
504
//            } else if (obj instanceof Float) {
505
//                s = String.valueOf((Float) obj);
506
//            } else if (obj instanceof Boolean) {
507
//                s = String.valueOf((Boolean) obj);
508
//            } else if (obj instanceof Long) {
509
//                s = String.valueOf((Long) obj);
510
//            } else if (obj instanceof Byte) {
511
//                s = String.valueOf((Byte) obj);
512
//            } else if (obj instanceof Date) {
513
//                s = ((Date) obj).toString();
514
//            }
515
//            if (valueGrouped.get(s) == null) {
516
//                valueGrouped.put(s, s);
517
//            }
518
        }
483 519
//		it.dispose();
484
		featureSet.dispose();
485
		return valueGrouped.keySet();
486
	}
487
	
520
        featureSet.dispose();
521
        return valueGrouped; //.keySet();
522
    }
523

  
488 524
    /**
489 525
     * Builds the output FeatureStore
490
     * 
526
     *
491 527
     * @param featureType
492 528
     * @return FeatureStore
493 529
     */
494 530
    private FeatureStore buildOutPutStore(FeatureType featureType,
495
    		String sextanteLayerName,
496
    		String groupByField,
497
    		String[] fieldList,
498
    		String[] funcList,
499
    		int geomOption,
500
    		int inputShapeType) {
501
    	int len = fieldList != null ? fieldList.length + 2 : 2;
502
    	
531
            String sextanteLayerName,
532
            String groupByField,
533
            String[] fieldList,
534
            String[] funcList,
535
            int geomOption,
536
            int inputShapeType) {
537
        int len = fieldList != null ? fieldList.length + 2 : 2;
538

  
503 539
        Class<?>[] types = new Class[len];
504 540
        attrNames = new String[len];
505 541

  
506 542
        FeatureAttributeDescriptor desc = featureType.getAttributeDescriptor(groupByField);
507 543
        attrNames[0] = desc.getName();
508 544
        types[0] = desc.getObjectClass();
509
        
510
        if(fieldList != null) {
511
        	for (int i = 1; i < attrNames.length - 1; i++) {
512
        		desc = featureType.getAttributeDescriptor(fieldList[i - 1]);
513
        		attrNames[i] = desc.getName();
514
        		if(attrNames[i].length() >= 6)
515
        			attrNames[i] = attrNames[i].substring(0, 5);
516
        		attrNames[i] += "_" + funcList[i - 1];
517
        		types[i] = desc.getObjectClass(); 
518
        	}
545

  
546
        if (fieldList != null) {
547
            NamesTranslator nTranslator = NamesTranslator.createTrimTranslator(10);
548
            for (int i = 1; i < attrNames.length - 1; i++) {
549
                desc = featureType.getAttributeDescriptor(fieldList[i - 1]);
550
                switch(funcList[i-1].toLowerCase()){
551
                    case "max": 
552
                        nTranslator.addSource("max_"+desc.getName());
553
                        break;
554
                    case "min": 
555
                        nTranslator.addSource("min_"+desc.getName());
556
                        break;
557
                    case "first": 
558
                        nTranslator.addSource("fst_"+desc.getName());
559
                        break;
560
                    case "average": 
561
                        nTranslator.addSource("avg_"+desc.getName());
562
                        break;
563
                    case "sum": 
564
                        nTranslator.addSource("sum_"+desc.getName());
565
                        break;
566
                    case "last": 
567
                        nTranslator.addSource("lst_"+desc.getName());
568
                        break;
569
                }
570
            }
571
            for (int i = 1; i < attrNames.length - 1; i++) {
572
                desc = featureType.getAttributeDescriptor(fieldList[i - 1]);
573
                switch(funcList[i-1].toLowerCase()){
574
                    case "min": 
575
                        attrNames[i] = nTranslator.getTranslation("min_"+desc.getName());
576
                        types[i] = desc.getObjectClass();
577
                        break;
578
                    case "max": 
579
                        attrNames[i] = nTranslator.getTranslation("max_"+desc.getName());
580
                        types[i] = desc.getObjectClass();
581
                        break;
582
                    case "first": 
583
                        attrNames[i] = nTranslator.getTranslation("fst_"+desc.getName());
584
                        types[i] = desc.getObjectClass();
585
                        break;
586
                    case "last": 
587
                        attrNames[i] = nTranslator.getTranslation("lst_"+desc.getName());
588
                        types[i] = desc.getObjectClass();
589
                        break;
590
                    case "sum": 
591
                        attrNames[i] = nTranslator.getTranslation("sum_"+desc.getName());
592
                        if(Double.class.isAssignableFrom(desc.getObjectClass())){
593
                            types[i] = Double.class;
594
                        } else if(Float.class.isAssignableFrom(desc.getObjectClass())) {
595
                            types[i] = Double.class;
596
                        } else if(Number.class.isAssignableFrom(desc.getObjectClass())) {
597
                            types[i] = Long.class;
598
                        } else {
599
                            types[i] = desc.getObjectClass();
600
                        }
601
                        break;
602
                    case "average": 
603
                        attrNames[i] = nTranslator.getTranslation("avg_"+desc.getName());
604
                        types[i] = Double.class;
605
                        break;
606
                }
607
            }
519 608
        }
520
        
609

  
521 610
        attrNames[attrNames.length - 1] = featureType.getDefaultGeometryAttributeName();
522 611
        types[types.length - 1] = featureType.getDefaultGeometryAttribute().getObjectClass();
523
        
612

  
524 613
        for (int i = 0; i < types.length; i++) {
525
			if(Time.class.isAssignableFrom(types[i])) {
526
				types[i] = Date.class;
527
			}
528
		}
529
        
614
            if (Time.class.isAssignableFrom(types[i])) {
615
                types[i] = Date.class;
616
            }
617
        }
618

  
530 619
        try {
531 620
            IVectorLayer output = getNewVectorLayer(RESULT, sextanteLayerName,
532
            		inputShapeType, types, attrNames);
621
                    inputShapeType, types, attrNames);
533 622
            return ((FlyrVectIVectorLayer) output).getFeatureStore();
534 623
        } catch (UnsupportedOutputChannelException e) {
535 624
            Sextante.addErrorToLog(e);
......
538 627
        }
539 628
        return null;
540 629
    }
541
    
630

  
542 631
    /**
543
     * Gets the list of fields index to add to the table. 
632
     * Gets the list of fields index to add to the table.
633
     *
544 634
     * @param fieldsString
545 635
     * @return
546 636
     */
547
	private int[] getFieldList(String fieldsString) {
548
		String[] list = fieldsString.split(";");
549
		int[] l = new int[list.length];
550
		for (int i = 0; i < list.length; i++) {
551
			try {
552
				l[i] = new Integer(list[i]);
553
			} catch (NumberFormatException e) {
554
				return null;
555
			}
556
		}
557
		return l;
558
	}
559
	
637
    private int[] getFieldList(String fieldsString) {
638
        String[] list = fieldsString.split(";");
639
        int[] l = new int[list.length];
640
        for (int i = 0; i < list.length; i++) {
641
            try {
642
                l[i] = new Integer(list[i]);
643
            } catch (NumberFormatException e) {
644
                return null;
645
            }
646
        }
647
        return l;
648
    }
649

  
560 650
    @Override
561 651
    public Class<? extends GeoAlgorithmParametersPanel> getCustomParametersPanelClass() {
562 652
        return GroupByParametersPanel.class;

Also available in: Unified diff