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

History | View | Annotate | Download (52 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * 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
 *
11
 * 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
 *
16
 * 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
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.dal.store.csv;
24

    
25
import java.io.File;
26
import java.io.FileInputStream;
27
import java.io.FileNotFoundException;
28
import java.io.FileReader;
29
import java.io.FileWriter;
30
import java.io.IOException;
31
import java.io.InputStreamReader;
32
import java.net.URL;
33
import java.nio.charset.Charset;
34
import java.util.ArrayList;
35
import java.util.HashMap;
36
import java.util.Iterator;
37
import java.util.List;
38
import java.util.Locale;
39

    
40
import org.apache.commons.io.FilenameUtils;
41
import org.apache.commons.io.IOUtils;
42
import org.apache.commons.lang3.StringUtils;
43
import org.cresques.cts.IProjection;
44
import org.gvsig.fmap.dal.DALLocator;
45
import org.gvsig.fmap.dal.DataManager;
46
import org.gvsig.fmap.dal.DataServerExplorer;
47
import org.gvsig.fmap.dal.DataStore;
48
import org.gvsig.fmap.dal.DataStoreNotification;
49
import org.gvsig.fmap.dal.DataTypes;
50
import org.gvsig.fmap.dal.FileHelper;
51
import org.gvsig.fmap.dal.exception.DataException;
52
import org.gvsig.fmap.dal.exception.InitializeException;
53
import org.gvsig.fmap.dal.exception.OpenException;
54
import org.gvsig.fmap.dal.exception.ReadException;
55
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
56
import org.gvsig.fmap.dal.feature.EditableFeature;
57
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
58
import org.gvsig.fmap.dal.feature.EditableFeatureType;
59
import org.gvsig.fmap.dal.feature.Feature;
60
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
61
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
62
import org.gvsig.fmap.dal.feature.FeatureSet;
63
import org.gvsig.fmap.dal.feature.FeatureStore;
64
import org.gvsig.fmap.dal.feature.FeatureType;
65
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
66
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
67
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
68
import org.gvsig.fmap.dal.feature.spi.memory.AbstractMemoryStoreProvider;
69
import org.gvsig.fmap.dal.resource.ResourceAction;
70
import org.gvsig.fmap.dal.resource.file.FileResource;
71
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
72
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
73
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
74
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
75
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
76
import org.gvsig.fmap.dal.store.csv.simplereaders.CSVReader;
77
import org.gvsig.fmap.dal.store.csv.simplereaders.FixedLenReader;
78
import org.gvsig.fmap.dal.store.csv.simplereaders.SimpleReader;
79
import org.gvsig.fmap.geom.Geometry;
80
import org.gvsig.fmap.geom.GeometryLocator;
81
import org.gvsig.fmap.geom.GeometryManager;
82
import org.gvsig.fmap.geom.aggregate.MultiPoint;
83
import org.gvsig.fmap.geom.primitive.Envelope;
84
import org.gvsig.fmap.geom.primitive.Point;
85
import org.gvsig.fmap.geom.type.GeometryType;
86
import org.gvsig.tools.ToolsLocator;
87
import org.gvsig.tools.dataTypes.CoercionException;
88
import org.gvsig.tools.dataTypes.DataType;
89
import org.gvsig.tools.dataTypes.DataTypesManager;
90
import org.gvsig.tools.dataTypes.DataTypesManager.Coercion;
91
import org.gvsig.tools.dataTypes.DataTypesManager.CoercionWithLocale;
92
import org.gvsig.tools.dispose.DisposableIterator;
93
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
94
import org.gvsig.tools.evaluator.AbstractEvaluator;
95
import org.gvsig.tools.evaluator.EvaluatorData;
96
import org.gvsig.tools.evaluator.EvaluatorException;
97
import org.gvsig.tools.exception.BaseException;
98
import org.gvsig.tools.exception.NotYetImplemented;
99
import org.gvsig.tools.persistence.PersistentState;
100
import org.gvsig.tools.persistence.exception.PersistenceException;
101
import org.gvsig.tools.task.SimpleTaskStatus;
102
import org.gvsig.tools.task.TaskStatusManager;
103
import org.gvsig.tools.visitor.VisitCanceledException;
104
import org.gvsig.tools.visitor.Visitor;
105
import org.slf4j.Logger;
106
import org.slf4j.LoggerFactory;
107
import org.supercsv.io.CsvListWriter;
108
import org.supercsv.prefs.CsvPreference;
109

    
110
public class CSVStoreProvider extends AbstractMemoryStoreProvider implements
111
        ResourceConsumer {
112

    
113
    private static final Logger logger = LoggerFactory.getLogger(CSVStoreProvider.class);
114

    
115
    public static final String NAME = "CSV";
116
    public static final String DESCRIPTION = "CSV file";
117

    
118
    public static final String METADATA_DEFINITION_NAME = NAME;
119

    
120
    private ResourceProvider resource;
121

    
122
    private long counterNewsOIDs = 0;
123
    private Envelope envelope;
124
    private boolean need_calculate_envelope = false;
125
    private SimpleTaskStatus taskStatus;
126

    
127
    public CSVStoreProvider(CSVStoreParameters parameters,
128
            DataStoreProviderServices storeServices) throws InitializeException {
129
        super(
130
                parameters,
131
                storeServices,
132
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
133
        );
134

    
135
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
136
        this.taskStatus = manager.createDefaultSimpleTaskStatus("CSV");
137

    
138
        counterNewsOIDs = 0;
139

    
140
        File file = getCSVParameters().getFile();
141
        resource = this.createResource(
142
                FileResource.NAME,
143
                new Object[]{file.getAbsolutePath()}
144
        );
145

    
146
        resource.addConsumer(this);
147
        initializeFeatureTypes();
148
    }
149

    
150
    private CSVStoreParameters getCSVParameters() {
151
        return (CSVStoreParameters) this.getParameters();
152
    }
153

    
154
    public String getProviderName() {
155
        return NAME;
156
    }
157

    
158
    public boolean allowWrite() {
159
        return false;
160
    }
161

    
162
    private String getFullFileName() {
163
        // Usar solo para mostrar mensajes en el logger.
164
        String s = "(unknow)";
165
        try {
166
            s = getCSVParameters().getFile().getAbsolutePath();
167
        } catch (Exception e2) {
168
            s = "(unknow)";
169
        }
170
        return s;
171
    }
172

    
173
    public void open() throws OpenException {
174
        if (this.data != null) {
175
            return;
176
        }
177
        this.data = new ArrayList<>();
178
        resource.setData(new HashMap());
179
        counterNewsOIDs = 0;
180
        try {
181
            loadFeatures();
182
        } catch (RuntimeException e) {
183
            logger.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
184
            throw e;
185
        } catch (Exception e) {
186
            logger.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
187
            throw new RuntimeException(e);
188
        }
189
    }
190

    
191
    public DataServerExplorer getExplorer() throws ReadException {
192
        DataManager manager = DALLocator.getDataManager();
193
        FilesystemServerExplorerParameters params;
194
        try {
195
            params = (FilesystemServerExplorerParameters) manager
196
                    .createServerExplorerParameters(FilesystemServerExplorer.NAME);
197
            params.setRoot(this.getCSVParameters().getFile().getParent());
198
            return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
199
        } catch (DataException e) {
200
            throw new ReadException(this.getProviderName(), e);
201
        } catch (ValidateDataParametersException e) {
202
            throw new ReadException(this.getProviderName(), e);
203
        }
204

    
205
    }
206

    
207
    class Writer {
208

    
209
        private Envelope envelope = null;
210
        private boolean calculate_envelope = false;
211
        private CsvListWriter listWriter = null;
212
        private CsvPreference csvpreferences = null;
213
        private FileWriter fwriter = null;
214
        private FeatureType ftype;
215
        private File file;
216
        private String[] values;
217
        private FeatureAttributeDescriptor[] descriptors;
218
        private Coercion convert = null;
219
        private int errorcounts = 0;
220
        private Throwable lasterror = null;
221
        private Locale locale = null;
222

    
223
        public void initialize(File file, FeatureType ftype, CsvPreference csvpreferences) {
224
            this.file = file;
225
            this.ftype = ftype;
226
            this.csvpreferences = csvpreferences;
227
            this.locale = CSVStoreParameters.getLocale(getCSVParameters());
228
            if (csvpreferences == null) {
229
                this.csvpreferences = CsvPreference.STANDARD_PREFERENCE;
230
            }
231
            if (ftype.getDefaultGeometryAttributeName() != null) {
232
                this.calculate_envelope = true;
233
            }
234
            this.descriptors = this.ftype.getAttributeDescriptors();
235
            this.convert = ToolsLocator.getDataTypesManager().getCoercion(org.gvsig.tools.dataTypes.DataTypes.STRING);
236
            this.errorcounts = 0;
237
        }
238

    
239
        public void begin() {
240
            try {
241
                this.fwriter = new FileWriter(file);
242
            } catch (IOException e) {
243
                logger.warn("Can't open file for write (" + file.getAbsolutePath() + ").", e);
244
                throw new RuntimeException(e);
245
            }
246
            this.listWriter = new CsvListWriter(this.fwriter, this.csvpreferences);
247
            int n = 0;
248
            for (int i = 0; i < descriptors.length; i++) {
249
                FeatureAttributeDescriptor descriptor = descriptors[i];
250
                if (descriptor.getEvaluator() == null) {
251
                    n++;
252
                }
253
            }
254

    
255
            String[] header = new String[n];
256
            this.values = new String[n];
257
            n = 0;
258
            for (int i = 0; i < descriptors.length; i++) {
259
                FeatureAttributeDescriptor descriptor = descriptors[i];
260
                if (descriptor.getEvaluator() == null) {
261
                    String name = descriptor.getName();
262
                    String typeName = descriptor.getDataTypeName();
263
                    if (descriptor.getDataType().getType() == DataTypes.STRING) {
264
                        header[n++] = name + "__" + typeName + "__" + descriptor.getSize();
265
                    } else {
266
                        header[n++] = name + "__" + typeName;
267
                    }
268
                }
269
            }
270
            try {
271
                listWriter.writeHeader(header);
272
            } catch (Exception e) {
273
                logger.warn("Can't write header '" + header.toString() + "' file for write (" + file.getAbsolutePath() + ").", e);
274
                throw new RuntimeException(e);
275
            }
276
        }
277

    
278
        public void add(FeatureProvider feature) {
279
            if (this.calculate_envelope) {
280
                Geometry geom = feature.getDefaultGeometry();
281
                if (geom != null) {
282
                    if (envelope == null) {
283
                        try {
284
                            envelope = (Envelope) geom.getEnvelope().clone();
285
                        } catch (CloneNotSupportedException e) {
286
                            logger.warn("Este error no deberia pasar, siempre se puede hacer un clone de un envelope.", e);
287
                        }
288
                    } else {
289
                        envelope.add(geom.getEnvelope());
290
                    }
291
                }
292
            }
293
            int n = 0;
294
            for (int i = 0; i < descriptors.length; i++) {
295
                FeatureAttributeDescriptor descriptor = descriptors[i];
296
                if (descriptor.getEvaluator() == null) {
297
                    Object value = feature.get(i);
298
                    try {
299
                        n++;
300
                        if (this.convert != null && this.convert instanceof CoercionWithLocale) {
301
                            values[n] = (String) ((CoercionWithLocale) this.convert).coerce(value, this.locale);
302
                        } else {
303
                            values[n] = (String) this.convert.coerce(value);
304
                        }
305
                    } catch (CoercionException e) {
306
                        try {
307
                            values[n] = value.toString();
308
                        } catch (Exception ex) {
309
                            values[n] = "";
310
                        }
311
                        if (errorcounts++ <= 10) {
312
                            this.lasterror = e;
313
                            logger.warn("Can't convert value of field " + i + " to string in CVS file '" + getFullFileName() + "'.", e);
314
                            if (errorcounts == 10) {
315
                                logger.warn("Too many error writing CVS file '" + getFullFileName() + "', don't output more.");
316
                            }
317
                        }
318
                    }
319
                }
320
            }
321
            try {
322
                this.listWriter.writeHeader(values);
323
            } catch (IOException e) {
324
                if (errorcounts++ <= 10) {
325
                    this.lasterror = e;
326
                    logger.warn("Can't write values to CVS file '" + getFullFileName() + "'.", e);
327
                    if (errorcounts == 10) {
328
                        logger.warn("Too many error writing CVS file '" + getFullFileName() + "', don't output more.");
329
                    }
330
                }
331
            }
332

    
333
        }
334

    
335
        public void end() throws PerformEditingException {
336
            if (this.errorcounts > 0) {
337
                throw new PerformEditingException(this.file.getAbsolutePath(), lasterror);
338
            }
339
            if (listWriter != null) {
340
                try {
341
                    listWriter.close();
342
                } catch (Exception ex) {
343
                    // Ignore error
344
                }
345
                listWriter = null;
346
            }
347
            if (fwriter != null) {
348
                try {
349
                    fwriter.close();
350
                } catch (Exception ex) {
351
                    // Ignore error
352
                }
353
                fwriter = null;
354
            }
355
        }
356

    
357
        public Envelope getEnvelope() {
358
            return this.envelope;
359
        }
360
    }
361

    
362
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
363

    
364
        try {
365
            this.taskStatus.add();
366
            taskStatus.message("_preparing");
367
            getResource().execute(new ResourceAction() {
368
                public Object run() throws Exception {
369
                    FeatureSet features = null;
370
                    DisposableIterator it = null;
371
                    try {
372
                        File file = (File) resource.get();
373

    
374
                        Writer writer = new Writer();
375
                        writer.initialize(file, getStoreServices().getDefaultFeatureType(), getCSVPreferences());
376
                        features
377
                                = getStoreServices().getFeatureStore()
378
                                .getFeatureSet();
379
                        List<FeatureProvider> newdata = new ArrayList<FeatureProvider>();
380
                        writer.begin();
381
                        it = features.fastIterator();
382
                        taskStatus.setRangeOfValues(0, 0);
383
                        long counter = 0;
384
                        while (it.hasNext()) {
385
                            taskStatus.setCurValue(counter++);
386
                            FeatureProvider feature = getStoreServices().getFeatureProviderFromFeature(
387
                                    (org.gvsig.fmap.dal.feature.Feature) it.next());
388
                            writer.add(feature);
389
                            if (feature.getOID() == null) {
390
                                logger.warn("feature without OID");
391
                                feature.setOID(createNewOID());
392
                            }
393
                            newdata.add(feature);
394
                        }
395
                        data = newdata;
396
                        if (writer.getEnvelope() != null) {
397
                            envelope = writer.getEnvelope().getGeometry().getEnvelope();
398
                        }
399
                        resource.notifyChanges();
400
                        writer.end();
401
                    } finally {
402
                        if (it != null) {
403
                            it.dispose();
404
                        }
405
                        if (features != null) {
406
                            features.dispose();
407
                        }
408
                    }
409
                    return null;
410
                }
411

    
412
                private CsvPreference getCSVPreferences() {
413
                    CSVReader reader = new CSVReader(getCSVParameters());
414
                    return reader.getCSVPreferences();
415
                }
416

    
417
            });
418
            this.taskStatus.terminate();
419
        } catch (Exception e) {
420
            this.taskStatus.abort();
421
            throw new PerformEditingException(getResource().toString(), e);
422
        } finally {
423
            this.taskStatus.remove();
424
        }
425
    }
426

    
427
    public boolean closeResourceRequested(ResourceProvider resource) {
428
        return true;
429
    }
430

    
431
    public int getOIDType() {
432
        return DataTypes.LONG;
433
    }
434

    
435
    public boolean supportsAppendMode() {
436
        return false;
437
    }
438

    
439
    public void append(FeatureProvider featureProvider) {
440
        throw new UnsupportedOperationException();
441
    }
442

    
443
    public void beginAppend() {
444
        throw new UnsupportedOperationException();
445
    }
446

    
447
    public void endAppend() {
448
        throw new UnsupportedOperationException();
449
    }
450

    
451
    public void saveToState(PersistentState state) throws PersistenceException {
452
        throw new NotYetImplemented();
453
    }
454

    
455
    public void loadFromState(PersistentState state) throws PersistenceException {
456
        throw new NotYetImplemented();
457
    }
458

    
459
    public Object createNewOID() {
460
        return new Long(counterNewsOIDs++);
461
    }
462

    
463
    protected void initializeFeatureTypes() throws InitializeException {
464
        try {
465
            this.open();
466
        } catch (OpenException e) {
467
            throw new InitializeException(this.getProviderName(), e);
468
        }
469
    }
470

    
471
    public Envelope getEnvelope() throws DataException {
472
        this.open();
473
        if (this.envelope != null) {
474
            return this.envelope;
475
        }
476
        if (!this.need_calculate_envelope) {
477
            return null;
478
        }
479
        FeatureStore fs = this.getFeatureStore();
480
        FeatureType ft = fs.getDefaultFeatureType();
481
        FeatureAttributeDescriptor fad = ft.getAttributeDescriptor(ft.getDefaultGeometryAttributeIndex());
482

    
483
        try {
484
            this.envelope = GeometryLocator.getGeometryManager().createEnvelope(fad.getGeomType().getSubType());
485
            fs.accept(new Visitor() {
486
                public void visit(Object obj) throws VisitCanceledException, BaseException {
487
                    Feature f = (Feature) obj;
488
                    Geometry geom = f.getDefaultGeometry();
489
                    if (geom != null) {
490
                        envelope.add(geom.getEnvelope());
491
                    }
492
                }
493
            });
494
        } catch (BaseException e) {
495
            logger.warn("Can't calculate the envelope of CSV file '" + this.getFullName() + "'.", e);
496
            this.envelope = null;
497
        }
498

    
499
        this.need_calculate_envelope = false;
500
        return this.envelope;
501
    }
502

    
503
    public Object getDynValue(String name) throws DynFieldNotFoundException {
504
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
505
            try {
506
                return this.getEnvelope();
507
            } catch (DataException e) {
508
                return null;
509
            }
510
        } else {
511
            if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
512
                IProjection pro = CSVStoreParameters.getCRS(this.getCSVParameters());
513
                if (pro != null) {
514
                    return pro;
515
                }
516
            }
517
        }
