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.lib / src / main / java / org / gvsig / fmap / dal / feature / spi / simpleprovider / SimpleSequentialReaderStoreProvider.java @ 44242

History | View | Annotate | Download (28.3 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
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA 02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.dal.feature.spi.simpleprovider;
25

    
26
import java.io.File;
27
import java.io.IOException;
28
import java.util.ArrayList;
29
import java.util.HashMap;
30
import java.util.Iterator;
31
import java.util.List;
32
import java.util.Locale;
33

    
34
import org.apache.commons.lang3.StringUtils;
35
import org.cresques.cts.IProjection;
36
import org.gvsig.fmap.dal.DALLocator;
37
import org.gvsig.fmap.dal.DataManager;
38
import org.gvsig.fmap.dal.DataServerExplorer;
39
import org.gvsig.fmap.dal.DataStore;
40
import org.gvsig.fmap.dal.DataStoreNotification;
41
import org.gvsig.fmap.dal.DataTypes;
42
import org.gvsig.fmap.dal.FileHelper;
43
import org.gvsig.fmap.dal.exception.DataException;
44
import org.gvsig.fmap.dal.exception.InitializeException;
45
import org.gvsig.fmap.dal.exception.OpenException;
46
import org.gvsig.fmap.dal.exception.ReadException;
47
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
48
import org.gvsig.fmap.dal.feature.EditableFeature;
49
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
50
import org.gvsig.fmap.dal.feature.EditableFeatureType;
51
import org.gvsig.fmap.dal.feature.Feature;
52
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
53
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
54
import org.gvsig.fmap.dal.feature.FeatureStore;
55
import org.gvsig.fmap.dal.feature.FeatureType;
56
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
57
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
58
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
59
import org.gvsig.fmap.dal.feature.spi.memory.AbstractMemoryStoreProvider;
60
import org.gvsig.fmap.dal.resource.file.FileResource;
61
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
62
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
63
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
64
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
65
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
66
import org.gvsig.fmap.geom.Geometry;
67
import org.gvsig.fmap.geom.GeometryLocator;
68
import org.gvsig.fmap.geom.GeometryManager;
69
import org.gvsig.fmap.geom.GeometryUtils;
70
import org.gvsig.fmap.geom.aggregate.MultiPoint;
71
import org.gvsig.fmap.geom.primitive.Envelope;
72
import org.gvsig.fmap.geom.primitive.Point;
73
import org.gvsig.fmap.geom.type.GeometryType;
74
import org.gvsig.tools.ToolsLocator;
75
import org.gvsig.tools.dataTypes.CoercionException;
76
import org.gvsig.tools.dataTypes.DataTypesManager;
77
import org.gvsig.tools.dataTypes.DataTypesManager.Coercion;
78
import org.gvsig.tools.dataTypes.DataTypesManager.CoercionWithLocale;
79
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
80
import org.gvsig.tools.exception.BaseException;
81
import org.gvsig.tools.task.SimpleTaskStatus;
82
import org.gvsig.tools.task.TaskStatusManager;
83
import org.gvsig.tools.visitor.VisitCanceledException;
84
import org.gvsig.tools.visitor.Visitor;
85
import org.slf4j.Logger;
86
import org.slf4j.LoggerFactory;
87

    
88
@SuppressWarnings("UseSpecificCatch")
89
public class SimpleSequentialReaderStoreProvider extends AbstractMemoryStoreProvider implements
90
        ResourceConsumer {
91

    
92
    private static final Logger LOGGER = LoggerFactory.getLogger(SimpleSequentialReaderStoreProvider.class);
93

    
94

    
95
    private final ResourceProvider resource;
96

    
97
    private long counterNewsOIDs = 0;
98
    private Envelope envelope;
99
    private boolean need_calculate_envelope = false;
100
    private final SimpleTaskStatus taskStatus;
101
    private String name = "";
102
    private final SimpleSequentialReaderFactory readerFactory;
103

    
104
    public SimpleSequentialReaderStoreProvider(
105
            SimpleSequentialReaderFactory readerFactory,
106
            SimpleSequentialReaderStoreParameters parameters,
107
            DataStoreProviderServices storeServices
108
        ) throws InitializeException {
109
        super(
110
                parameters,
111
                storeServices,
112
                FileHelper.newMetadataContainer(readerFactory.getName())
113
        );
114
        this.readerFactory = readerFactory;
115
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
116
        this.taskStatus = manager.createDefaultSimpleTaskStatus(readerFactory.getName());
117

    
118
        counterNewsOIDs = 0;
119

    
120
        File file = getParameters().getFile();
121
        resource = this.createResource(
122
                FileResource.NAME,
123
                new Object[]{file.getAbsolutePath()}
124
        );
125

    
126
        resource.addConsumer(this);
127
        initializeFeatureTypes();
128
    }
129

    
130
    @Override
131
    public SimpleSequentialReaderStoreParameters getParameters() {
132
        return (SimpleSequentialReaderStoreParameters) super.getParameters();
133
    }
134

    
135
    @Override
136
    public String getProviderName() {
137
        if( this.readerFactory==null ) {
138
            return "unknown";
139
        }
140
        return this.readerFactory.getName();
141
    }
142

    
143
    @Override
144
    public boolean allowWrite() {
145
        return false;
146
    }
147

    
148
    private String getFullFileName() {
149
        // Usar solo para mostrar mensajes en el logger.
150
        String s;
151
        try {
152
            s = getParameters().getFile().getAbsolutePath();
153
        } catch (Exception e2) {
154
            s = "(unknow)";
155
        }
156
        return s;
157
    }
158

    
159
    @Override
160
    public void open() throws OpenException {
161
        if ( this.data != null ) {
162
            return;
163
        }
164
        this.data = new ArrayList<>();
165
        resource.setData(new HashMap());
166
        counterNewsOIDs = 0;
167
        try {
168
            loadFeatures();
169
        } catch (RuntimeException e) {
170
            LOGGER.warn("Can't load features from '"+getProviderName()+"' file '" + getFullFileName() + "'.", e);
171
            throw e;
172
        } catch (Exception e) {
173
            LOGGER.warn("Can't load features from '"+getProviderName()+"' file '" + getFullFileName() + "'.", e);
174
            throw new RuntimeException(e);
175
        }
176
    }
177

    
178
    @Override
179
    public DataServerExplorer getExplorer() throws ReadException {
180
        DataManager manager = DALLocator.getDataManager();
181
        FilesystemServerExplorerParameters params;
182
        try {
183
            params = (FilesystemServerExplorerParameters) manager
184
                    .createServerExplorerParameters(FilesystemServerExplorer.NAME);
185
            params.setRoot(this.getParameters().getFile().getParent());
186
            return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
187
        } catch (DataException | ValidateDataParametersException e) {
188
            throw new ReadException(this.getProviderName(), e);
189
        }
190

    
191
    }
192

    
193
    @Override
194
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
195
        throw new UnsupportedOperationException();
196
    }
197

    
198
    @Override
199
    public boolean closeResourceRequested(ResourceProvider resource) {
200
        return true;
201
    }
202

    
203
    @Override
204
    public int getOIDType() {
205
        return DataTypes.LONG;
206
    }
207

    
208
    @Override
209
    public boolean supportsAppendMode() {
210
        return false;
211
    }
212

    
213
    @Override
214
    public void append(FeatureProvider featureProvider) {
215
        throw new UnsupportedOperationException();
216
    }
217

    
218
    @Override
219
    public void beginAppend() {
220
        throw new UnsupportedOperationException();
221
    }
222

    
223
    @Override
224
    public void endAppend() {
225
        throw new UnsupportedOperationException();
226
    }
227

    
228
    @Override
229
    public Object createNewOID() {
230
        return counterNewsOIDs++;
231
    }
232

    
233
    protected void initializeFeatureTypes() throws InitializeException {
234
        try {
235
            this.open();
236
        } catch (OpenException e) {
237
            throw new InitializeException(this.getProviderName(), e);
238
        }
239
    }
240

    
241
    @Override
242
    public Envelope getEnvelope() throws DataException {
243
        this.open();
244
        if ( this.envelope != null ) {
245
            return this.envelope;
246
        }
247
        if ( !this.need_calculate_envelope ) {
248
            return null;
249
        }
250
        FeatureStore fs = this.getFeatureStore();
251
        FeatureType ft = fs.getDefaultFeatureType();
252
        FeatureAttributeDescriptor fad = ft.getAttributeDescriptor(ft.getDefaultGeometryAttributeIndex());
253

    
254
        try {
255
            this.envelope = GeometryLocator.getGeometryManager().createEnvelope(fad.getGeomType().getSubType());
256
            fs.accept(new Visitor() {
257
                @Override
258
                public void visit(Object obj) throws VisitCanceledException, BaseException {
259
                    Feature f = (Feature) obj;
260
                    Geometry geom = f.getDefaultGeometry();
261
                    if ( geom != null ) {
262
                        envelope.add(geom.getEnvelope());
263
                    }
264
                }
265
            });
266
        } catch (BaseException e) {
267
            LOGGER.warn("Can't calculate the envelope of '"+getProviderName()+"' file '" + this.getFullName() + "'.", e);
268
            this.envelope = null;
269
        }
270

    
271
        this.need_calculate_envelope = false;
272
        return this.envelope;
273
    }
274

    
275
    @Override
276
    public Object getDynValue(String name) throws DynFieldNotFoundException {
277
        if ( DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name) ) {
278
            try {
279
                return this.getEnvelope();
280
            } catch (DataException e) {
281
                return null;
282
            }
283
        } else {
284
            if ( DataStore.METADATA_CRS.equalsIgnoreCase(name) ) {
285
                IProjection pro = this.getParameters().getCRS();
286
                if ( pro != null ) {
287
                    return pro;
288
                }
289
                FeatureType type;
290
                try {
291
                    type = this.getStoreServices().getDefaultFeatureType();
292
                    pro = type.getDefaultSRS();
293
                    if( pro!=null ) {
294
                        return pro;
295
                    }
296
                } catch (DataException ex) {
297
                }
298
            }
299
        }
300
        return super.getDynValue(name);
301
    }
