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

History | View | Annotate | Download (50.1 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.FileReader;
27
import java.io.FileWriter;
28
import java.io.IOException;
29
import java.net.URL;
30
import java.text.SimpleDateFormat;
31
import java.util.ArrayList;
32
import java.util.HashMap;
33
import java.util.Iterator;
34
import java.util.List;
35
import java.util.Locale;
36

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

    
107
public class CSVStoreProvider extends AbstractMemoryStoreProvider implements
108
        ResourceConsumer {
109

    
110
    private static final Logger logger = LoggerFactory.getLogger(CSVStoreProvider.class);
111

    
112
    public static final String NAME = "CSV";
113
    public static final String DESCRIPTION = "CSV file";
114

    
115
    public static final String METADATA_DEFINITION_NAME = NAME;
116

    
117
    private ResourceProvider resource;
118

    
119
    private long counterNewsOIDs = 0;
120
    private Envelope envelope;
121
    private boolean need_calculate_envelope = false;
122
    private SimpleTaskStatus taskStatus;
123

    
124
    public CSVStoreProvider(CSVStoreParameters parameters,
125
            DataStoreProviderServices storeServices) throws InitializeException {
126
        super(
127
                parameters,
128
                storeServices,
129
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
130
        );
131

    
132
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
133
        this.taskStatus = manager.createDefaultSimpleTaskStatus("CSV");
134

    
135
        counterNewsOIDs = 0;
136

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

    
143
        resource.addConsumer(this);
144
        initializeFeatureTypes();
145
    }
146

    
147
    private CSVStoreParameters getCSVParameters() {
148
        return (CSVStoreParameters) this.getParameters();
149
    }
150

    
151
    public String getProviderName() {
152
        return NAME;
153
    }
154

    
155
    public boolean allowWrite() {
156
        return false;
157
    }
158

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

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

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

    
202
    }
203

    
204
    class Writer {
205

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

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

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

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

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

    
330
        }
331

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

    
354
        public Envelope getEnvelope() {
355
            return this.envelope;
356
        }
357
    }
358

    
359
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
360

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

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

    
409
                private CsvPreference getCSVPreferences() {
410
                    CSVReader reader = new CSVReader(getCSVParameters());
411
                    return reader.getCSVPreferences();
412
                }
413

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

    
424
    public boolean closeResourceRequested(ResourceProvider resource) {
425
        return true;
426
    }
427

    
428
    public int getOIDType() {
429
        return DataTypes.LONG;
430
    }
431

    
432
    public boolean supportsAppendMode() {
433
        return false;
434
    }
435

    
436
    public void append(FeatureProvider featureProvider) {
437
        throw new UnsupportedOperationException();
438
    }
439

    
440
    public void beginAppend() {
441
        throw new UnsupportedOperationException();
442
    }
443

    
444
    public void endAppend() {
445
        throw new UnsupportedOperationException();
446
    }
447

    
448
    public void saveToState(PersistentState state) throws PersistenceException {
449
        throw new NotYetImplemented();
450
    }
451

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

    
456
    public Object createNewOID() {
457
        return new Long(counterNewsOIDs++);
458
    }
459

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

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

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

    
496
        this.need_calculate_envelope = false;
497
        return this.envelope;
498
    }
499

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

    
518
    public void resourceChanged(ResourceProvider resource) {
519
        this.getStoreServices().notifyChange(
520
                DataStoreNotification.RESOURCE_CHANGED,
521
                resource);
522
    }
523

    
524
    public Object getSourceId() {
525
        return this.getCSVParameters().getFile();
526
    }
527

    
528
    public String getName() {
529
        String name = this.getCSVParameters().getFile().getName();
530
        return FilenameUtils.getBaseName(name);
531
    }
532

    
533
    public String getFullName() {
534
        return this.getCSVParameters().getFile().getAbsolutePath();
535
    }
536

    
537
    public ResourceProvider getResource() {
538
        return resource;
539
    }
540

    
541
    private boolean isEmpty(String s) {
542
        if (s == null) {
543
            return true;
544
        }
545
        return s.trim().length() == 0;
546
    }