518
        return super.getDynValue(name);
519
    }
520

    
521
    public void resourceChanged(ResourceProvider resource) {
522
        this.getStoreServices().notifyChange(
523
                DataStoreNotification.RESOURCE_CHANGED,
524
                resource);
525
    }
526

    
527
    public Object getSourceId() {
528
        return this.getCSVParameters().getFile();
529
    }
530

    
531
    public String getName() {
532
        String name = this.getCSVParameters().getFile().getName();
533
        return FilenameUtils.getBaseName(name);
534
    }
535

    
536
    public String getFullName() {
537
        return this.getCSVParameters().getFile().getAbsolutePath();
538
    }
539

    
540
    public ResourceProvider getResource() {
541
        return resource;
542
    }
543

    
544
    private boolean isEmpty(String s) {
545
        if (s == null) {
546
            return true;
547
        }
548
        return s.trim().length() == 0;
549
    }
550

    
551
    private class FieldTypeParser {
552

    
553
        public String name = null;
554
        public int type = DataTypes.STRING;
555
        public int size = 0;
556
        public boolean allowNulls = true;
557
        public int geometryType = Geometry.TYPES.GEOMETRY;
558

    
559
        private String typename = "string";
560

    
561
        FieldTypeParser() {
562
        }
563

    
564
        private int getType(String value) {
565
            DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
566
            return dataTypesManager.getType(typename);
567
        }
568

    
569
        public void clear() {
570
            name = null;
571
            type = DataTypes.STRING;
572
            size = 0;
573
            allowNulls = true;
574
            geometryType = Geometry.TYPES.GEOMETRY;
575
        }
576

    
577
        public void copyFrom(FieldTypeParser other) {
578
            name = other.name;
579
            type = other.type;
580
            size = other.size;
581
            allowNulls = other.allowNulls;
582
            geometryType = other.geometryType;
583
        }
584

    
585
        // El formato seria:
586
        //   name[:typename[:size[:notnull|null]]]
587
        //   name[:GEOMETRY[:geometry_type[:notnull|null]]]
588
        //   name[__typename[__size[__notnull|null]]]
589
        //
590
        public boolean parse(String value) {
591
            String typename = null;
592
            String[] ss = null;
593
            if (value.contains(":")) {
594
                ss = value.split(":");
595
            } else if (value.contains("__")) {
596
                ss = value.split("__");
597
            }
598
            if (ss == null) {
599
                this.name = value;
600
                return true;
601
            }
602
            switch (ss.length) {
603
                case 4:
604
                    if (!StringUtils.isBlank(ss[3])) {
605
                        if ("notnull".equalsIgnoreCase(ss[3].trim())) {
606
                            this.allowNulls = false;
607
                        } else {
608
                            this.allowNulls = true;
609
                        }
610
                    }
611
                case 3:
612
                    if (!StringUtils.isBlank(ss[1])) {
613
                        this.typename = ss[1].trim();
614
                        this.type = this.getType(this.typename);
615
                        if (this.type == DataTypes.INVALID) {
616
                            this.type = DataTypes.STRING;
617
                            logger.info("Type '" + typename + "' not valid for attribute '" + value + "' in CSV file '" + getFullFileName() + "'.");
618
                        }
619
                    }
620
                    if (!StringUtils.isBlank(ss[2])) {
621
                        if (this.type == DataTypes.GEOMETRY) {
622
                            String s = ss[2].trim();
623
                            if (s.equalsIgnoreCase("line") || s.equalsIgnoreCase("linestring") || s.equalsIgnoreCase("curve")) {
624
                                this.geometryType = Geometry.TYPES.CURVE;
625
                            } else if (s.equalsIgnoreCase("multiline") || s.equalsIgnoreCase("multilinestring") || s.equalsIgnoreCase("multicurve")) {
626
                                this.geometryType = Geometry.TYPES.MULTICURVE;
627
                            } else if (s.equalsIgnoreCase("point")) {
628
                                this.geometryType = Geometry.TYPES.POINT;
629
                            } else if (s.equalsIgnoreCase("multipoint")) {
630
                                this.geometryType = Geometry.TYPES.MULTIPOINT;
631
                            } else if (s.equalsIgnoreCase("polygon") || s.equalsIgnoreCase("surface")) {
632
                                this.geometryType = Geometry.TYPES.POLYGON;
633
                            } else if (s.equalsIgnoreCase("multipolygon") || s.equalsIgnoreCase("multisurface")) {
634
                                this.geometryType = Geometry.TYPES.MULTISURFACE;
635
                            }
636
                            this.size = 1;
637
                        } else {
638
                            try {
639
                                this.size = Integer.parseInt(ss[2]);
640
                            } catch (Exception ex) {
641
                                logger.warn("Ignore incorrect field size for field " + value + " in CSV header of '" + getFullFileName() + "'.", ex);
642
                            }
643
                        }
644
                    }
645
                    this.name = ss[0].trim();
646
                    break;
647
                case 2:
648
                    if (!StringUtils.isBlank(ss[1])) {
649
                        this.typename = ss[1].trim();
650
                        this.type = this.getType(this.typename);
651
                        if (this.type == DataTypes.INVALID) {
652
                            this.type = DataTypes.STRING;
653
                            logger.info("Type '" + typename + "' not valid for attribute '" + value + "' in CSV file '" + getFullFileName() + "'.");
654
                        }
655
                    }
656
                case 1:
657
                    this.name = ss[0].trim();
658
                    break;
659
            }
660

    
661
            if (this.type != DataTypes.STRING) {
662
                this.size = 0;
663
            }
664
            return true;
665
        }
666

    
667
    }