302

    
303
    @Override
304
    public void resourceChanged(ResourceProvider resource) {
305
        this.getStoreServices().notifyChange(
306
                DataStoreNotification.RESOURCE_CHANGED,
307
                resource);
308
    }
309

    
310
    @Override
311
    public Object getSourceId() {
312
        return this.getParameters().getFile();
313
    }
314

    
315
    @Override
316
    public String getName() {
317
        return this.name;
318
    }
319

    
320
    @Override
321
    public String getFullName() {
322
        return this.getParameters().getFile().getAbsolutePath();
323
    }
324

    
325
    @Override
326
    public ResourceProvider getResource() {
327
        return resource;
328
    }
329

    
330
    private class FieldTypeParser {
331

    
332
        public String name = null;
333
        public int type = DataTypes.STRING;
334
        public int size = 0;
335
        public boolean allowNulls = true;
336
        public int geomType = Geometry.TYPES.GEOMETRY;
337
        public int geomSubtype = Geometry.SUBTYPES.GEOM2D;
338

    
339
        private String typename = "string";
340

    
341
        FieldTypeParser() {
342
        }
343

    
344
        private int getType(String value) {
345
            DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
346
            return dataTypesManager.getType(typename);
347
        }
348

    
349
        @SuppressWarnings("UseSpecificCatch")
350
        public boolean parse(String value) {
351
            String[] args;
352
            if ( value.contains(":") ) {
353
                args = value.split(":");
354
            } else if ( value.contains("/") ) {
355
                args = value.split("/");
356
            } else if ( value.contains("__") ) {
357
                args = value.split("__");
358
            } else {
359
                this.name = value;
360
                return true;
361
            }
362
            
363
            int n = 0;
364
            this.name = args[n++];
365
            if( n >= args.length ) {
366
                return true;
367
            }
368
            this.typename = args[n++];
369
            this.type = this.getType(this.typename);
370
            if ( this.type == DataTypes.INVALID ) {
371
                this.geomType = GeometryUtils.getGeometryType(this.typename);
372
                if( this.geomType==Geometry.TYPES.UNKNOWN )  {
373
                    this.type = DataTypes.STRING;
374
                    LOGGER.info("Type '" + this.typename + "' not valid for attribute '" + value + "' in '"+getProviderName()+"' file '" + getFullFileName() + "'.");
375
                } else {
376
                    this.typename = "GEOMETRY";
377
                    this.type = DataTypes.GEOMETRY;
378
                }
379
            }
380
            switch(this.type) {
381
                case DataTypes.STRING:
382
                    this.size = 50;
383
                    break;
384
                case DataTypes.INT:
385
                    this.size = 10;
386
                    break;
387
                case DataTypes.LONG:
388
                    this.size = 20;
389
                    break;
390
                case DataTypes.FLOAT:
391
                    this.size = 10;
392
                    break;
393
                case DataTypes.DOUBLE:
394
                    this.size = 20;
395
                    break;
396
                default:
397
                    this.size = 0;
398
            }
399
            while (n < args.length) {
400
                String option = args[n++].toLowerCase();
401
                switch (option) {
402
                    case "size":
403
                        try {
404
                            this.size = Integer.parseInt(args[n++]);
405
                        } catch (Exception ex) {
406
                            LOGGER.warn("Ignore incorrect field size for field " + value + " in '"+getProviderName()+"' file '" + getFullFileName() + "'.", ex);
407
                        }
408
                        break;
409
                    case "geomtype":
410
                        this.geomType = GeometryUtils.getGeometryType(args[n++]);
411
                        break;
412
                    case "geomsubtype":
413
                        this.geomSubtype = GeometryUtils.getGeometrySubtype(args[n++]);
414
                        break;
415
                    case "allownulls":
416
                        this.allowNulls = true;
417
                        break;
418
                    case "notallownulls":
419
                        this.allowNulls = false;
420
                        break;
421
                    default:
422
                        LOGGER.warn("Illegal argumente '"+option+"' in '"+getProviderName()+"' file '" + getFullFileName() + "'.");
423
                }
424
            }
425
            return true;
426
        }
427

    
428
    }