547

    
548
    private class FieldTypeParser {
549

    
550
        public String name = null;
551
        public int type = DataTypes.STRING;
552
        public int size = 0;
553
        public boolean allowNulls = true;
554
        public int geometryType = Geometry.TYPES.GEOMETRY;
555

    
556
        private String typename = "string";
557

    
558
        FieldTypeParser() {
559
        }
560

    
561
        private int getType(String value) {
562
            DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
563
            return dataTypesManager.getType(typename);
564
        }
565

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

    
574
        public void copyFrom(FieldTypeParser other) {
575
            name = other.name;
576
            type = other.type;
577
            size = other.size;
578
            allowNulls = other.allowNulls;
579
            geometryType = other.geometryType;
580
        }
581

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

    
658
            if (this.type != DataTypes.STRING) {
659
                this.size = 0;
660
            }
661
            return true;
662
        }
663

    
664
    }
665

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

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

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

    
692
        }
693

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

    
752
    static class PointAttributeEmulator implements FeatureAttributeEmulator {
753

    
754
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
755

    
756
        private static final int XNAME = 0;
757
        private static final int YNAME = 1;
758
        private static final int ZNAME = 2;
759

    
760
        private final GeometryManager geommgr;
761
        private final String[] fieldNames;
762
        private final Coercion toDouble;
763
        private final DataType dataType;
764
        private int errorcount = 0;
765

    
766
        public PointAttributeEmulator(String[] pointDimensionNames) {
767
            if (pointDimensionNames.length > 2) {
768
                this.fieldNames = new String[3];
769
                this.fieldNames[ZNAME] = pointDimensionNames[2];
770
            } else {
771
                this.fieldNames = new String[2];
772
            }
773
            this.fieldNames[XNAME] = pointDimensionNames[0];
774
            this.fieldNames[YNAME] = pointDimensionNames[1];
775
            this.geommgr = GeometryLocator.getGeometryManager();
776
            DataTypesManager datatypeManager = ToolsLocator.getDataTypesManager();
777

    
778
            this.toDouble = datatypeManager.getCoercion(DataTypes.DOUBLE);
779
            this.dataType = datatypeManager.get(DataTypes.GEOMETRY);
780
        }
781

    
782
        public Object get(Feature feature) {
783
            try {
784
                Object valueX = feature.get(this.fieldNames[XNAME]);
785
                valueX = toDouble.coerce(valueX);
786
                if (valueX == null) {
787
                    return null;
788
                }
789
                Object valueY = feature.get(this.fieldNames[YNAME]);
790
                valueY = toDouble.coerce(valueY);
791
                if (valueY == null) {
792
                    return null;
793
                }
794
                Object valueZ = null;
795
                if (this.fieldNames.length > 2) {
796
                    valueZ = toDouble.coerce(feature.get(this.fieldNames[ZNAME]));
797
                    if (valueZ == null) {
798
                        return null;
799
                    }
800
                }
801

    
802
                double x = ((Double) valueX).doubleValue();
803
                double y = ((Double) valueY).doubleValue();
804
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
805
                if (this.fieldNames.length > 2) {
806
                    double z = ((Double) valueZ).doubleValue();
807
                    point.setCoordinateAt(2, z);
808
                }
809
                return point;
810
            } catch (Exception ex) {
811
                if (++errorcount < 5) {
812
                    logger.warn("[" + errorcount + "] Can't create point in CSV provider. XNAME='"
813
                            + this.fieldNames[XNAME] + "', YNAME='" + this.fieldNames[XNAME] + "' feature=" + feature.toString(), ex);
814
                }
815
                return null;
816
            }
817
        }
818

    
819
        public void set(EditableFeature feature, Object value) {
820
            if (value == null) {
821
                return;
822
            }
823
            Point point = null;
824
            if (value instanceof MultiPoint) {
825
                point = (Point) ((MultiPoint) value).getPrimitiveAt(0);
826
            } else {
827
                point = (Point) value;
828
            }
829
            feature.set(this.fieldNames[XNAME], point.getX());
830
            feature.set(this.fieldNames[YNAME], point.getY());
831
            if (this.fieldNames.length > 2) {
832
                feature.set(this.fieldNames[ZNAME], point.getCoordinateAt(2));
833
            }
834
        }
835

    
836
        public boolean allowSetting() {
837
            return true;
838
        }
839

    
840
        public String[] getRequiredFieldNames() {
841
            return this.fieldNames;
842
        }
843

    
844
    }