668

    
669
    private EditableFeatureType getFeatureType(String headers[], int automaticTypes[]) {
670
        EditableFeatureType fType = getStoreServices().createFeatureType(this.getName());
671
        fType.setHasOID(true);
672

    
673
        FieldTypeParser[] fieldTypes = new FieldTypeParser[headers.length];
674
        //
675
        // Calculamos cuales pueden ser los tipos de datos
676
        //
677
        for (int i = 0; i < fieldTypes.length; i++) {
678
            fieldTypes[i] = new FieldTypeParser();
679
        }
680

    
681
        // Asuminos los tipos pasados por parametro, que se supone
682
        // son los detectados automaticamente.
683
        if (automaticTypes != null) {
684
            for (int i = 0; i < fieldTypes.length && i < automaticTypes.length; i++) {
685
                fieldTypes[i].type = automaticTypes[i];
686
            }
687
        }
688
        // Luego probamos con lo que diga las cabezeras del CVS, sobreescribiendo
689
        // los tipos anteriores en caso de definirse en la cabezara.
690
        for (int i = 0; i < fieldTypes.length; i++) {
691
            if (!fieldTypes[i].parse(headers[i])) {
692
                continue;
693
            }
694

    
695
        }
696

    
697
        // Y por ultimo hacemos caso a lo que se haya especificado en los parametros
698
        // de apertura del CSV, teniendo esto prioridad sobre todo.
699
        String param_types_def = CSVStoreParameters.getRawFieldTypes(this.getParameters());
700
        if (StringUtils.isNotBlank(param_types_def)) {
701
            String sep = CSVStoreParameters.getDelimiter(param_types_def);
702
            if (StringUtils.isNotBlank(sep)) {
703
                String[] param_types = param_types_def.split(sep);
704
                FieldTypeParser parser = new FieldTypeParser();
705
                for (String param_type : param_types) {
706
                    parser.clear();
707
                    parser.parse(param_type);
708
                    for (FieldTypeParser fieldType : fieldTypes) {
709
                        if (StringUtils.equalsIgnoreCase(fieldType.name, parser.name)) {
710
                            fieldType.copyFrom(parser);
711
                            break;
712
                        }
713
                    }
714
                }
715
            }
716
        }
717
        //
718
        // Una vez ya sabemos los tipos de datos rellenamos el feature-type
719
        //
720
        for (int i = 0; i < fieldTypes.length; i++) {
721
            EditableFeatureAttributeDescriptor fad = fType.add(
722
                    fieldTypes[i].name,
723
                    fieldTypes[i].type
724
            );
725
            fad.setSize(fieldTypes[i].size);
726
            fad.setAllowNull(fieldTypes[i].allowNulls);
727
            if (fieldTypes[i].type == DataTypes.GEOMETRY) {
728
                if (fType.getDefaultGeometryAttributeName() == null) {
729
                    fType.setDefaultGeometryAttributeName(fieldTypes[i].name);
730
                }
731
                fad.setGeometryType(fieldTypes[i].geometryType);
732
            }
733
        }
734
        String[] pointDimensionNames = CSVStoreParameters.getPointDimensionNames(this.getParameters());
735
        if (pointDimensionNames != null) {
736
            PointAttributeEmulator emulator = new PointAttributeEmulator(pointDimensionNames);
737
            EditableFeatureAttributeDescriptor attr = fType.add(
738
                    CSVStoreParameters.getPointColumnName(this.getParameters()), 
739
                    DataTypes.GEOMETRY, emulator
740
            );
741
            GeometryManager geommgr = GeometryLocator.getGeometryManager();
742
            GeometryType gt;
743
            try {
744
                gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM3D);
745
                attr.setGeometryType(gt);
746
                attr.setGeometryType(Geometry.TYPES.POINT);
747
                attr.setGeometrySubType(Geometry.SUBTYPES.GEOM3D);
748
            } catch (Exception e) {
749
                logger.warn("Can't set geometry type for the calculated field in CSV file '" + getFullFileName() + "'.", e);
750
            }
751
        }