429

    
430
    private EditableFeatureType getFeatureType(List<String> headers, int automaticTypes[]) {
431
        EditableFeatureType fType = getStoreServices().createFeatureType(this.getName());
432
        fType.setHasOID(true);
433
//        DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
434

    
435
        FieldTypeParser[] fieldTypes = new FieldTypeParser[headers.size()];
436
        //
437
        // Calculamos cuales pueden ser los tipos de datos
438
        //
439
        for ( int i = 0; i < fieldTypes.length; i++ ) {
440
            fieldTypes[i] = new FieldTypeParser();
441
        }
442

    
443
        // Asuminos los tipos pasados por parametro, que se supone
444
        // son los detectados automaticamente.
445
        if ( automaticTypes != null ) {
446
            for ( int i = 0; i < fieldTypes.length && i < automaticTypes.length; i++ ) {
447
                fieldTypes[i].type = automaticTypes[i];
448
            }
449
        }
450
        // Luego probamos con lo que diga las cabezeras, sobreescribiendo
451
        // los tipos anteriores en caso de definirse en la cabezara.
452
        for ( int i = 0; i < fieldTypes.length; i++ ) {
453
            fieldTypes[i].parse(headers.get(i));
454
        }
455

    
456
        // Y por ultimo hacemos caso a lo que se haya especificado en los parametros
457
        // de apertura del reader, teniendo esto prioridad sobre todo.
458
        int[] param_types = this.getParameters().getFieldTypes();
459
        if ( param_types != null ) {
460
            for ( int i = 0; i < fieldTypes.length && i < param_types.length; i++ ) {
461
                fieldTypes[i].type = param_types[i];
462
            }
463
        }
464

    
465
        int[] param_sizes = this.getParameters().getFieldSizes();
466
        if ( param_sizes != null ) {
467
            for ( int i = 0; i < param_sizes.length; i++ ) {
468
                if ( param_sizes[i] > 0 ) {
469
                    fieldTypes[i].size = param_sizes[i];
470
                }
471
            }
472
        }
473
        //
474
        // Una vez ya sabemos los tipos de datos rellenamos el feature-type
475
        //
476
        for (FieldTypeParser fieldType : fieldTypes) {
477
            EditableFeatureAttributeDescriptor fad = fType.add(fieldType.name, fieldType.type);
478
            fad.setSize(fieldType.size);
479
            fad.setAllowNull(fieldType.allowNulls);
480
            if (fieldType.type == DataTypes.GEOMETRY ) {
481
                fad.setGeometryType(fieldType.geomType, fieldType.geomSubtype);
482
                if( fType.getDefaultGeometryAttributeName() == null ) {
483
                    fType.setDefaultGeometryAttributeName(fieldType.name);
484
                }
485
            }
486
        }
487
        String[] pointDimensionNames = this.getParameters().getPointDimensionNames();
488
        if ( pointDimensionNames != null ) {
489
            PointAttributeEmulator emulator = new PointAttributeEmulator(pointDimensionNames);
490
            EditableFeatureAttributeDescriptor attr = fType.add("the_geom", DataTypes.GEOMETRY, emulator);
491
            GeometryManager geommgr = GeometryLocator.getGeometryManager();
492
            GeometryType gt;
493
            try {
494
                if ( emulator.fieldNames != null && emulator.fieldNames.length <= 2 ) {
495
                        gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D);
496
                } else {
497
                        gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM3D);
498
                }
499
                attr.setGeometryType(gt);
500
            } catch (Exception e) {
501
                LOGGER.warn("Can't set geometry type for the calculated field in '"+getProviderName()+"' file '" + getFullFileName() + "'.", e);
502
            }
