Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.file / org.gvsig.fmap.dal.file.csv / src / main / java / org / gvsig / fmap / dal / store / csv / CSVStoreProvider.java @ 44947

History | View | Annotate | Download (46.4 KB)

1 40846 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6 42775 jjdelcerro
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10 40846 jjdelcerro
 *
11 42775 jjdelcerro
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15 40846 jjdelcerro
 *
16 42775 jjdelcerro
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 40846 jjdelcerro
 *
20 42775 jjdelcerro
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22 40846 jjdelcerro
 */
23
package org.gvsig.fmap.dal.store.csv;
24
25
import java.io.File;
26 43283 jjdelcerro
import java.io.FileInputStream;
27
import java.io.FileNotFoundException;
28 40846 jjdelcerro
import java.io.FileReader;
29
import java.io.IOException;
30 43283 jjdelcerro
import java.io.InputStreamReader;
31 43425 jjdelcerro
import java.net.URI;
32 41062 jjdelcerro
import java.net.URL;
33 43283 jjdelcerro
import java.nio.charset.Charset;
34 40846 jjdelcerro
import java.util.ArrayList;
35
import java.util.HashMap;
36 41006 jjdelcerro
import java.util.Iterator;
37 40846 jjdelcerro
import java.util.List;
38 41069 jjdelcerro
import java.util.Locale;
39 44408 jjdelcerro
import java.util.Map;
40 40846 jjdelcerro
41 41006 jjdelcerro
import org.apache.commons.io.FilenameUtils;
42 42775 jjdelcerro
import org.apache.commons.io.IOUtils;
43 41876 jjdelcerro
import org.apache.commons.lang3.StringUtils;
44 40846 jjdelcerro
import org.cresques.cts.IProjection;
45
import org.gvsig.fmap.dal.DALLocator;
46
import org.gvsig.fmap.dal.DataManager;
47
import org.gvsig.fmap.dal.DataServerExplorer;
48
import org.gvsig.fmap.dal.DataStore;
49
import org.gvsig.fmap.dal.DataStoreNotification;
50
import org.gvsig.fmap.dal.DataTypes;
51
import org.gvsig.fmap.dal.FileHelper;
52
import org.gvsig.fmap.dal.exception.DataException;
53
import org.gvsig.fmap.dal.exception.InitializeException;
54
import org.gvsig.fmap.dal.exception.OpenException;
55
import org.gvsig.fmap.dal.exception.ReadException;
56
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
57 41335 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeature;
58 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
59 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureType;
60 41059 jjdelcerro
import org.gvsig.fmap.dal.feature.Feature;
61 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
62 41335 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
63 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureSet;
64 41059 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStore;
65 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
66 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
67 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
68
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
69
import org.gvsig.fmap.dal.feature.spi.memory.AbstractMemoryStoreProvider;
70 41006 jjdelcerro
import org.gvsig.fmap.dal.resource.ResourceAction;
71 40846 jjdelcerro
import org.gvsig.fmap.dal.resource.file.FileResource;
72
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
73
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
74
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
75
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
76
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
77 44936 jjdelcerro
import org.gvsig.fmap.dal.store.csv.AutomaticDetectionOfTypes.DetectedValue;
78 41617 jjdelcerro
import org.gvsig.fmap.dal.store.csv.simplereaders.CSVReader;
79
import org.gvsig.fmap.dal.store.csv.simplereaders.FixedLenReader;
80
import org.gvsig.fmap.dal.store.csv.simplereaders.SimpleReader;
81 40846 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
82
import org.gvsig.fmap.geom.GeometryLocator;
83
import org.gvsig.fmap.geom.GeometryManager;
84 44408 jjdelcerro
import org.gvsig.fmap.geom.GeometryUtils;
85 41335 jjdelcerro
import org.gvsig.fmap.geom.aggregate.MultiPoint;
86 40846 jjdelcerro
import org.gvsig.fmap.geom.primitive.Envelope;
87 41006 jjdelcerro
import org.gvsig.fmap.geom.primitive.Point;
88
import org.gvsig.fmap.geom.type.GeometryType;
89 40846 jjdelcerro
import org.gvsig.tools.ToolsLocator;
90 41335 jjdelcerro
import org.gvsig.tools.dataTypes.DataType;
91 41006 jjdelcerro
import org.gvsig.tools.dataTypes.DataTypesManager;
92 44669 jjdelcerro
import org.gvsig.tools.dataTypes.Coercion;
93 41006 jjdelcerro
import org.gvsig.tools.dispose.DisposableIterator;
94 44408 jjdelcerro
import org.gvsig.tools.dynobject.Tags;
95 40846 jjdelcerro
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
96 41006 jjdelcerro
import org.gvsig.tools.evaluator.AbstractEvaluator;
97
import org.gvsig.tools.evaluator.EvaluatorData;
98
import org.gvsig.tools.evaluator.EvaluatorException;
99 41059 jjdelcerro
import org.gvsig.tools.exception.BaseException;
100 40846 jjdelcerro
import org.gvsig.tools.exception.NotYetImplemented;
101
import org.gvsig.tools.persistence.PersistentState;
102
import org.gvsig.tools.persistence.exception.PersistenceException;
103
import org.gvsig.tools.task.SimpleTaskStatus;
104
import org.gvsig.tools.task.TaskStatusManager;
105 41059 jjdelcerro
import org.gvsig.tools.visitor.VisitCanceledException;
106
import org.gvsig.tools.visitor.Visitor;
107 40846 jjdelcerro
import org.slf4j.Logger;
108
import org.slf4j.LoggerFactory;
109 40878 jjdelcerro
import org.supercsv.prefs.CsvPreference;
110 44669 jjdelcerro
import org.gvsig.tools.dataTypes.CoercionContext;
111 40846 jjdelcerro
112 44309 omartinez
@SuppressWarnings("UseSpecificCatch")
113 40846 jjdelcerro
public class CSVStoreProvider extends AbstractMemoryStoreProvider implements
114 41617 jjdelcerro
        ResourceConsumer {
115
116 44408 jjdelcerro
    private static final Logger LOGGER = LoggerFactory.getLogger(CSVStoreProvider.class);
117 40846 jjdelcerro
118 44669 jjdelcerro
    public static final String NAME = DataStore.CSV_PROVIDER_NAME;
119 40846 jjdelcerro
    public static final String DESCRIPTION = "CSV file";
120
121
    public static final String METADATA_DEFINITION_NAME = NAME;
122
123
    private ResourceProvider resource;
124
125
    private long counterNewsOIDs = 0;
126
    private Envelope envelope;
127 41059 jjdelcerro
    private boolean need_calculate_envelope = false;
128 44309 omartinez
    private final SimpleTaskStatus taskStatus;
129
    private final CSVFeatureWriter writer;
130 40846 jjdelcerro
131
    public CSVStoreProvider(CSVStoreParameters parameters,
132 41617 jjdelcerro
            DataStoreProviderServices storeServices) throws InitializeException {
133 40846 jjdelcerro
        super(
134 41617 jjdelcerro
                parameters,
135
                storeServices,
136
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
137 40846 jjdelcerro
        );
138 44309 omartinez
        this.writer = new CSVFeatureWriter();
139 40846 jjdelcerro
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
140
        this.taskStatus = manager.createDefaultSimpleTaskStatus("CSV");
141
142
        counterNewsOIDs = 0;
143
144
        File file = getCSVParameters().getFile();
145
        resource = this.createResource(
146 41617 jjdelcerro
                FileResource.NAME,
147
                new Object[]{file.getAbsolutePath()}
148 40846 jjdelcerro
        );
149
150
        resource.addConsumer(this);
151 44309 omartinez
152 41006 jjdelcerro
        initializeFeatureTypes();
153 40846 jjdelcerro
    }
154
155
    private CSVStoreParameters getCSVParameters() {
156
        return (CSVStoreParameters) this.getParameters();
157
    }
158
159 44309 omartinez
    @Override
160 40846 jjdelcerro
    public String getProviderName() {
161
        return NAME;
162
    }
163
164 44309 omartinez
    @Override
165 40846 jjdelcerro
    public boolean allowWrite() {
166 44309 omartinez
        return true;
167 40846 jjdelcerro
    }
168
169 41006 jjdelcerro
    private String getFullFileName() {
170 41617 jjdelcerro
        // Usar solo para mostrar mensajes en el logger.
171 44309 omartinez
        String s;
172 41617 jjdelcerro
        try {
173
            s = getCSVParameters().getFile().getAbsolutePath();
174
        } catch (Exception e2) {
175
            s = "(unknow)";
176
        }
177
        return s;
178 41006 jjdelcerro
    }
179 41617 jjdelcerro
180 44309 omartinez
    @Override
181 40846 jjdelcerro
    public void open() throws OpenException {
182 42775 jjdelcerro
        if (this.data != null) {
183 40846 jjdelcerro
            return;
184
        }
185 43215 jjdelcerro
        this.data = new ArrayList<>();
186 41006 jjdelcerro
        resource.setData(new HashMap());
187
        counterNewsOIDs = 0;
188 41617 jjdelcerro
        try {
189
            loadFeatures();
190
        } catch (RuntimeException e) {
191 44408 jjdelcerro
            LOGGER.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
192 41617 jjdelcerro
            throw e;
193
        } catch (Exception e) {
194 44408 jjdelcerro
            LOGGER.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
195 41617 jjdelcerro
            throw new RuntimeException(e);
196
        }
197 40846 jjdelcerro
    }
198
199 44309 omartinez
    @Override
200 40846 jjdelcerro
    public DataServerExplorer getExplorer() throws ReadException {
201
        DataManager manager = DALLocator.getDataManager();
202 41006 jjdelcerro
        FilesystemServerExplorerParameters params;
203 40846 jjdelcerro
        try {
204
            params = (FilesystemServerExplorerParameters) manager
205 41617 jjdelcerro
                    .createServerExplorerParameters(FilesystemServerExplorer.NAME);
206 40846 jjdelcerro
            params.setRoot(this.getCSVParameters().getFile().getParent());
207 41617 jjdelcerro
            return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
208 40846 jjdelcerro
        } catch (DataException e) {
209
            throw new ReadException(this.getProviderName(), e);
210
        } catch (ValidateDataParametersException e) {
211
            throw new ReadException(this.getProviderName(), e);
212
        }
213
214
    }
215
216 44309 omartinez
    @Override
217 40846 jjdelcerro
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
218
219
        try {
220
            this.taskStatus.add();
221
            taskStatus.message("_preparing");
222 44309 omartinez
            this.getResource().closeRequest();
223 40846 jjdelcerro
            getResource().execute(new ResourceAction() {
224 44309 omartinez
                @Override
225 40846 jjdelcerro
                public Object run() throws Exception {
226
                    FeatureSet features = null;
227
                    DisposableIterator it = null;
228
                    try {
229
                        File file = (File) resource.get();
230 41617 jjdelcerro
231
                        features
232
                                = getStoreServices().getFeatureStore()
233 44309 omartinez
                                        .getFeatureSet();
234 41006 jjdelcerro
                        List<FeatureProvider> newdata = new ArrayList<FeatureProvider>();
235 44309 omartinez
                        FeatureType ftype = getStoreServices().getDefaultFeatureType();
236
                        writer.initialize(getCSVParameters(), file, ftype, getCSVPreferences());
237 44900 omartinez
                        writer.begin();
238 40846 jjdelcerro
                        it = features.fastIterator();
239 41617 jjdelcerro
                        taskStatus.setRangeOfValues(0, 0);
240
                        long counter = 0;
241 42775 jjdelcerro
                        while (it.hasNext()) {
242 40846 jjdelcerro
                            taskStatus.setCurValue(counter++);
243
                            FeatureProvider feature = getStoreServices().getFeatureProviderFromFeature(
244 41617 jjdelcerro
                                    (org.gvsig.fmap.dal.feature.Feature) it.next());
245 40846 jjdelcerro
                            writer.add(feature);
246 42775 jjdelcerro
                            if (feature.getOID() == null) {
247 44408 jjdelcerro
                                LOGGER.warn("feature without OID");
248 40846 jjdelcerro
                                feature.setOID(createNewOID());
249
                            }
250
                            newdata.add(feature);
251
                        }
252
                        data = newdata;
253 42775 jjdelcerro
                        if (writer.getEnvelope() != null) {
254 40846 jjdelcerro
                            envelope = writer.getEnvelope().getGeometry().getEnvelope();
255
                        }
256
                        resource.notifyChanges();
257 41006 jjdelcerro
                        writer.end();
258 40846 jjdelcerro
                    } finally {
259 42775 jjdelcerro
                        if (it != null) {
260 40846 jjdelcerro
                            it.dispose();
261
                        }
262 42775 jjdelcerro
                        if (features != null) {
263 40846 jjdelcerro
                            features.dispose();
264
                        }
265
                    }
266
                    return null;
267
                }
268 41617 jjdelcerro
269 40846 jjdelcerro
            });
270
            this.taskStatus.terminate();
271
        } catch (Exception e) {
272
            this.taskStatus.abort();
273
            throw new PerformEditingException(getResource().toString(), e);
274
        } finally {
275
            this.taskStatus.remove();
276
        }
277
    }