845

    
846
    static class ToPointEvaluaror extends AbstractEvaluator {
847

    
848
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
849

    
850
        private GeometryManager geommgr = null;
851
        private String xname = null;
852
        private String yname = null;
853
        private String zname = null;
854
        private Coercion toDouble;
855
        private int errorcount = 0;
856

    
857
        ToPointEvaluaror(String[] pointDimensionNames) {
858
            this.xname = pointDimensionNames[0];
859
            this.yname = pointDimensionNames[1];
860
            if (pointDimensionNames.length > 2) {
861
                this.zname = pointDimensionNames[2];
862
            }
863
            this.geommgr = GeometryLocator.getGeometryManager();
864
            this.toDouble = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.DOUBLE);
865
        }
866

    
867
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
868
            try {
869
                double x = ((Double) toDouble.coerce(data.getDataValue(xname))).doubleValue();
870
                double y = ((Double) toDouble.coerce(data.getDataValue(yname))).doubleValue();
871
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
872
                if (zname != null) {
873
                    double z = ((Double) toDouble.coerce(data.getDataValue(zname))).doubleValue();
874
                    point.setCoordinateAt(2, z);
875
                }
876
                return point;
877
            } catch (Exception ex) {
878
                if (++errorcount < 5) {
879
                    logger.warn("[" + errorcount + "] Can't create point in CSV provider. XNAME='"
880
                            + xname + "', YNAME='" + yname + "', ZNAME='" + zname + "', data=" + data.toString());
881
                }
882
                return null;
883
            }
884
        }
885

    
886
        public String getName() {
887
            return "ToPointEvaluaror";
888
        }
889

    
890
    }
891

    
892
    private SimpleReader getSimpleReader(FileReader in) {
893
        SimpleReader reader;
894
        if (CSVStoreParameters.getRawFieldsDefinition(getCSVParameters()) != null) {
895
            reader = new FixedLenReader(in, getCSVParameters());
896
        } else {
897
            reader = new CSVReader(in, getCSVParameters());
898
        }
899
        return reader;
900
    }
901

    
902
    private String getFixedHeader(int column) {
903
        char[] header = new char[3];
904

    
905
        String s = String.format("%03d", column);
906
        header[0] = (char) (s.charAt(0) + 17);
907
        header[1] = (char) (s.charAt(1) + 17);
908
        header[2] = (char) (s.charAt(2) + 17);
909
        return String.valueOf(header);
910
    }
911

    
912
    private String[] getFixedHeaders(int count) {
913
        String[] headers = new String[count];
914
        for (int i = 0; i < headers.length; i++) {
915
            headers[i] = getFixedHeader(i);
916
        }
917
        return headers;
918
    }
919

    
920
    private void loadFeatures() {
921
        FileReader in = null;
922
        SimpleReader reader = null;
923
        try {
924
            String headers[] = null;
925
            FeatureStoreProviderServices store = this.getStoreServices();
926

    
927
            boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
928

    
929
            in = new FileReader(this.getCSVParameters().getFile());
930

    
931
            reader = getSimpleReader(in);
932

    
933
            headers = CSVStoreParameters.getHeaders(getCSVParameters());
934
            if (headers == null) {
935
                if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
936
                    headers = reader.getHeader();
937
                    if (headers == null) {
938
                        if (CSVStoreParameters.getIgnoreErrors(getCSVParameters())) {
939
                            headers = getFixedHeaders(reader.getColumnsCount());
940
                        } else {
941
                            String msg = "Can't retrieve header from csv file '"
942
                                    + this.getCSVParameters().getFile()
943
                                    .getAbsolutePath()
944
                                    + "' and not specified in the parameters.";
945
                            logger.warn(msg);
946
                            throw new RuntimeException(msg);
947
                        }
948
                    }
949
                } else {
950
                    headers = getFixedHeaders(reader.getColumnsCount());
951
                }
952
            } else {
953
                if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
954
                    reader.getHeader(); // Skip and ignore the header of file
955
                }
956
            }
957

    
958
            int[] detectedTypes = automaticDetectionOfTypes(headers);