503
        }
504
        return fType;
505
    }
506

    
507
    class PointAttributeEmulator implements FeatureAttributeEmulator {
508

    
509
        private static final int XNAME = 0;
510
        private static final int YNAME = 1;
511
        private static final int ZNAME = 2;
512

    
513
        private final GeometryManager geommgr;
514
        private final String[] fieldNames;
515
        private final Coercion toDouble;
516
        private int errorcount = 0;
517

    
518
        public PointAttributeEmulator(String[] pointDimensionNames) {
519
            if ( pointDimensionNames.length > 2 ) {
520
                this.fieldNames = new String[3];
521
                this.fieldNames[ZNAME] = pointDimensionNames[2];
522
            } else {
523
                this.fieldNames = new String[2];
524
            }
525
            this.fieldNames[XNAME] = pointDimensionNames[0];
526
            this.fieldNames[YNAME] = pointDimensionNames[1];
527
            this.geommgr = GeometryLocator.getGeometryManager();
528
            DataTypesManager datatypeManager = ToolsLocator.getDataTypesManager();
529

    
530
            this.toDouble = datatypeManager.getCoercion(DataTypes.DOUBLE);
531
        }
532

    
533
        @Override
534
        @SuppressWarnings("UseSpecificCatch")
535
        public Object get(Feature feature) {
536
            try {
537
                Object valueX = feature.get(this.fieldNames[XNAME]);
538
                valueX = toDouble.coerce(valueX);
539
                if ( valueX == null ) {
540
                    return null;
541
                }
542
                Object valueY = feature.get(this.fieldNames[YNAME]);
543
                valueY = toDouble.coerce(valueY);
544
                if ( valueY == null ) {
545
                    return null;
546
                }
547
                Object valueZ = null;
548
                if ( this.fieldNames.length > 2 ) {
549
                    valueZ = toDouble.coerce(feature.get(this.fieldNames[ZNAME]));
550
                    if ( valueZ == null ) {
551
                        return null;
552
                    }
553
                }
554

    
555
                double x = ((Double) valueX);
556
                double y = ((Double) valueY);
557
                Point point;
558
                if ( this.fieldNames.length > 2 ) {
559
                    point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
560
                    double z = ((Double) valueZ);
561
                    point.setCoordinateAt(2, z);
562
                } else {
563
                    point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM2D);
564
                }
565
                return point;
566
            } catch (Exception ex) {
567
                if ( ++errorcount < 5 ) {
568
                    LOGGER.warn("[" + errorcount + "] Can't create point from '"+getProviderName()+"' file."+
569
                            "XNAME='" + this.fieldNames[XNAME] + 
570
                            "', YNAME='" + this.fieldNames[YNAME] + 
571
                            "', ZNAME='" + ((this.fieldNames.length > 2)? this.fieldNames[ZNAME]: "(2D)") +
572
                            "' feature=" + feature.toString(), ex);
573
                }
574
                return null;
575
            }
576
        }