278
279 44309 omartinez
    private CsvPreference getCSVPreferences() {
280
        CSVReader reader = new CSVReader(getCSVParameters());
281
        return reader.getCSVPreferences();
282
    }
283
284
    @Override
285 40846 jjdelcerro
    public boolean closeResourceRequested(ResourceProvider resource) {
286
        return true;
287
    }
288
289 44309 omartinez
    @Override
290 40846 jjdelcerro
    public int getOIDType() {
291
        return DataTypes.LONG;
292
    }
293
294 44309 omartinez
    @Override
295 40846 jjdelcerro
    public boolean supportsAppendMode() {
296 44309 omartinez
        return true;
297 40846 jjdelcerro
    }
298
299 44309 omartinez
    @Override
300
    public void append(final FeatureProvider featureProvider) {
301
        //todo
302
        getResource().execute(new ResourceAction() {
303
            @Override
304
            public Object run() throws Exception {
305
                //writer.append(getStoreServices().createFeature(featureProvider));
306
                writer.add(featureProvider);
307
                return null;
308
            }
309
        });
310 40846 jjdelcerro
    }
311
312 44309 omartinez
    @Override
313
    public void beginAppend() throws DataException {
314
        this.close();
315
        getResource().execute(new ResourceAction() {
316
            public Object run() throws Exception {
317
                writer.initialize(
318
                        getCSVParameters(),
319
                        getCSVParameters().getFile(),
320
                        getFeatureStore().getDefaultFeatureType(),
321 44388 omartinez
                        getCSVPreferences()
322 44309 omartinez
                );
323
                writer.beginAppend();
324
                return null;
325
            }
326
        });
327
328 40846 jjdelcerro
    }
