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 @ 45359

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