577

    
578
        @Override
579
        public void set(EditableFeature feature, Object value) {
580
            if ( value == null ) {
581
                return;
582
            }
583
            Point point;
584
            if ( value instanceof MultiPoint ) {
585
                point = (Point) ((MultiPoint) value).getPrimitiveAt(0);
586
            } else {
587
                point = (Point) value;
588
            }
589
            feature.set(this.fieldNames[XNAME], point.getX());
590
            feature.set(this.fieldNames[YNAME], point.getY());
591
            if ( this.fieldNames.length > 2 ) {
592
                feature.set(this.fieldNames[ZNAME], point.getCoordinateAt(2));
593
            }
594
        }
595

    
596
        @Override
597
        public boolean allowSetting() {
598
            return true;
599
        }
600

    
601
        @Override
602
        public String[] getRequiredFieldNames() {
603
            return this.fieldNames;
604
        }
605

    
606
    }
607

    
608

    
609
    private void loadFeatures() throws IOException, DataException,
610
            CoercionException, CloneNotSupportedException {
611
        SimpleSequentialReader reader = null;
612

    
613
        try {
614
            List<String> headers;
615
            FeatureStoreProviderServices store = this.getStoreServices();
616

    
617
            boolean ignore_errors = getParameters().getIgnoreErrors();
618

    
619
            reader = this.readerFactory.createReader(this.getParameters());
620
            this.name = reader.getName();
621
            
622
            headers = getParameters().getFieldNames();
623
            if ( headers == null ) {
624
                headers = reader.getFieldNames();
625
            }
626

    
627
            // Initialize the feature types
628
            EditableFeatureType edftype = this.getFeatureType(headers, automaticDetectionOfTypes(reader));
629
            FeatureType ftype = edftype.getNotEditableCopy();
630
            List<FeatureType> ftypes = new ArrayList<>();
631
            ftypes.add(ftype);
632
            store.setFeatureTypes(ftypes, ftype);
633

    
634
            Coercion coercion[] = new Coercion[ftype.size()];
635
            int sizes[] = new int[ftype.size()];
636
            for ( int i = 0; i < ftype.size(); i++ ) {
637
                sizes[i] = -1;
638
                FeatureAttributeDescriptor ad = ftype.getAttributeDescriptor(i);
639
                coercion[i] = ad.getDataType().getCoercion();
640
                if ( ad.getDataType().getType() == DataTypes.STRING ) {
641
                    if ( ad.getSize() == 0 ) {
642
                        // Es un string y no tiene un size asignado.
643
                        // Lo ponemos a cero para calcularlo.
644
                        sizes[i] = 0;
645
                    }
646
                }
647
            }
648
            if ( ftype.getDefaultGeometryAttributeName() != null ) {
649
                this.need_calculate_envelope = true;
650
            }
651

    
652
            Locale locale = getParameters().getLocale();
653
            taskStatus.message("_loading");
654
            int count = 0;
655

    
656
            int count_errors = 0;
657
            
658
            reader.rewind();
659
            List<Object> row = reader.read();
660

    
661
            Object rawvalue;
662
            while ( row != null ) {
663
                taskStatus.setCurValue(++count);
664
                FeatureProvider feature = this.createFeatureProvider(ftype);
665
                for ( int i = 0; i < row.size(); i++ ) {
666
                    rawvalue = row.get(i);
667
                    if( rawvalue instanceof String && StringUtils.isBlank((String)rawvalue) ) {
668
                        rawvalue = null;
669
                    }
670
                    try {
671
                        Object value;
672
                        if ( locale != null && coercion[i] instanceof CoercionWithLocale ) {
673
                            value = ((CoercionWithLocale) (coercion[i])).coerce(rawvalue, locale);
674
                        } else {
675
                            value = coercion[i].coerce(rawvalue);
676
                        }
677
                        feature.set(i, value);
678
                        if ( sizes[i] >= 0 && value != null ) {
679
                            int x = ((String) value).length();
680
                            if ( sizes[i] < x ) {
681
                                sizes[i] = x;
682
                            }
683
                        }
684
                    } catch (RuntimeException ex) {
685
                        if ( !ignore_errors ) {
686
                            throw ex;
687
                        }
688
                        if ( count_errors++ < 10 ) {
689
                            LOGGER.warn("Can't load value of attribute " + i + " in row " + count + ".", ex);
690
                        }
691
                        if ( count_errors == 10 ) {
692
                            LOGGER.info("Too many errors, suppress messages.");
693
                        }
694
                    }
695
                }
696
                this.addFeatureProvider(feature);
697
                row = reader.read();
698
            }
699
            for ( int i = 0; i < ftype.size(); i++ ) {
700
                if ( sizes[i] > 0 ) {
701
                    EditableFeatureAttributeDescriptor efad = ((EditableFeatureAttributeDescriptor) edftype.getAttributeDescriptor(i));
702
                    efad.setSize(sizes[i]);
703
                }
704
            }
705
            // Volvemos a asignar al store el featuretype, ya que puede
706
            // haber cambiado.
707
            ftype = edftype.getNotEditableCopy();
708
            ftypes = new ArrayList<>();
709
            ftypes.add(ftype);
710
            store.setFeatureTypes(ftypes, ftype);
711

    
712
            taskStatus.terminate();
713
        } catch (Exception ex) {
714
            LOGGER.warn("Can't load features from '"+getProviderName()+"' file '" + getFullFileName() + "'.", ex);
715
        } finally {
716
            if ( reader != null ) {
717
                try {
718
                    reader.close();
719
                } catch (Exception ex) {
720
                    // Do nothing
721
                }
722
            }
723

    
724
        }
725
    }