329
330 44309 omartinez
    @Override
331 40846 jjdelcerro
    public void endAppend() {
332 44309 omartinez
        try {
333
            getResource().execute(new ResourceAction() {
334
                public Object run() throws Exception {
335
                    writer.end();
336
                    resource.notifyChanges(); //resourcesNotifyChanges();
337
                    counterNewsOIDs = -1;
338
                    return null;
339
                }
340
            });
341
            writer.end();
342
        } catch (PerformEditingException ex) {
343 44408 jjdelcerro
            LOGGER.warn("Not been able to end append '" + this.getFullName() + "'.", ex);
344 44309 omartinez
        }
345 40846 jjdelcerro
    }
346
347
    public void saveToState(PersistentState state) throws PersistenceException {
348
        throw new NotYetImplemented();
349
    }
350
351
    public void loadFromState(PersistentState state) throws PersistenceException {
352
        throw new NotYetImplemented();
353
    }
354
355 44309 omartinez
    @Override
356 40846 jjdelcerro
    public Object createNewOID() {
357 44309 omartinez
        return counterNewsOIDs++;
358 40846 jjdelcerro
    }
359
360
    protected void initializeFeatureTypes() throws InitializeException {
361
        try {
362
            this.open();
363
        } catch (OpenException e) {
364
            throw new InitializeException(this.getProviderName(), e);
365
        }
366
    }
367
368 44309 omartinez
    @Override
369 40846 jjdelcerro
    public Envelope getEnvelope() throws DataException {
370
        this.open();
371 42775 jjdelcerro
        if (this.envelope != null) {
372 41617 jjdelcerro
            return this.envelope;
373 41059 jjdelcerro
        }
374 42775 jjdelcerro
        if (!this.need_calculate_envelope) {
375 41617 jjdelcerro
            return null;
376 41059 jjdelcerro
        }
377
        FeatureStore fs = this.getFeatureStore();
378
        FeatureType ft = fs.getDefaultFeatureType();
379
        FeatureAttributeDescriptor fad = ft.getAttributeDescriptor(ft.getDefaultGeometryAttributeIndex());
380
381
        try {
382
            this.envelope = GeometryLocator.getGeometryManager().createEnvelope(fad.getGeomType().getSubType());
383 41617 jjdelcerro
            fs.accept(new Visitor() {
384 44309 omartinez
                @Override
385 41617 jjdelcerro
                public void visit(Object obj) throws VisitCanceledException, BaseException {
386
                    Feature f = (Feature) obj;
387
                    Geometry geom = f.getDefaultGeometry();
388 42775 jjdelcerro
                    if (geom != null) {
389 41617 jjdelcerro
                        envelope.add(geom.getEnvelope());
390
                    }
391
                }
392
            });
393
        } catch (BaseException e) {
394 44408 jjdelcerro
            LOGGER.warn("Can't calculate the envelope of CSV file '" + this.getFullName() + "'.", e);
395 41617 jjdelcerro
            this.envelope = null;
396
        }
397
398 41059 jjdelcerro
        this.need_calculate_envelope = false;
399 40846 jjdelcerro
        return this.envelope;
400
    }
401
402 44309 omartinez
    @Override
403 40846 jjdelcerro
    public Object getDynValue(String name) throws DynFieldNotFoundException {
404 42775 jjdelcerro
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
405 40846 jjdelcerro
            try {
406
                return this.getEnvelope();
407
            } catch (DataException e) {
408
                return null;
409
            }
410
        } else {
411 42775 jjdelcerro
            if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
412 40878 jjdelcerro
                IProjection pro = CSVStoreParameters.getCRS(this.getCSVParameters());
413 42775 jjdelcerro
                if (pro != null) {
414 40846 jjdelcerro
                    return pro;
415
                }
416
            }
417
        }
418
        return super.getDynValue(name);
419
    }
420
421 44309 omartinez
    @Override
422 40846 jjdelcerro
    public void resourceChanged(ResourceProvider resource) {
423
        this.getStoreServices().notifyChange(
424 41617 jjdelcerro
                DataStoreNotification.RESOURCE_CHANGED,
425
                resource);
426 40846 jjdelcerro
    }
427
428 44309 omartinez
    @Override
429 40846 jjdelcerro
    public Object getSourceId() {
430
        return this.getCSVParameters().getFile();
431
    }
432
433 44309 omartinez
    @Override
434 40846 jjdelcerro
    public String getName() {
435 40878 jjdelcerro
        String name = this.getCSVParameters().getFile().getName();
436 41006 jjdelcerro
        return FilenameUtils.getBaseName(name);
437 40846 jjdelcerro
    }
438
439 44309 omartinez
    @Override
440 40846 jjdelcerro
    public String getFullName() {
441
        return this.getCSVParameters().getFile().getAbsolutePath();
442
    }
443
444 44309 omartinez
    @Override
445 40846 jjdelcerro
    public ResourceProvider getResource() {
446
        return resource;
447
    }
448
449
    private boolean isEmpty(String s) {
450 42775 jjdelcerro
        if (s == null) {
451 41617 jjdelcerro
            return true;
452
        }
453
        return s.trim().length() == 0;
454 40846 jjdelcerro
    }
455 40878 jjdelcerro
456 44309 omartinez
    private void init(CSVStoreParameters parameters, DataStoreProviderServices storeServices) {
457
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
458
    }