752
        
753
        String geometry_column = CSVStoreParameters.getGeometryColumn(this.getParameters());
754
        if( !StringUtils.isEmpty(geometry_column) ) {
755
            EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor) fType.get(geometry_column);
756
            if( attr!=null && attr.getType()!=DataTypes.GEOMETRY ) {
757
                attr.setDataType(DataTypes.GEOMETRY);
758
                GeometryManager geommgr = GeometryLocator.getGeometryManager();
759
                GeometryType gt;
760
                try {
761
                    gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.UNKNOWN);
762
                    attr.setGeometryType(gt);
763
                } catch (Exception e) {
764
                    logger.warn("Can't set geometry type for the calculated field in CSV file '" + getFullFileName() + "'.", e);
765
                }
766
                fType.setDefaultGeometryAttributeName(geometry_column);
767
            }
768
        }
769
        return fType;
770
    }
771

    
772
    static class PointAttributeEmulator implements FeatureAttributeEmulator {
773

    
774
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
775

    
776
        private static final int XNAME = 0;
777
        private static final int YNAME = 1;
778
        private static final int ZNAME = 2;
779

    
780
        private final GeometryManager geommgr;
781
        private final String[] fieldNames;
782
        private final Coercion toDouble;
783
        private final DataType dataType;
784
        private int errorcount = 0;
785

    
786
        public PointAttributeEmulator(String[] pointDimensionNames) {
787
            if (pointDimensionNames.length > 2) {
788
                this.fieldNames = new String[3];
789
                this.fieldNames[ZNAME] = pointDimensionNames[2];
790
            } else {
791
                this.fieldNames = new String[2];
792
            }
793
            this.fieldNames[XNAME] = pointDimensionNames[0];
794
            this.fieldNames[YNAME] = pointDimensionNames[1];
795
            this.geommgr = GeometryLocator.getGeometryManager();
796
            DataTypesManager datatypeManager = ToolsLocator.getDataTypesManager();
797

    
798
            this.toDouble = datatypeManager.getCoercion(DataTypes.DOUBLE);
799
            this.dataType = datatypeManager.get(DataTypes.GEOMETRY);
800
        }
801

    
802
        public Object get(Feature feature) {
803
            try {
804
                Object valueX = feature.get(this.fieldNames[XNAME]);
805
                valueX = toDouble.coerce(valueX);
806
                if (valueX == null) {
807
                    return null;
808
                }
809
                Object valueY = feature.get(this.fieldNames[YNAME]);
810
                valueY = toDouble.coerce(valueY);
811
                if (valueY == null) {
812
                    return null;
813
                }
814
                Object valueZ = null;
815
                if (this.fieldNames.length > 2) {
816
                    valueZ = toDouble.coerce(feature.get(this.fieldNames[ZNAME]));
817
                    if (valueZ == null) {
818
                        return null;
819
                    }
820
                }
821

    
822
                double x = ((Double) valueX).doubleValue();
823
                double y = ((Double) valueY).doubleValue();
824
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
825
                if (this.fieldNames.length > 2) {
826
                    double z = ((Double) valueZ).doubleValue();
827
                    point.setCoordinateAt(2, z);
828
                }
829
                return point;
830
            } catch (Exception ex) {
831
                if (++errorcount < 5) {
832
                    logger.warn("[" + errorcount + "] Can't create point in CSV provider. XNAME='"
833
                            + this.fieldNames[XNAME] + "', YNAME='" + this.fieldNames[XNAME] + "' feature=" + feature.toString(), ex);
834
                }
835
                return null;
836
            }
837
        }
838

    
839
        public void set(EditableFeature feature, Object value) {
840
            if (value == null) {
841
                return;
842
            }
843
            Point point = null;
844
            if (value instanceof MultiPoint) {
845
                point = (Point) ((MultiPoint) value).getPrimitiveAt(0);
846
            } else {
847
                point = (Point) value;
848
            }
849
            feature.set(this.fieldNames[XNAME], point.getX());
850
            feature.set(this.fieldNames[YNAME], point.getY());
851
            if (this.fieldNames.length > 2) {
852
                feature.set(this.fieldNames[ZNAME], point.getCoordinateAt(2));
853
            }
854
        }
855

    
856
        public boolean allowSetting() {
857
            return true;
858
        }
859

    
860
        public String[] getRequiredFieldNames() {
861
            return this.fieldNames;
862
        }
863

    
864
    }