726
    
727
    private int[] automaticDetectionOfTypes(SimpleSequentialReader reader) throws IOException {
728
        boolean automatic_types_detection = getParameters().getAutomaticTypesDetection();
729
        if ( !automatic_types_detection ) {
730
            return null;
731
        }
732
        int[] types = null;
733
        try {
734
            reader.rewind();
735
            List<String> fieldNames = reader.getFieldNames();
736
            if ( fieldNames == null ) {
737
                fieldNames = getParameters().getFieldNames();
738
            }
739

    
740
            AutomaticDetectionOfTypes x = new AutomaticDetectionOfTypes(
741
                    this.getFullFileName()
742
            );
743
            types = x.detect(
744
                    fieldNames.size(), 
745
                    reader, 
746
                    false, 
747
                    getParameters().getLocale()
748
            );
749
        } catch (Exception ex) {
750
            throw new RuntimeException("Problems reading '"+getProviderName()+"' file '" + getFullFileName() + "'.", ex);
751
        }
752
        return types;
753
    }
754

    
755
    @Override
756
    public boolean hasDynValue(String name) {
757
        if ( DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name) ) {
758
            return true;
759
        } else if ( DataStore.METADATA_CRS.equalsIgnoreCase(name) ) {
760
            return true;
761
        }
762
        return super.hasDynValue(name);
763
    }
764

    
765
    
766
}