459 44941 jjdelcerro
460
    public static class FieldTypeParser {
461 41617 jjdelcerro
462 41335 jjdelcerro
        public String name = null;
463
        public int type = DataTypes.STRING;
464
        public int size = 0;
465 44408 jjdelcerro
        public int geomType = Geometry.TYPES.GEOMETRY;
466
        public int geomSubtype = Geometry.SUBTYPES.GEOM2D;
467
        public Map<String,String> tags = new HashMap<>();
468
        public Map<String,String> assignments = new HashMap<>();
469 44936 jjdelcerro
470
        // Valores obtenidos desde la deteccion automatica desde los datos
471
        public DetectedValue detectedValue = null ;
472 41335 jjdelcerro
473
        private String typename = "string";
474 41617 jjdelcerro
475 44941 jjdelcerro
        private final String fullFileName;
476
        private final String providerName;
477
478
        FieldTypeParser(String providerName, String fullFileName) {
479
            this.providerName = providerName;
480
            this.fullFileName = fullFileName;
481 41335 jjdelcerro
        }
482 41617 jjdelcerro
483 44941 jjdelcerro
        public String getProviderName() {
484
            return this.providerName;
485
        }
486
487
        public String getFullFileName() {
488
            return this.fullFileName;
489
        }
490
491 44408 jjdelcerro
        public void clear() {
492
            this.name = null;
493
            this.type = DataTypes.STRING;
494
            this.size = 0;
495
            this.tags = new HashMap<>();
496
            this.assignments = new HashMap<>();
497
        }
498
499
        public void copyFrom(FieldTypeParser other) {
500
            this.name = other.name;
501
            this.type = other.type;
502
            this.size = other.size;
503
            this.tags = new HashMap<>();
504
            this.tags.putAll(other.tags);
505
            this.assignments = new HashMap<>();
506
            this.assignments.putAll(other.assignments);
507
        }
508
509 41335 jjdelcerro
        private int getType(String value) {
510 41617 jjdelcerro
            DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
511 41335 jjdelcerro
            return dataTypesManager.getType(typename);
512
        }
513 41617 jjdelcerro
514 44408 jjdelcerro
        private String[] split(String value, String separators) {
515
            int firstSeparatorPosition = 1000000;
516
            Character sep = null;
517
            for (char ch : separators.toCharArray()) {
518
                int pos = value.indexOf(ch);
519
                if( pos>0 && pos<firstSeparatorPosition ) {
520
                    sep = ch;
521
                    firstSeparatorPosition = pos;
522
                }
523
            }
524
            if( sep == null ) {
525
                return new String[] { value };
526
            }
527
            return value.split("["+sep+"]");
528 42775 jjdelcerro
        }
529
530 44408 jjdelcerro
        @SuppressWarnings("UseSpecificCatch")
531 41335 jjdelcerro
        public boolean parse(String value) {
532 44408 jjdelcerro
            String[] args;
533
            if ( value.contains("__") ) {
534
                args = value.split("__");
535
            } else {
536
                args = split(value, ":/#@!;-");
537
                if( args.length == 1 ) {
538
                    this.name = value;
539
                    return true;
540
                }
541
            }
542
            int n = 0;
543 44445 jjdelcerro
            this.name = StringUtils.trim(args[n++]);
544 44408 jjdelcerro
            if( n >= args.length ) {
545 41335 jjdelcerro
                return true;
546
            }
547 44445 jjdelcerro
            this.typename = StringUtils.trim(args[n++]);
548 44408 jjdelcerro
            this.type = this.getType(this.typename);
549
            if ( this.type == DataTypes.INVALID ) {
550
                this.geomType = GeometryUtils.getGeometryType(this.typename);
551
                if( this.geomType==Geometry.TYPES.UNKNOWN )  {
552
                    this.type = DataTypes.STRING;
553
                    LOGGER.info("Type '" + this.typename + "' not valid for attribute '" + value + "' in '"+getProviderName()+"' file '" + getFullFileName() + "'.");
554
                } else {
555
                    this.typename = "GEOMETRY";
556
                    this.type = DataTypes.GEOMETRY;
557
                }
558
            }
559 44669 jjdelcerro
            this.size = 0;
560 44498 omartinez
561 44408 jjdelcerro
            while (n < args.length) {
562 44445 jjdelcerro
                String option = StringUtils.trim(args[n++].toLowerCase());
563 44408 jjdelcerro
                switch (option) {
564
                    case "size":
565
                        try {
566
                            this.size = Integer.parseInt(args[n++]);
567
                        } catch (Exception ex) {
568
                            LOGGER.warn("Ignore incorrect field size for field " + value + " in '"+getProviderName()+"' file '" + getFullFileName() + "'.", ex);
569 42775 jjdelcerro
                        }
570 44408 jjdelcerro
                        break;
571
                    case "tag": {
572 44445 jjdelcerro
                            String x = StringUtils.trim(args[n++]);
573 44408 jjdelcerro
                            int pos = x.indexOf("=");
574
                            if( pos < 0 ) {
575
                                this.tags.put(x, null);
576
                            } else {
577
                                this.tags.put(
578 44445 jjdelcerro
                                        StringUtils.trim(StringUtils.substring(x, 0, pos)),
579
                                        StringUtils.trim(StringUtils.substring(x, pos+1))
580 44408 jjdelcerro
                                );
581
                            }
582
                            break;
583 42775 jjdelcerro
                        }
584 44408 jjdelcerro
                    case "set": {
585 44445 jjdelcerro
                            String x = StringUtils.trim(args[n++]);
586 44408 jjdelcerro
                            int pos = x.indexOf("=");
587
                            if( pos < 0 ) {
588
                                this.assignments.put(x, null);
589
                            } else {
590
                                this.assignments.put(
591 44445 jjdelcerro
                                        StringUtils.trim(StringUtils.substring(x, 0, pos)),
592
                                        StringUtils.trim(StringUtils.substring(x, pos+1))
593 44408 jjdelcerro
                                );
594 42775 jjdelcerro
                            }
595 44408 jjdelcerro
                            break;
596 41876 jjdelcerro
                        }
597 44408 jjdelcerro
                    default:
598 44738 jjdelcerro
                        if( StringUtils.isNumeric(option) && this.size == 0 ) {
599
                          try {
600
                              this.size = Integer.parseInt(option);
601
                          } catch (Exception ex) {
602
                              LOGGER.warn("Ignore incorrect field size for field " + value + " in '"+getProviderName()+"' file '" + getFullFileName() + "'.", ex);
603
                          }
604
                          break;
605
                        }
606 44408 jjdelcerro
                        LOGGER.warn("Illegal argumente '"+option+"' for field '"+this.name+"' in '"+getProviderName()+"' file '" + getFullFileName() + "' ("+value+").");
607
                }
608 41335 jjdelcerro
            }
609
            return true;
610
        }
611 41617 jjdelcerro
612 41335 jjdelcerro
    }