865

    
866
    static class ToPointEvaluaror extends AbstractEvaluator {
867

    
868
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
869

    
870
        private GeometryManager geommgr = null;
871
        private String xname = null;
872
        private String yname = null;
873
        private String zname = null;
874
        private Coercion toDouble;
875
        private int errorcount = 0;
876

    
877
        ToPointEvaluaror(String[] pointDimensionNames) {
878
            this.xname = pointDimensionNames[0];
879
            this.yname = pointDimensionNames[1];
880
            if (pointDimensionNames.length > 2) {
881
                this.zname = pointDimensionNames[2];
882
            }
883
            this.geommgr = GeometryLocator.getGeometryManager();
884
            this.toDouble = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.DOUBLE);
885
        }
886

    
887
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
888
            try {
889
                double x = ((Double) toDouble.coerce(data.getDataValue(xname))).doubleValue();
890
                double y = ((Double) toDouble.coerce(data.getDataValue(yname))).doubleValue();
891
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
892
                if (zname != null) {
893
                    double z = ((Double) toDouble.coerce(data.getDataValue(zname))).doubleValue();
894
                    point.setCoordinateAt(2, z);
895
                }
896
                return point;
897
            } catch (Exception ex) {
898
                if (++errorcount < 5) {
899
                    logger.warn("[" + errorcount + "] Can't create point in CSV provider. XNAME='"
900
                            + xname + "', YNAME='" + yname + "', ZNAME='" + zname + "', data=" + data.toString());
901
                }
902
                return null;
903
            }