959
            if( detectedTypes!=null && detectedTypes.length>headers.length ) {
960
                // Se han detectado mas columnas que las que hay en la cabezera,
961
                // a?adimos mas columnas a la cabezera.
962
                String[] headers2 = new String[detectedTypes.length];
963
                for( int i=0; i<headers2.length; i++ ) {
964
                    if( i<headers.length ) {
965
                        headers2[i] = headers[i];
966
                    } else {
967
                        headers2[i] = getFixedHeader(i);
968
                    }
969
                }
970
                headers = headers2;
971
            }
972
            // Initialize the feature types
973
            EditableFeatureType edftype = this.getFeatureType(headers, detectedTypes);
974
            FeatureType ftype = edftype.getNotEditableCopy();
975
            List<FeatureType> ftypes = new ArrayList<>();
976
            ftypes.add(ftype);
977
            store.setFeatureTypes(ftypes, ftype);
978

    
979
            Coercion coercion[] = new Coercion[ftype.size()];
980
            int sizes[] = new int[ftype.size()];
981
            for (int i = 0; i < ftype.size(); i++) {
982
                sizes[i] = -1;
983
                FeatureAttributeDescriptor ad = ftype.getAttributeDescriptor(i);
984
                coercion[i] = ad.getDataType().getCoercion();
985
                if (ad.getDataType().getType() == DataTypes.STRING) {
986
                    if (ad.getSize() == 0) {
987
                        // Es un string y no tiene un size asignado.
988
                        // Lo ponemos a cero para calcularlo.
989
                        sizes[i] = 0;
990
                    }
991
                }
992
            }
993
            if (ftype.getDefaultGeometryAttributeName() != null) {
994
                this.need_calculate_envelope = true;
995
            }
996

    
997
            Locale locale = CSVStoreParameters.getLocale(getCSVParameters());
998
            taskStatus.message("_loading");
999
            int count = 0;
1000

    
1001
            int count_errors = 0;
1002

    
1003
            List<String> row = reader.read();
1004

    
1005
            int skipLines = CSVStoreParameters.getSkipLines(getCSVParameters());
1006
            if (skipLines > 0) {
1007
                row = reader.skip(skipLines);
1008
            }
1009
            int limit = CSVStoreParameters.getLimit(getCSVParameters());
1010
            while (row != null) {
1011
                taskStatus.setCurValue(++count);
1012
                FeatureProvider feature = this.createFeatureProvider(ftype);
1013
                for (int i = 0; i < row.size(); i++) {
1014
                    Object rawvalue = row.get(i);
1015
                    try {
1016
                        Object value = null;
1017
                        if (locale != null && coercion[i] instanceof CoercionWithLocale) {
1018
                            value = ((CoercionWithLocale) (coercion[i])).coerce(rawvalue, locale);
1019
                        } else {
1020
                            value = coercion[i].coerce(rawvalue);
1021
                        }
1022
                        feature.set(i, value);
1023
                        if (sizes[i] >= 0 && value instanceof String ) {
1024
                            int x = ((String) value).length();
1025
                            if (sizes[i] < x) {
1026
                                sizes[i] = x;
1027
                            }
1028
                        }
1029
                    } catch (Exception ex) {
1030
                        if (!ignore_errors) {
1031
                            throw ex;
1032
                        }
1033
                        if (count_errors++ < 10) {
1034
                            logger.warn("Can't load value of attribute " + i + " in row " + count + ".", ex);
1035
                        }
1036
                        if (count_errors == 10) {
1037
                            logger.info("Too many errors, suppress messages.");
1038
                        }
1039
                    }
1040
                }
1041
                this.addFeatureProvider(feature);
1042
                if( limit>0 ) {
1043
                    if( limit < this.data.size() ) {
1044
                        break;
1045
                    }
1046
                }
1047
                row = reader.read();
1048
            }
1049
            for (int i = 0; i < ftype.size(); i++) {
1050
                if (sizes[i] > 0) {
1051
                    EditableFeatureAttributeDescriptor efad = ((EditableFeatureAttributeDescriptor) edftype.getAttributeDescriptor(i));
1052
                    efad.setSize(sizes[i]);
1053
                }
1054
            }
1055
            // Volvemos a asignar al store el featuretype, ya que puede