613 41617 jjdelcerro
614 44936 jjdelcerro
    private EditableFeatureType getFeatureType(String headers[], AutomaticDetectionOfTypes.DetectedValue automaticTypes[]) {
615 41335 jjdelcerro
        EditableFeatureType fType = getStoreServices().createFeatureType(this.getName());
616
        fType.setHasOID(true);
617
618
        FieldTypeParser[] fieldTypes = new FieldTypeParser[headers.length];
619 41617 jjdelcerro
        //
620 41335 jjdelcerro
        // Calculamos cuales pueden ser los tipos de datos
621
        //
622 42775 jjdelcerro
        for (int i = 0; i < fieldTypes.length; i++) {
623 44941 jjdelcerro
            fieldTypes[i] = new FieldTypeParser(getProviderName(), getFullFileName());
624 41335 jjdelcerro
        }
625
626 41617 jjdelcerro
        // Asuminos los tipos pasados por parametro, que se supone
627 41335 jjdelcerro
        // son los detectados automaticamente.
628 42775 jjdelcerro
        if (automaticTypes != null) {
629
            for (int i = 0; i < fieldTypes.length && i < automaticTypes.length; i++) {
630 44936 jjdelcerro
                fieldTypes[i].detectedValue = automaticTypes[i];
631
                fieldTypes[i].type = automaticTypes[i].getType();
632 41335 jjdelcerro
            }
633
        }
634
        // Luego probamos con lo que diga las cabezeras del CVS, sobreescribiendo
635
        // los tipos anteriores en caso de definirse en la cabezara.
636 42775 jjdelcerro
        for (int i = 0; i < fieldTypes.length; i++) {
637
            if (!fieldTypes[i].parse(headers[i])) {
638 41335 jjdelcerro
                continue;
639
            }
640
641
        }
642
643 41617 jjdelcerro
        // Y por ultimo hacemos caso a lo que se haya especificado en los parametros
644 41335 jjdelcerro
        // de apertura del CSV, teniendo esto prioridad sobre todo.
645 41876 jjdelcerro
        String param_types_def = CSVStoreParameters.getRawFieldTypes(this.getParameters());
646 41901 jjdelcerro
        if (StringUtils.isNotBlank(param_types_def)) {
647
            String sep = CSVStoreParameters.getDelimiter(param_types_def);
648 42775 jjdelcerro
            if (StringUtils.isNotBlank(sep)) {
649 41901 jjdelcerro
                String[] param_types = param_types_def.split(sep);
650 44941 jjdelcerro
                FieldTypeParser parser = new FieldTypeParser(getProviderName(), getFullFileName());
651 42775 jjdelcerro
                for (String param_type : param_types) {
652
                    parser.clear();
653
                    parser.parse(param_type);
654
                    for (FieldTypeParser fieldType : fieldTypes) {
655
                        if (StringUtils.equalsIgnoreCase(fieldType.name, parser.name)) {
656
                            fieldType.copyFrom(parser);
657
                            break;
658
                        }
659 41901 jjdelcerro
                    }
660 41335 jjdelcerro
                }
661
            }
662
        }
663 41617 jjdelcerro
        //
664 41335 jjdelcerro
        // Una vez ya sabemos los tipos de datos rellenamos el feature-type
665
        //
666 44408 jjdelcerro
        for (FieldTypeParser fieldType : fieldTypes) {
667
            EditableFeatureAttributeDescriptor fad = fType.add(fieldType.name, fieldType.type);
668 44941 jjdelcerro
            if( fieldType.detectedValue!=null ) {
669 44947 jjdelcerro
                fad.setDisplaySize(Math.max(fieldType.detectedValue.getDisplaySize(), fieldType.size));
670 44941 jjdelcerro
                fad.setSize(Math.max(fieldType.detectedValue.getDisplaySize(), fieldType.size));
671
                if( fad.getPrecision()<fieldType.detectedValue.getPrecision() ) {
672
                    fad.setPrecision(fieldType.detectedValue.getPrecision());
673
                }
674
                if( fad.getScale()<fieldType.detectedValue.getScale()) {
675
                    fad.setScale(fieldType.detectedValue.getScale());
676
                }
677
            } else {
678 44947 jjdelcerro
                fad.setDisplaySize(fieldType.size);
679 44936 jjdelcerro
            }
680 44408 jjdelcerro
            if (fieldType.type == DataTypes.GEOMETRY ) {
681
                fad.setGeometryType(fieldType.geomType, fieldType.geomSubtype);
682
                if( fType.getDefaultGeometryAttributeName() == null ) {
683
                    fType.setDefaultGeometryAttributeName(fieldType.name);
684 41876 jjdelcerro
                }
685 41335 jjdelcerro
            }
686 44894 omartinez
            Locale locale = CSVStoreParameters.getLocale(this.getParameters());
687
            fad.setLocale(locale);
688 44408 jjdelcerro
            for (Map.Entry<String, String> entry : fieldType.assignments.entrySet()) {
689
                try {
690
                    switch(entry.getKey().toLowerCase()) {
691
                        case "expression":
692
                            // Los campos calculados los procesamos en una segunda
693
                            // pasada, cuando ya estan definidos el resto de los campos
694
                            // ya que pueden requerir campos que aun no se han definido.
695
                            break;
696
                        default:
697
                            fad.set(entry.getKey(), entry.getValue());
698
                    }
699
                } catch (Exception ex) {
700
                    LOGGER.warn("Can't set property '"+entry.getKey()+"' of '"+fad.getName()+"'.", ex);
701
                }
702 44894 omartinez
            }
703 44408 jjdelcerro
            Tags tags = fad.getTags();
704
            for (Map.Entry<String, String> entry : fieldType.tags.entrySet()) {
705
                tags.set(entry.getKey(), entry.getValue());
706
            }
707 41335 jjdelcerro
        }
708 44408 jjdelcerro
        // Processamos ahora los campos calculados
709
        for (FieldTypeParser fieldType : fieldTypes) {
710
            EditableFeatureAttributeDescriptor fad = fType.getEditableAttributeDescriptor(fieldType.name);
711
            for (Map.Entry<String, String> entry : fieldType.assignments.entrySet()) {
712
                try {
713
                    switch(entry.getKey().toLowerCase()) {
714
                        case "expression":
715
                            fad.set(entry.getKey(), entry.getValue());
716
                            break;
717
                    }
718
                } catch (Exception ex) {
719
                    LOGGER.warn("Can't set property '"+entry.getKey()+"' in '"+fad.getName()+"' of '"+getFullFileName()+"'.", ex);
720
                }
721
            }
722
        }
723 41335 jjdelcerro
        String[] pointDimensionNames = CSVStoreParameters.getPointDimensionNames(this.getParameters());
724 44408 jjdelcerro
        if ( pointDimensionNames != null ) {
725 41335 jjdelcerro
            PointAttributeEmulator emulator = new PointAttributeEmulator(pointDimensionNames);
726 44936 jjdelcerro
            String columnName = CSVStoreParameters.getPointColumnName(this.getParameters());
727
            if( StringUtils.isBlank(columnName) ) {
728
                columnName = "the_geom";
729
            }
730
            EditableFeatureAttributeDescriptor attr = fType.add(columnName, DataTypes.GEOMETRY, emulator);
731 41335 jjdelcerro
            GeometryManager geommgr = GeometryLocator.getGeometryManager();
732
            GeometryType gt;
733
            try {
734 44408 jjdelcerro
                if ( emulator.fieldNames != null && emulator.fieldNames.length <= 2 ) {
735
                        gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D);
736
                } else {
737
                        gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM3D);
738
                }
739 41335 jjdelcerro
                attr.setGeometryType(gt);
740
            } catch (Exception e) {
741 44408 jjdelcerro
                LOGGER.warn("Can't set geometry type for the calculated field in '"+getProviderName()+"' file '" + getFullFileName() + "'.", e);
742 41335 jjdelcerro
            }
743 44408 jjdelcerro
        }
744
745 43283 jjdelcerro
        String geometry_column = CSVStoreParameters.getGeometryColumn(this.getParameters());
746 44309 omartinez
        if (!StringUtils.isEmpty(geometry_column)) {
747 43283 jjdelcerro
            EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor) fType.get(geometry_column);
748 44309 omartinez
            if (attr != null && attr.getType() != DataTypes.GEOMETRY) {
749 43283 jjdelcerro
                attr.setDataType(DataTypes.GEOMETRY);
750
                GeometryManager geommgr = GeometryLocator.getGeometryManager();
751
                GeometryType gt;
752
                try {
753
                    gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.UNKNOWN);
754
                    attr.setGeometryType(gt);
755
                } catch (Exception e) {
756 44408 jjdelcerro
                    LOGGER.warn("Can't set geometry type for the calculated field in CSV file '" + getFullFileName() + "'.", e);
757 43283 jjdelcerro
                }