904
        }
905

    
906
        public String getName() {
907
            return "ToPointEvaluaror";
908
        }
909

    
910
    }
911

    
912
    private SimpleReader getSimpleReader(InputStreamReader in) {
913
        SimpleReader reader;
914
        if (CSVStoreParameters.getRawFieldsDefinition(getCSVParameters()) != null) {
915
            reader = new FixedLenReader(in, getCSVParameters());
916
        } else {
917
            reader = new CSVReader(in, getCSVParameters());
918
        }
919
        return reader;
920
    }
921

    
922
    private String getFixedHeader(int column) {
923
        char[] header = new char[3];
924

    
925
        String s = String.format("%03d", column);
926
        header[0] = (char) (s.charAt(0) + 17);
927
        header[1] = (char) (s.charAt(1) + 17);
928
        header[2] = (char) (s.charAt(2) + 17);
929
        return String.valueOf(header);
930
    }
931

    
932
    private String[] getFixedHeaders(int count) {
933
        String[] headers = new String[count];
934
        for (int i = 0; i < headers.length; i++) {
935
            headers[i] = getFixedHeader(i);
936
        }
937
        return headers;
938
    }
939

    
940
    private InputStreamReader openFile(File f, String charsetName) throws FileNotFoundException {
941
        Charset charset = Charset.defaultCharset();
942
        FileInputStream fis = new FileInputStream(f);
943
        if( !StringUtils.isEmpty(charsetName) ) {
944
            if( Charset.isSupported(charsetName) )  {
945
                try {
946
                    charset = Charset.forName(charsetName);
947
                } catch(Throwable th) {
948
                    logger.warn("Can't use charset '"+charsetName+"' for read csv '"+this.getFullFileName()+"'.", th);
949
                }
950
            } else {
951
                logger.warn("charset '"+charsetName+"' not supported for read csv '"+this.getFullFileName()+"'.");                
952
            }
953
        }
954
        InputStreamReader isr = new InputStreamReader(fis, charset);
955
        return isr;
956
    }
957
    
958
    private void loadFeatures() {
959
        InputStreamReader in = null;
960
        SimpleReader reader = null;
961
        try {
962
            String headers[] = null;
963
            FeatureStoreProviderServices store = this.getStoreServices();
964

    
965
            boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
966

    
967
            in = openFile(
968
                this.getCSVParameters().getFile(), 
969
                CSVStoreParameters.getCharset(this.getCSVParameters())
970
            );
971

    
972
            reader = getSimpleReader(in);
973

    
974
            headers = CSVStoreParameters.getHeaders(getCSVParameters());
975
            if (headers == null) {
976
                if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
977
                    headers = reader.getHeader();
978
                    if (headers == null) {
979
                        if (CSVStoreParameters.getIgnoreErrors(getCSVParameters())) {
980
                            headers = getFixedHeaders(reader.getColumnsCount());
981
                        } else {
982
                            String msg = "Can't retrieve header from csv file '"
983
                                    + this.getCSVParameters().getFile()
984
                                    .getAbsolutePath()
985
                                    + "' and not specified in the parameters.";
986
                            logger.warn(msg);
987
                            throw new RuntimeException(msg);
988
                        }
989
                    }
990
                } else {
991
                    headers = getFixedHeaders(reader.getColumnsCount());
992
                }
993
            } else {
994
                if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
995
                    reader.getHeader(); // Skip and ignore the header of file
996
                }
997
            }
998

    
999
            int[] detectedTypes = automaticDetectionOfTypes(headers);