1056
            // haber cambiado.
1057
            ftype = edftype.getNotEditableCopy();
1058
            ftypes = new ArrayList<>();
1059
            ftypes.add(ftype);
1060
            store.setFeatureTypes(ftypes, ftype);
1061

    
1062
            taskStatus.terminate();
1063
        } catch (Exception ex) {
1064
            int lineno = 0;
1065
            if (reader != null) {
1066
                lineno = reader.getLine();
1067
            }
1068
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
1069

    
1070
        } finally {
1071
            if (reader != null) {
1072
                try {
1073
                    reader.close();
1074
                } catch (Exception ex) {
1075
                    // Do nothing
1076
                }
1077
                reader = null;
1078
            }
1079
            if (in != null) {
1080
                try {
1081
                    in.close();
1082
                } catch (Exception ex) {
1083
                    // Do nothing
1084
                }
1085
                in = null;
1086
            }
1087
        }
1088
    }
1089

    
1090
    private static class PossibleDataType {
1091

    
1092
        public boolean possibleInt = true;
1093
        public boolean possibleFloat = true;
1094
        public boolean possibleDouble = true;
1095
        public boolean possibleLong = true;
1096
        public boolean possibleURL = true;
1097
        public boolean possibleDate = true;
1098
        public boolean possibleGeometry = true;
1099
    }