758
                fType.setDefaultGeometryAttributeName(geometry_column);
759
            }
760
        }
761 41335 jjdelcerro
        return fType;
762 40846 jjdelcerro
    }
763 41617 jjdelcerro
764 41335 jjdelcerro
    static class PointAttributeEmulator implements FeatureAttributeEmulator {
765
766
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
767
768 41342 jjdelcerro
        private static final int XNAME = 0;
769
        private static final int YNAME = 1;
770
        private static final int ZNAME = 2;
771 41617 jjdelcerro
772 41335 jjdelcerro
        private final GeometryManager geommgr;
773 41342 jjdelcerro
        private final String[] fieldNames;
774 41335 jjdelcerro
        private final Coercion toDouble;
775
        private final DataType dataType;
776
        private int errorcount = 0;
777
778
        public PointAttributeEmulator(String[] pointDimensionNames) {
779 42775 jjdelcerro
            if (pointDimensionNames.length > 2) {
780 41342 jjdelcerro
                this.fieldNames = new String[3];
781
                this.fieldNames[ZNAME] = pointDimensionNames[2];
782 41335 jjdelcerro
            } else {
783 41342 jjdelcerro
                this.fieldNames = new String[2];
784 41335 jjdelcerro
            }
785 41342 jjdelcerro
            this.fieldNames[XNAME] = pointDimensionNames[0];
786
            this.fieldNames[YNAME] = pointDimensionNames[1];
787 41335 jjdelcerro
            this.geommgr = GeometryLocator.getGeometryManager();
788
            DataTypesManager datatypeManager = ToolsLocator.getDataTypesManager();
789
790
            this.toDouble = datatypeManager.getCoercion(DataTypes.DOUBLE);
791
            this.dataType = datatypeManager.get(DataTypes.GEOMETRY);
792
        }
793 41617 jjdelcerro
794 44309 omartinez
        @Override
795 41335 jjdelcerro
        public Object get(Feature feature) {
796
            try {
797 41348 jjdelcerro
                Object valueX = feature.get(this.fieldNames[XNAME]);
798
                valueX = toDouble.coerce(valueX);
799 42775 jjdelcerro
                if (valueX == null) {
800 41348 jjdelcerro
                    return null;
801
                }
802
                Object valueY = feature.get(this.fieldNames[YNAME]);
803
                valueY = toDouble.coerce(valueY);
804 42775 jjdelcerro
                if (valueY == null) {
805 41348 jjdelcerro
                    return null;
806
                }
807
                Object valueZ = null;
808 42775 jjdelcerro
                if (this.fieldNames.length > 2) {
809 41348 jjdelcerro
                    valueZ = toDouble.coerce(feature.get(this.fieldNames[ZNAME]));
810 42775 jjdelcerro
                    if (valueZ == null) {
811 41348 jjdelcerro
                        return null;
812
                    }
813
                }
814 41617 jjdelcerro
815 44309 omartinez
                double x = ((Double) valueX);
816
                double y = ((Double) valueY);
817 41335 jjdelcerro
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
818 42775 jjdelcerro
                if (this.fieldNames.length > 2) {
819 44309 omartinez
                    double z = ((Double) valueZ);
820 41335 jjdelcerro
                    point.setCoordinateAt(2, z);
821
                }
822
                return point;
823
            } catch (Exception ex) {
824 42775 jjdelcerro
                if (++errorcount < 5) {
825 41335 jjdelcerro
                    logger.warn("[" + errorcount + "] Can't create point in CSV provider. XNAME='"
826 41617 jjdelcerro
                            + this.fieldNames[XNAME] + "', YNAME='" + this.fieldNames[XNAME] + "' feature=" + feature.toString(), ex);
827 41335 jjdelcerro
                }
828
                return null;
829
            }
830
        }
831
832
        public void set(EditableFeature feature, Object value) {
833 42775 jjdelcerro
            if (value == null) {
834 41335 jjdelcerro
                return;
835
            }
836
            Point point = null;
837 42775 jjdelcerro
            if (value instanceof MultiPoint) {
838 41617 jjdelcerro
                point = (Point) ((MultiPoint) value).getPrimitiveAt(0);
839 41335 jjdelcerro
            } else {
840
                point = (Point) value;
841
            }
842 41342 jjdelcerro
            feature.set(this.fieldNames[XNAME], point.getX());
843
            feature.set(this.fieldNames[YNAME], point.getY());
844 42775 jjdelcerro
            if (this.fieldNames.length > 2) {
845 41342 jjdelcerro
                feature.set(this.fieldNames[ZNAME], point.getCoordinateAt(2));
846 41335 jjdelcerro
            }
847
        }
848
849 44309 omartinez
        @Override
850 41335 jjdelcerro
        public boolean allowSetting() {
851
            return true;
852
        }
853 41342 jjdelcerro
854 44309 omartinez
        @Override
855 41342 jjdelcerro
        public String[] getRequiredFieldNames() {
856
            return this.fieldNames;
857
        }
858 41617 jjdelcerro
859 41335 jjdelcerro
    }
860 41617 jjdelcerro
861 41006 jjdelcerro
    static class ToPointEvaluaror extends AbstractEvaluator {
862 40846 jjdelcerro
863 41335 jjdelcerro
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
864 40846 jjdelcerro
865 41335 jjdelcerro
        private GeometryManager geommgr = null;
866
        private String xname = null;
867
        private String yname = null;
868
        private String zname = null;
869
        private Coercion toDouble;
870
        private int errorcount = 0;
871
872
        ToPointEvaluaror(String[] pointDimensionNames) {
873
            this.xname = pointDimensionNames[0];
874
            this.yname = pointDimensionNames[1];
875 42775 jjdelcerro
            if (pointDimensionNames.length > 2) {
876 41335 jjdelcerro
                this.zname = pointDimensionNames[2];
877
            }
878
            this.geommgr = GeometryLocator.getGeometryManager();
879
            this.toDouble = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.DOUBLE);
880
        }
881
882 44309 omartinez
        @Override
883 41335 jjdelcerro
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
884
            try {
885
                double x = ((Double) toDouble.coerce(data.getDataValue(xname))).doubleValue();
886
                double y = ((Double) toDouble.coerce(data.getDataValue(yname))).doubleValue();
887
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
888 42775 jjdelcerro
                if (zname != null) {
889 41335 jjdelcerro
                    double z = ((Double) toDouble.coerce(data.getDataValue(zname))).doubleValue();
890
                    point.setCoordinateAt(2, z);
891
                }
892
                return point;
893
            } catch (Exception ex) {
894 42775 jjdelcerro
                if (++errorcount < 5) {
895 41335 jjdelcerro
                    logger.warn("[" + errorcount + "] Can't create point in CSV provider. XNAME='"
896
                            + xname + "', YNAME='" + yname + "', ZNAME='" + zname + "', data=" + data.toString());
897
                }
898
                return null;
899
            }
900
        }