1000
            if( detectedTypes!=null && detectedTypes.length>headers.length ) {
1001
                // Se han detectado mas columnas que las que hay en la cabezera,
1002
                // a?adimos mas columnas a la cabezera.
1003
                String[] headers2 = new String[detectedTypes.length];
1004
                for( int i=0; i<headers2.length; i++ ) {
1005
                    if( i<headers.length ) {
1006
                        headers2[i] = headers[i];
1007
                    } else {
1008
                        headers2[i] = getFixedHeader(i);
1009
                    }
1010
                }
1011
                headers = headers2;
1012
            }
1013
            // Initialize the feature types
1014
            EditableFeatureType edftype = this.getFeatureType(headers, detectedTypes);
1015
            FeatureType ftype = edftype.getNotEditableCopy();
1016
            List<FeatureType> ftypes = new ArrayList<>();
1017
            ftypes.add(ftype);
1018
            store.setFeatureTypes(ftypes, ftype);
1019

    
1020
            Coercion coercion[] = new Coercion[ftype.size()];
1021
            int sizes[] = new int[ftype.size()];
1022
            for (int i = 0; i < ftype.size(); i++) {
1023
                sizes[i] = -1;
1024
                FeatureAttributeDescriptor ad = ftype.getAttributeDescriptor(i);
1025
                coercion[i] = ad.getDataType().getCoercion();
1026
                if (ad.getDataType().getType() == DataTypes.STRING) {
1027
                    if (ad.getSize() == 0) {
1028
                        // Es un string y no tiene un size asignado.
1029
                        // Lo ponemos a cero para calcularlo.
1030
                        sizes[i] = 0;
1031
                    }
1032
                }
1033
            }
1034
            if (ftype.getDefaultGeometryAttributeName() != null) {
1035
                this.need_calculate_envelope = true;
1036
            }
1037

    
1038
            Locale locale = CSVStoreParameters.getLocale(getCSVParameters());
1039
            taskStatus.message("_loading");
1040
            int count = 0;
1041

    
1042
            int count_errors = 0;
1043

    
1044
            List<String> row = reader.read();
1045

    
1046
            int skipLines = CSVStoreParameters.getSkipLines(getCSVParameters());
1047
            if (skipLines > 0) {
1048
                row = reader.skip(skipLines);
1049
            }
1050
            int limit = CSVStoreParameters.getLimit(getCSVParameters());
1051
            while (row != null) {
1052
                taskStatus.setCurValue(++count);
1053
                FeatureProvider feature = this.createFeatureProvider(ftype);
1054
                for (int i = 0; i < row.size(); i++) {
1055
                    Object rawvalue = row.get(i);
1056
                    try {
1057
                        Object value = null;
1058
                        if (locale != null && coercion[i] instanceof CoercionWithLocale) {
1059
                            value = ((CoercionWithLocale) (coercion[i])).coerce(rawvalue, locale);
1060
                        } else {
1061
                            value = coercion[i].coerce(rawvalue);
1062
                        }
1063
                        feature.set(i, value);
1064
                        if (sizes[i] >= 0 && value instanceof String ) {
1065
                            int x = ((String) value).length();
1066
                            if (sizes[i] < x) {
1067
                                sizes[i] = x;
1068
                            }
1069
                        }
1070
                    } catch (Exception ex) {
1071
                        if (!ignore_errors) {
1072
                            throw ex;
1073
                        }
1074
                        if (count_errors++ < 10) {
1075
                            logger.warn("Can't load value of attribute " + i + " in row " + count + ".", ex);
1076
                        }
1077
                        if (count_errors == 10) {
1078
                            logger.info("Too many errors, suppress messages.");
1079
                        }
1080
                    }
1081
                }
1082
                this.addFeatureProvider(feature);
1083
                if( limit>0 ) {
1084
                    if( limit < this.data.size() ) {
1085
                        break;
1086
                    }
1087
                }
1088
                row = reader.read();
1089
            }
1090
            for (int i = 0; i < ftype.size(); i++) {
1091
                if (sizes[i] > 0) {
1092
                    EditableFeatureAttributeDescriptor efad = ((EditableFeatureAttributeDescriptor) edftype.getAttributeDescriptor(i));
1093
                    efad.setSize(sizes[i]);
1094
                }
1095
            }
1096
            // Volvemos a asignar al store el featuretype, ya que puede
1097
            // haber cambiado.
1098
            ftype = edftype.getNotEditableCopy();
1099
            ftypes = new ArrayList<>();
1100
            ftypes.add(ftype);
1101
            store.setFeatureTypes(ftypes, ftype);
1102

    
1103
            taskStatus.terminate();
1104
        } catch (Exception ex) {
1105
            int lineno = 0;
1106
            if (reader != null) {
1107
                lineno = reader.getLine();
1108
            }
1109
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
1110

    
1111
        } finally {
1112
            if (reader != null) {
1113
                try {
1114
                    reader.close();
1115
                } catch (Exception ex) {
1116
                    // Do nothing
1117
                }
1118
                reader = null;
1119
            }
1120
            if (in != null) {
1121
                try {
1122
                    in.close();
1123
                } catch (Exception ex) {
1124
                    // Do nothing
1125
                }
1126
                in = null;
1127
            }
1128
        }
1129
    }
1130

    
1131
    private static class PossibleDataType {
1132

    
1133
        public boolean possibleInt = true;
1134
        public boolean possibleFloat = true;
1135
        public boolean possibleDouble = true;
1136
        public boolean possibleLong = true;
1137
        public boolean possibleURL = true;
1138
        public boolean possibleDate = true;
1139
        public boolean possibleGeometry = true;
1140
    }