1100

    
1101
    private int[] automaticDetectionOfTypes(String[] headers) throws IOException {
1102
        boolean automatic_types_detection = CSVStoreParameters.getAutomaticTypesDetection(getCSVParameters());
1103
        if (!automatic_types_detection) {
1104
            return null;
1105
        }
1106
        List<PossibleDataType> possibleDataTypes;
1107
        Locale locale;
1108
        int[] types = null;
1109

    
1110
        FileReader in = null;
1111
        SimpleReader reader = null;
1112

    
1113
        try {
1114
            in = new FileReader(this.getCSVParameters().getFile());
1115
            reader = getSimpleReader(in);
1116
            if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
1117
                reader.read();
1118
            }
1119
            possibleDataTypes = new ArrayList<>(headers.length);
1120
            for (String header : headers) {
1121
                possibleDataTypes.add(new PossibleDataType());
1122
            }
1123
            locale = CSVStoreParameters.getLocale(getCSVParameters());
1124
            if (locale == null) {
1125
                locale = Locale.getDefault();
1126
            }
1127
            DataTypesManager typeManager = ToolsLocator.getDataTypesManager();
1128
            CoercionWithLocale toDouble = (CoercionWithLocale) typeManager.getCoercion(DataTypes.DOUBLE);
1129
            CoercionWithLocale toFloat = (CoercionWithLocale) typeManager.getCoercion(DataTypes.FLOAT);
1130
            CoercionWithLocale toDate = (CoercionWithLocale) typeManager.getCoercion(DataTypes.DATE);
1131
            CoercionWithLocale toInt = (CoercionWithLocale) typeManager.getCoercion(DataTypes.INT);
1132
            CoercionWithLocale toLong = (CoercionWithLocale) typeManager.getCoercion(DataTypes.LONG);
1133
            Coercion toGeom = typeManager.getCoercion(DataTypes.GEOMETRY);
1134

    
1135
            List<String> row = reader.read();
1136

    
1137
            while (row != null) {
1138
                for (int i = 0; i < row.size(); i++) {
1139
                    while( possibleDataTypes.size()<row.size() ) {
1140
                        possibleDataTypes.add(new PossibleDataType());
1141
                    }
1142
                    String rawvalue = row.get(i);
1143
                    PossibleDataType possibleDataType = possibleDataTypes.get(i);
1144
                    if (possibleDataType.possibleDouble) {
1145
                        try {
1146
                            toDouble.coerce(rawvalue, locale);
1147
                            possibleDataType.possibleDouble = true;
1148
                        } catch (Exception ex) {
1149
                            possibleDataType.possibleDouble = false;
1150
                        }
1151
                    }
1152
                    if (possibleDataType.possibleFloat) {
1153
                        try {
1154
                            toFloat.coerce(rawvalue, locale);
1155
                            possibleDataType.possibleFloat = true;
1156
                        } catch (Exception ex) {
1157
                            possibleDataType.possibleFloat = false;
1158
                        }
1159
                    }
1160
                    if (possibleDataType.possibleLong) {
1161
                        possibleDataType.possibleLong = isValidLong(rawvalue);
1162
                    }
1163
                    if (possibleDataType.possibleInt) {
1164
                        possibleDataType.possibleInt = isValidInteger(rawvalue);
1165
                    }
1166
                    if (possibleDataType.possibleDate) {
1167
                        try {
1168
                            toDate.coerce(rawvalue, locale);
1169
                            possibleDataType.possibleDate = true;
1170
                        } catch (Exception ex) {
1171
                            possibleDataType.possibleDate = false;
1172
                        }
1173
                    }
1174
                    if (possibleDataType.possibleURL) {
1175
                        try {
1176
                            new URL((String) rawvalue);
1177
                            possibleDataType.possibleURL = true;
1178
                        } catch (Exception ex) {
1179
                            possibleDataType.possibleURL = false;
1180
                        }
1181
                    }
1182
                    if (possibleDataType.possibleGeometry) {
1183
                        try {
1184
                            toGeom.coerce((String) rawvalue);
1185
                            possibleDataType.possibleGeometry = true;
1186
                        } catch (Exception ex) {
1187
                            possibleDataType.possibleGeometry = false;
1188
                        }
1189
                    }
1190
                }
1191
                row = reader.read();
1192
            }
1193
            int n = 0;
1194
            types = new int[possibleDataTypes.size()];
1195
            for (PossibleDataType possibleDataType : possibleDataTypes) {
1196
                if (possibleDataType.possibleInt) {
1197
                    types[n++] = DataTypes.INT;
1198
                    continue;
1199
                }
1200
                if (possibleDataType.possibleLong) {
1201
                    types[n++] = DataTypes.LONG;
1202
                    continue;
1203
                }
1204
                if (possibleDataType.possibleFloat) {
1205
                    // Forzamos los float a double para evitar perder precision
1206
                    types[n++] = DataTypes.DOUBLE;
1207
                    continue;
1208
                }
1209
                if (possibleDataType.possibleDouble) {
1210
                    types[n++] = DataTypes.DOUBLE;
1211
                    continue;
1212
                }
1213
                if (possibleDataType.possibleURL) {
1214
                    types[n++] = DataTypes.URL;
1215
                    continue;
1216
                }
1217
                if (possibleDataType.possibleDate) {
1218
                    types[n++] = DataTypes.DATE;
1219
                    continue;
1220
                }
1221
                if (possibleDataType.possibleGeometry) {
1222
                    types[n++] = DataTypes.GEOMETRY;
1223
                    continue;
1224
                }
1225
                types[n++] = DataTypes.STRING;
1226
            }
1227
        } catch (Exception ex) {
1228
            int lineno = 0;
1229
            if (reader != null) {
1230
                lineno = reader.getLine();
1231
            }
1232
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
1233

    
1234
        } finally {
1235
            IOUtils.closeQuietly(reader);
1236
            IOUtils.closeQuietly(in);
1237
        }
1238
        return types;
1239
    }
1240

    
1241
    private boolean isValidLong(String s) {
1242
        if (s == null) {
1243
            return true;
1244
        }
1245
        s = s.trim().toLowerCase();
1246
        if (s.isEmpty()) {
1247
            return true;
1248
        }
1249
        try {
1250
            if (s.startsWith("0x")) {
1251
                Long.valueOf(s.substring(2), 16);
1252
            } else {
1253
                Long.valueOf(s);
1254
            }
1255
            return true;
1256
        } catch (Exception ex) {
1257
            return false;
1258
        }
1259
    }
1260

    
1261
    private boolean isValidInteger(String s) {
1262
        if (s == null) {
1263
            return true;
1264
        }
1265
        s = s.trim().toLowerCase();
1266
        if (s.isEmpty()) {
1267
            return true;
1268
        }
1269
        try {
1270
            if (s.startsWith("0x")) {
1271
                Integer.valueOf(s.substring(2), 16);
1272
            } else {
1273
                Integer.valueOf(s);
1274
            }
1275
            return true;
1276
        } catch (Exception ex) {
1277
            return false;
1278
        }
1279
    }
1280

    
1281
}