901
902 44309 omartinez
        @Override
903 41335 jjdelcerro
        public String getName() {
904
            return "ToPointEvaluaror";
905
        }
906
907 40846 jjdelcerro
    }
908 41335 jjdelcerro
909 43283 jjdelcerro
    private SimpleReader getSimpleReader(InputStreamReader in) {
910 41617 jjdelcerro
        SimpleReader reader;
911 42775 jjdelcerro
        if (CSVStoreParameters.getRawFieldsDefinition(getCSVParameters()) != null) {
912 41617 jjdelcerro
            reader = new FixedLenReader(in, getCSVParameters());
913
        } else {
914
            reader = new CSVReader(in, getCSVParameters());
915
        }
916
        return reader;
917
    }
918 41006 jjdelcerro
919 42775 jjdelcerro
    private String getFixedHeader(int column) {
920
        char[] header = new char[3];
921
922
        String s = String.format("%03d", column);
923
        header[0] = (char) (s.charAt(0) + 17);
924
        header[1] = (char) (s.charAt(1) + 17);
925
        header[2] = (char) (s.charAt(2) + 17);
926
        return String.valueOf(header);
927
    }
928
929
    private String[] getFixedHeaders(int count) {
930
        String[] headers = new String[count];
931
        for (int i = 0; i < headers.length; i++) {
932
            headers[i] = getFixedHeader(i);
933
        }
934
        return headers;
935
    }
936
937 43283 jjdelcerro
    private InputStreamReader openFile(File f, String charsetName) throws FileNotFoundException {
938
        Charset charset = Charset.defaultCharset();
939
        FileInputStream fis = new FileInputStream(f);
940 44309 omartinez
        if (!StringUtils.isEmpty(charsetName)) {
941
            if (Charset.isSupported(charsetName)) {
942 43283 jjdelcerro
                try {
943
                    charset = Charset.forName(charsetName);
944 44309 omartinez
                } catch (Throwable th) {
945 44408 jjdelcerro
                    LOGGER.warn("Can't use charset '" + charsetName + "' for read csv '" + this.getFullFileName() + "'.", th);
946 43283 jjdelcerro
                }
947
            } else {
948 44408 jjdelcerro
                LOGGER.warn("charset '" + charsetName + "' not supported for read csv '" + this.getFullFileName() + "'.");
949 43283 jjdelcerro
            }
950
        }
951
        InputStreamReader isr = new InputStreamReader(fis, charset);
952
        return isr;
953
    }
954 44309 omartinez
955 42775 jjdelcerro
    private void loadFeatures() {
956 43283 jjdelcerro
        InputStreamReader in = null;
957 41617 jjdelcerro
        SimpleReader reader = null;
958
        try {
959
            String headers[] = null;
960
            FeatureStoreProviderServices store = this.getStoreServices();
961 41006 jjdelcerro
962 41617 jjdelcerro
            boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
963 42220 fdiaz
964 43283 jjdelcerro
            in = openFile(
965 44309 omartinez
                    this.getCSVParameters().getFile(),
966
                    CSVStoreParameters.getCharset(this.getCSVParameters())
967 43283 jjdelcerro
            );
968 41006 jjdelcerro
969 41617 jjdelcerro
            reader = getSimpleReader(in);
970 41006 jjdelcerro
971 41617 jjdelcerro
            headers = CSVStoreParameters.getHeaders(getCSVParameters());
972 42775 jjdelcerro
            if (headers == null) {
973
                if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
974
                    headers = reader.getHeader();
975
                    if (headers == null) {
976
                        if (CSVStoreParameters.getIgnoreErrors(getCSVParameters())) {
977
                            headers = getFixedHeaders(reader.getColumnsCount());
978
                        } else {
979
                            String msg = "Can't retrieve header from csv file '"
980
                                    + this.getCSVParameters().getFile()
981 44309 omartinez
                                            .getAbsolutePath()
982 42775 jjdelcerro
                                    + "' and not specified in the parameters.";
983 44408 jjdelcerro
                            LOGGER.warn(msg);
984 42775 jjdelcerro
                            throw new RuntimeException(msg);
985
                        }
986
                    }
987
                } else {
988
                    headers = getFixedHeaders(reader.getColumnsCount());
989 41617 jjdelcerro
                }
990 42775 jjdelcerro
            } else {
991
                if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
992
                    reader.getHeader(); // Skip and ignore the header of file
993
                }
994 41617 jjdelcerro
            }
995 41006 jjdelcerro
996 44936 jjdelcerro
            AutomaticDetectionOfTypes.DetectedValue[] detectedTypes = automaticDetectionOfTypes(headers);
997 44309 omartinez
            if (detectedTypes != null && detectedTypes.length > headers.length) {
998 42775 jjdelcerro
                // Se han detectado mas columnas que las que hay en la cabezera,
999
                // a?adimos mas columnas a la cabezera.
1000
                String[] headers2 = new String[detectedTypes.length];
1001 44309 omartinez
                for (int i = 0; i < headers2.length; i++) {
1002
                    if (i < headers.length) {
1003 42775 jjdelcerro
                        headers2[i] = headers[i];
1004
                    } else {
1005
                        headers2[i] = getFixedHeader(i);
1006
                    }
1007
                }
1008
                headers = headers2;
1009
            }
1010 44309 omartinez
            for (int i = 0; i < headers.length; i++) {
1011
                if (StringUtils.isEmpty(headers[i])) {
1012 44272 jjdelcerro
                    headers[i] = getFixedHeader(i);
1013
                }
1014
            }
1015 41617 jjdelcerro
            // Initialize the feature types
1016 42775 jjdelcerro
            EditableFeatureType edftype = this.getFeatureType(headers, detectedTypes);
1017 41617 jjdelcerro
            FeatureType ftype = edftype.getNotEditableCopy();
1018 42775 jjdelcerro
            List<FeatureType> ftypes = new ArrayList<>();
1019 41617 jjdelcerro
            ftypes.add(ftype);
1020
            store.setFeatureTypes(ftypes, ftype);
1021 41059 jjdelcerro
1022 41617 jjdelcerro
            Coercion coercion[] = new Coercion[ftype.size()];
1023 44669 jjdelcerro
            CoercionContext coercionContext[] = new CoercionContext[ftype.size()];
1024 41617 jjdelcerro
            int sizes[] = new int[ftype.size()];
1025 42775 jjdelcerro
            for (int i = 0; i < ftype.size(); i++) {
1026 41617 jjdelcerro
                sizes[i] = -1;
1027
                FeatureAttributeDescriptor ad = ftype.getAttributeDescriptor(i);
1028 44669 jjdelcerro
                coercion[i] = ad.getCoercion();
1029
                coercionContext[i] = ad.getCoercionContext();
1030 44309 omartinez
                switch (ad.getDataType().getType()) {
1031
                    case DataTypes.INT:
1032 44669 jjdelcerro
                        sizes[i] = 0;
1033 44309 omartinez
                        break;
1034
                    case DataTypes.LONG:
1035 44669 jjdelcerro
                        sizes[i] = 0;
1036 44309 omartinez
                        break;
1037
                    case DataTypes.STRING:
1038
                        if (ad.getSize() == 0) {
1039
                            // Es un string y no tiene un size asignado.
1040
                            // Lo ponemos a cero para calcularlo.
1041
                            sizes[i] = 0;
1042
                        }
1043
                        break;
1044
                    case DataTypes.URL:
1045
                    case DataTypes.URI:
1046
                    case DataTypes.FILE:
1047 41617 jjdelcerro
                        sizes[i] = 0;
1048
                }
1049
            }