1141

    
1142
    private int[] automaticDetectionOfTypes(String[] headers) throws IOException {
1143
        boolean automatic_types_detection = CSVStoreParameters.getAutomaticTypesDetection(getCSVParameters());
1144
        if (!automatic_types_detection) {
1145
            return null;
1146
        }
1147
        List<PossibleDataType> possibleDataTypes;
1148
        Locale locale;
1149
        int[] types = null;
1150

    
1151
        FileReader in = null;
1152
        SimpleReader reader = null;
1153

    
1154
        try {
1155
            in = new FileReader(this.getCSVParameters().getFile());
1156
            reader = getSimpleReader(in);
1157
            if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
1158
                reader.read();
1159
            }
1160
            possibleDataTypes = new ArrayList<>(headers.length);
1161
            for (String header : headers) {
1162
                possibleDataTypes.add(new PossibleDataType());
1163
            }
1164
            locale = CSVStoreParameters.getLocale(getCSVParameters());
1165
            if (locale == null) {
1166
                locale = Locale.getDefault();
1167
            }
1168
            DataTypesManager typeManager = ToolsLocator.getDataTypesManager();
1169
            CoercionWithLocale toDouble = (CoercionWithLocale) typeManager.getCoercion(DataTypes.DOUBLE);
1170
            CoercionWithLocale toFloat = (CoercionWithLocale) typeManager.getCoercion(DataTypes.FLOAT);
1171
            CoercionWithLocale toDate = (CoercionWithLocale) typeManager.getCoercion(DataTypes.DATE);
1172
            CoercionWithLocale toInt = (CoercionWithLocale) typeManager.getCoercion(DataTypes.INT);
1173
            CoercionWithLocale toLong = (CoercionWithLocale) typeManager.getCoercion(DataTypes.LONG);
1174
            Coercion toGeom = typeManager.getCoercion(DataTypes.GEOMETRY);
1175

    
1176
            List<String> row = reader.read();
1177

    
1178
            while (row != null) {
1179
                for (int i = 0; i < row.size(); i++) {
1180
                    while( possibleDataTypes.size()<row.size() ) {
1181
                        possibleDataTypes.add(new PossibleDataType());
1182
                    }
1183
                    String rawvalue = row.get(i);
1184
                    PossibleDataType possibleDataType = possibleDataTypes.get(i);
1185
                    if (possibleDataType.possibleDouble) {
1186
                        try {
1187
                            toDouble.coerce(rawvalue, locale);
1188
                            possibleDataType.possibleDouble = true;
1189
                        } catch (Exception ex) {
1190
                            possibleDataType.possibleDouble = false;
1191
                        }
1192
                    }
1193
                    if (possibleDataType.possibleFloat) {
1194
                        try {
1195
                            toFloat.coerce(rawvalue, locale);
1196
                            possibleDataType.possibleFloat = true;
1197
                        } catch (Exception ex) {
1198
                            possibleDataType.possibleFloat = false;
1199
                        }
1200
                    }
1201
                    if (possibleDataType.possibleLong) {
1202
                        possibleDataType.possibleLong = isValidLong(rawvalue);
1203
                    }
1204
                    if (possibleDataType.possibleInt) {
1205
                        possibleDataType.possibleInt = isValidInteger(rawvalue);
1206
                    }
1207
                    if (possibleDataType.possibleDate) {
1208
                        try {
1209
                            toDate.coerce(rawvalue, locale);
1210
                            possibleDataType.possibleDate = true;
1211
                        } catch (Exception ex) {
1212
                            possibleDataType.possibleDate = false;
1213
                        }
1214
                    }
1215
                    if (possibleDataType.possibleURL) {
1216
                        try {
1217
                            new URL((String) rawvalue);
1218
                            possibleDataType.possibleURL = true;
1219
                        } catch (Exception ex) {
1220
                            possibleDataType.possibleURL = false;
1221
                        }
1222
                    }
1223
                    if (possibleDataType.possibleGeometry) {
1224
                        try {
1225
                            toGeom.coerce((String) rawvalue);
1226
                            possibleDataType.possibleGeometry = true;
1227
                        } catch (Exception ex) {
1228
                            possibleDataType.possibleGeometry = false;
1229
                        }
1230
                    }
1231
                }
1232
                row = reader.read();
1233
            }
1234
            int n = 0;
1235
            types = new int[possibleDataTypes.size()];
1236
            for (PossibleDataType possibleDataType : possibleDataTypes) {
1237
                if (possibleDataType.possibleInt) {
1238
                    types[n++] = DataTypes.INT;
1239
                    continue;
1240
                }
1241
                if (possibleDataType.possibleLong) {
1242
                    types[n++] = DataTypes.LONG;
1243
                    continue;
1244
                }
1245
                if (possibleDataType.possibleFloat) {
1246
                    // Forzamos los float a double para evitar perder precision
1247
                    types[n++] = DataTypes.DOUBLE;
1248
                    continue;
1249
                }
1250
                if (possibleDataType.possibleDouble) {
1251
                    types[n++] = DataTypes.DOUBLE;
1252
                    continue;
1253
                }
1254
                if (possibleDataType.possibleURL) {
1255
                    types[n++] = DataTypes.URL;
1256
                    continue;
1257
                }
1258
                if (possibleDataType.possibleDate) {
1259
                    types[n++] = DataTypes.DATE;
1260
                    continue;
1261
                }
1262
                if (possibleDataType.possibleGeometry) {
1263
                    types[n++] = DataTypes.GEOMETRY;
1264
                    continue;
1265
                }
1266
                types[n++] = DataTypes.STRING;
1267
            }
1268
        } catch (Exception ex) {
1269
            int lineno = 0;
1270
            if (reader != null) {
1271
                lineno = reader.getLine();
1272
            }
1273
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
1274

    
1275
        } finally {
1276
            IOUtils.closeQuietly(reader);
1277
            IOUtils.closeQuietly(in);
1278
        }
1279
        return types;
1280
    }
1281

    
1282
    private boolean isValidLong(String s) {
1283
        if (s == null) {
1284
            return true;
1285
        }
1286
        s = s.trim().toLowerCase();
1287
        if (s.isEmpty()) {
1288
            return true;
1289
        }
1290
        try {
1291
            if (s.startsWith("0x")) {
1292
                Long.valueOf(s.substring(2), 16);
1293
            } else {
1294
                Long.valueOf(s);
1295
            }
1296
            return true;
1297
        } catch (Exception ex) {
1298
            return false;
1299
        }
1300
    }
1301

    
1302
    private boolean isValidInteger(String s) {
1303
        if (s == null) {
1304
            return true;
1305
        }
1306
        s = s.trim().toLowerCase();
1307
        if (s.isEmpty()) {
1308
            return true;
1309
        }
1310
        try {
1311
            if (s.startsWith("0x")) {
1312
                Integer.valueOf(s.substring(2), 16);
1313
            } else {
1314
                Integer.valueOf(s);
1315
            }
1316
            return true;
1317
        } catch (Exception ex) {
1318
            return false;
1319
        }
1320
    }
1321

    
1322
}