1050 42775 jjdelcerro
            if (ftype.getDefaultGeometryAttributeName() != null) {
1051 41617 jjdelcerro
                this.need_calculate_envelope = true;
1052
            }
1053 41006 jjdelcerro
1054 41617 jjdelcerro
            Locale locale = CSVStoreParameters.getLocale(getCSVParameters());
1055
            taskStatus.message("_loading");
1056
            int count = 0;
1057 41062 jjdelcerro
1058 41617 jjdelcerro
            int count_errors = 0;
1059 41062 jjdelcerro
1060 41617 jjdelcerro
            List<String> row = reader.read();
1061 41062 jjdelcerro
1062 41617 jjdelcerro
            int skipLines = CSVStoreParameters.getSkipLines(getCSVParameters());
1063 42775 jjdelcerro
            if (skipLines > 0) {
1064 41617 jjdelcerro
                row = reader.skip(skipLines);
1065
            }
1066 42775 jjdelcerro
            int limit = CSVStoreParameters.getLimit(getCSVParameters());
1067
            while (row != null) {
1068 41617 jjdelcerro
                taskStatus.setCurValue(++count);
1069
                FeatureProvider feature = this.createFeatureProvider(ftype);
1070 42775 jjdelcerro
                for (int i = 0; i < row.size(); i++) {
1071 41617 jjdelcerro
                    Object rawvalue = row.get(i);
1072
                    try {
1073
                        Object value = null;
1074 44749 jjdelcerro
                        if( coercion[i]!=null ) {
1075
                          value = coercion[i].coerce(rawvalue, coercionContext[i]);
1076
                        }
1077 41617 jjdelcerro
                        feature.set(i, value);
1078 44309 omartinez
                        if (sizes[i] >= 0
1079
                                && (value instanceof String || value instanceof URL
1080
                                || value instanceof URI || value instanceof File)) {
1081 43425 jjdelcerro
                            int x = value.toString().length();
1082 42775 jjdelcerro
                            if (sizes[i] < x) {
1083 41617 jjdelcerro
                                sizes[i] = x;
1084
                            }
1085
                        }
1086 42775 jjdelcerro
                    } catch (Exception ex) {
1087
                        if (!ignore_errors) {
1088 41617 jjdelcerro
                            throw ex;
1089
                        }
1090 42775 jjdelcerro
                        if (count_errors++ < 10) {
1091 44408 jjdelcerro
                            LOGGER.warn("Can't load value of attribute " + i + " in row " + count + ".", ex);
1092 41617 jjdelcerro
                        }
1093 42775 jjdelcerro
                        if (count_errors == 10) {
1094 44408 jjdelcerro
                            LOGGER.info("Too many errors, suppress messages.");
1095 41617 jjdelcerro
                        }
1096
                    }
1097
                }
1098
                this.addFeatureProvider(feature);
1099 44309 omartinez
                if (limit > 0) {
1100
                    if (limit < this.data.size()) {
1101 42775 jjdelcerro
                        break;
1102
                    }
1103
                }
1104 41617 jjdelcerro
                row = reader.read();
1105
            }
1106 42775 jjdelcerro
            for (int i = 0; i < ftype.size(); i++) {
1107
                if (sizes[i] > 0) {
1108 41617 jjdelcerro
                    EditableFeatureAttributeDescriptor efad = ((EditableFeatureAttributeDescriptor) edftype.getAttributeDescriptor(i));
1109
                    efad.setSize(sizes[i]);
1110
                }
1111
            }
1112
            // Volvemos a asignar al store el featuretype, ya que puede
1113
            // haber cambiado.
1114
            ftype = edftype.getNotEditableCopy();
1115 42775 jjdelcerro
            ftypes = new ArrayList<>();
1116 41617 jjdelcerro
            ftypes.add(ftype);
1117
            store.setFeatureTypes(ftypes, ftype);
1118 41062 jjdelcerro
1119 41617 jjdelcerro
            taskStatus.terminate();
1120 42775 jjdelcerro
        } catch (Exception ex) {
1121 41643 jjdelcerro
            int lineno = 0;
1122 42775 jjdelcerro
            if (reader != null) {
1123 41643 jjdelcerro
                lineno = reader.getLine();
1124
            }
1125 42775 jjdelcerro
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
1126 41643 jjdelcerro
1127 41617 jjdelcerro
        } finally {
1128 42775 jjdelcerro
            if (reader != null) {
1129 41617 jjdelcerro
                try {
1130
                    reader.close();
1131
                } catch (Exception ex) {
1132
                    // Do nothing
1133
                }
1134
                reader = null;
1135
            }
1136 42775 jjdelcerro
            if (in != null) {
1137 41617 jjdelcerro
                try {
1138
                    in.close();
1139
                } catch (Exception ex) {
1140
                    // Do nothing
1141
                }
1142
                in = null;
1143
            }
1144
        }
1145
    }
1146 41062 jjdelcerro
1147 44936 jjdelcerro
    private AutomaticDetectionOfTypes.DetectedValue[] automaticDetectionOfTypes(String[] headers) throws IOException {
1148 41617 jjdelcerro
        boolean automatic_types_detection = CSVStoreParameters.getAutomaticTypesDetection(getCSVParameters());
1149 42775 jjdelcerro
        if (!automatic_types_detection) {
1150 41617 jjdelcerro
            return null;
1151
        }
1152 44936 jjdelcerro
        AutomaticDetectionOfTypes.DetectedValue[] types = null;
1153 41617 jjdelcerro
1154
        FileReader in = null;
1155
        SimpleReader reader = null;
1156
1157
        try {
1158
            in = new FileReader(this.getCSVParameters().getFile());
1159
            reader = getSimpleReader(in);
1160 43983 jjdelcerro
            AutomaticDetectionOfTypes x = new AutomaticDetectionOfTypes(
1161
                    this.getFullFileName()
1162
            );
1163
            types = x.detect(
1164 44309 omartinez
                    headers.length,
1165
                    reader,
1166
                    CSVStoreParameters.isFirstLineHeader(getCSVParameters()),
1167 43983 jjdelcerro
                    CSVStoreParameters.getLocale(getCSVParameters())
1168
            );
1169 42775 jjdelcerro
        } catch (Exception ex) {
1170 41643 jjdelcerro
            int lineno = 0;
1171 42775 jjdelcerro
            if (reader != null) {
1172 41643 jjdelcerro
                lineno = reader.getLine();
1173
            }
1174 42775 jjdelcerro
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
1175 41643 jjdelcerro
1176 41617 jjdelcerro
        } finally {
1177 42775 jjdelcerro
            IOUtils.closeQuietly(reader);
1178
            IOUtils.closeQuietly(in);
1179
        }
1180
        return types;
1181
    }
1182
1183 40846 jjdelcerro
}