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

History | View | Annotate | Download (33 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.Closeable;
26
import java.io.File;
27
import java.io.IOException;
28
import java.io.InputStreamReader;
29
import java.net.URI;
30
import java.net.URL;
31
import java.util.ArrayList;
32
import java.util.HashMap;
33
import java.util.Iterator;
34
import java.util.List;
35
import org.apache.commons.io.FileUtils;
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.feature.EditableFeatureAttributeDescriptor;
53
import org.gvsig.fmap.dal.feature.EditableFeatureType;
54
import org.gvsig.fmap.dal.feature.Feature;
55
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
56
import org.gvsig.fmap.dal.feature.FeatureQuery;
57
import org.gvsig.fmap.dal.feature.FeatureSet;
58
import org.gvsig.fmap.dal.feature.FeatureStore;
59
import org.gvsig.fmap.dal.feature.FeatureType;
60
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
61
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
62
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
63
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
64
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
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.AbstractSimpleReader;
74
import org.gvsig.fmap.dal.store.csv.simplereaders.CSVReaderSuperCSV;
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.primitive.Envelope;
80
import org.gvsig.fmap.geom.primitive.Point;
81
import org.gvsig.tools.ToolsLocator;
82
import org.gvsig.tools.dataTypes.Coercion;
83
import org.gvsig.tools.dispose.DisposableIterator;
84
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
85
import org.gvsig.tools.evaluator.AbstractEvaluator;
86
import org.gvsig.tools.evaluator.EvaluatorData;
87
import org.gvsig.tools.evaluator.EvaluatorException;
88
import org.gvsig.tools.exception.BaseException;
89
import org.gvsig.tools.exception.NotYetImplemented;
90
import org.gvsig.tools.persistence.PersistentState;
91
import org.gvsig.tools.persistence.exception.PersistenceException;
92
import org.gvsig.tools.task.SimpleTaskStatus;
93
import org.gvsig.tools.task.TaskStatusManager;
94
import org.gvsig.tools.visitor.VisitCanceledException;
95
import org.gvsig.tools.visitor.Visitor;
96
import org.slf4j.Logger;
97
import org.slf4j.LoggerFactory;
98
import org.supercsv.prefs.CsvPreference;
99
import org.gvsig.tools.dataTypes.CoercionContext;
100
import org.gvsig.tools.i18n.I18nManager;
101
import org.gvsig.tools.util.GetItemWithSize64;
102

    
103
@SuppressWarnings("UseSpecificCatch")
104
public class CSVStoreProvider extends AbstractMemoryStoreProvider implements
105
        ResourceConsumer {
106

    
107
    private static final Logger LOGGER = LoggerFactory.getLogger(CSVStoreProvider.class);
108

    
109
    public static final String NAME = DataStore.CSV_PROVIDER_NAME;
110
    public static final String DESCRIPTION = "CSV file";
111

    
112
    public static final String METADATA_DEFINITION_NAME = NAME;
113

    
114
    private final ResourceProvider resource;
115

    
116
    private long counterNewsOIDs = 0;
117
    private Envelope envelope;
118
    private boolean need_calculate_envelope = false;
119
    private final SimpleTaskStatus taskStatus;
120
    private final CSVFeatureWriter writer;
121
    private FeatureType featureType;
122
    private GetItemWithSize64<List<String>> virtualrows;
123
    private RowToFeatureTranslator rowToFeatureTranslator;
124

    
125
    @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
126
    public CSVStoreProvider(CSVStoreParameters parameters,
127
            DataStoreProviderServices storeServices) throws InitializeException {
128
        super(
129
                parameters,
130
                storeServices,
131
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
132
        );
133
        this.writer = new CSVFeatureWriter();
134
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
135
        this.taskStatus = manager.createDefaultSimpleTaskStatus("CSV");
136
        this.taskStatus.setAutoremove(true);
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

    
148
        initializeFeatureTypes();
149
    }
150

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

    
155
    @Override
156
    public String getProviderName() {
157
        return NAME;
158
    }
159

    
160
    @Override
161
    public boolean allowWrite() {
162
        return true;
163
    }
164

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

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

    
195
    @Override
196
    public DataServerExplorer getExplorer() throws ReadException {
197
        DataManager manager = DALLocator.getDataManager();
198
        FilesystemServerExplorerParameters params;
199
        try {
200
            params = (FilesystemServerExplorerParameters) manager
201
                    .createServerExplorerParameters(FilesystemServerExplorer.NAME);
202
            params.setRoot(this.getCSVParameters().getFile().getParent());
203
            return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
204
        } catch (Exception e) {
205
            throw new ReadException(this.getProviderName(), e);
206
        }
207

    
208
    }
209

    
210
    @Override
211
    @SuppressWarnings("Convert2Lambda")
212
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
213

    
214
        try {
215
            I18nManager i18n = ToolsLocator.getI18nManager();
216
            this.taskStatus.add();
217
            taskStatus.message(i18n.getTranslation("_Preparing_writing"));
218
            this.getResource().closeRequest();
219
            getResource().execute(new ResourceAction() {
220
                @Override
221
                public Object run() throws Exception {
222
                    FeatureSet features = null;
223
                    DisposableIterator it = null;
224
                    try {
225
                        File file = (File) resource.get();
226
                        features = getStoreServices().getFeatureStore().getFeatureSet();
227

    
228
                        taskStatus.message(i18n.getTranslation("_Writing_records"));
229
                        if (virtualrows == null) {
230
                            List<FeatureProvider> newdata = new ArrayList<>();
231
                            FeatureType ftype = getStoreServices().getDefaultFeatureType();
232
                            writer.initialize(getCSVParameters(), file, ftype, getCSVPreferences());
233
                            writer.begin();
234
                            it = features.fastIterator();
235
                            taskStatus.setRangeOfValues(0, features.getSize());
236
                            taskStatus.setCurValue(0);
237
                            while (it.hasNext()) {
238
                                taskStatus.incrementCurrentValue();
239
                                FeatureProvider feature = getStoreServices().getFeatureProviderFromFeature(
240
                                        (org.gvsig.fmap.dal.feature.Feature) it.next());
241
                                writer.add(feature);
242
                                if (feature.getOID() == null) {
243
                                    LOGGER.warn("feature without OID");
244
                                    feature.setOID(createNewOID());
245
                                }
246
                                newdata.add(feature);
247
                            }
248
                            data = newdata;
249
                            if (writer.getEnvelope() != null) {
250
                                envelope = writer.getEnvelope().getGeometry().getEnvelope();
251
                            }
252
                            resource.notifyChanges();
253
                            writer.end();
254
                            
255
                        } else {
256

    
257
                            CSVStoreParameters csvParams = getCSVParameters();
258
                            CSVStoreParameters tmpParams = (CSVStoreParameters) csvParams.getCopy();
259

    
260
                            String tmpBase = File.createTempFile("tmp_" + System.currentTimeMillis(), null).getAbsolutePath();
261
                            File tmpFile = new File(tmpBase + ".csv");
262
                            tmpParams.setFile(tmpFile);
263

    
264
                            FeatureType ftype = getStoreServices().getDefaultFeatureType();
265
                            writer.initialize(tmpParams, tmpFile, ftype, getCSVPreferences());
266
                            writer.begin();
267
                            it = features.fastIterator();
268
                            taskStatus.setIndeterminate();
269
                            taskStatus.setCurValue(0);
270
                            while (it.hasNext()) {
271
                                taskStatus.incrementCurrentValue();
272
                                if( taskStatus.isCancellationRequested() ) {
273
                                    taskStatus.cancel();
274
                                    LOGGER.info("CSV writing canceled ("+getFullFileName()+")");
275
                                    break;
276
                                }
277
                                FeatureProvider feature = getStoreServices().getFeatureProviderFromFeature(
278
                                        (org.gvsig.fmap.dal.feature.Feature) it.next());
279
                                writer.add(feature);
280
                                if (feature.getOID() == null) {
281
                                    LOGGER.warn("feature without OID");
282
                                    feature.setOID(createNewOID());
283
                                }
284
                            }
285
                            if (writer.getEnvelope() != null) {
286
                                envelope = writer.getEnvelope().getGeometry().getEnvelope();
287
                            }
288
                            resource.notifyChanges();
289
                            writer.end();
290
                            if( !taskStatus.isCancelled() ) {
291
                                if (!csvParams.getFile().delete()) {
292
                                    LOGGER.debug("Can't delete csv file '" + csvParams.getFile() + "'.");
293
                                    throw new IOException("Can't delete csv '"
294
                                            + FilenameUtils.getBaseName(csvParams.getFile().getAbsolutePath())
295
                                            + "' file to replace with the new csv.\nThe new csv is in temporary file '" + tmpFile.getAbsolutePath()
296
                                            + "'");
297
                                }
298

    
299
                                File csvFile = csvParams.getFile();
300
                                FileUtils.moveFile(tmpParams.getFile(), csvFile);
301
                                FileUtils.delete(new File(FilenameUtils.removeExtension(csvFile.getAbsolutePath())+".idx"));
302

    
303
                                loadFeatures();
304
                            }
305
                        }
306
                    } finally {
307
                        if (it != null) {
308
                            it.dispose();
309
                        }
310
                        if (features != null) {
311
                            features.dispose();
312
                        }
313
                    }
314
                    return null;
315
                }
316

    
317
            });
318
            this.taskStatus.terminate();
319
        } catch (Exception e) {
320
            this.taskStatus.abort();
321
            throw new PerformEditingException(getResource().toString(), e);
322
        }
323
    }
324

    
325
    private CsvPreference getCSVPreferences() {
326
        CSVReaderSuperCSV reader = new CSVReaderSuperCSV(getCSVParameters());
327
        return reader.getCSVPreferences();
328
    }
329

    
330
    @Override
331
    public boolean closeResourceRequested(ResourceProvider resource) {
332
        return true;
333
    }
334

    
335
    @Override
336
    public int getOIDType() {
337
        return DataTypes.LONG;
338
    }
339

    
340
    @Override
341
    public boolean supportsAppendMode() {
342
        return true;
343
    }
344

    
345
    @Override
346
    @SuppressWarnings("Convert2Lambda")
347
    public void append(final FeatureProvider featureProvider) {
348
        //todo
349
        getResource().execute(new ResourceAction() {
350
            @Override
351
            public Object run() throws Exception {
352
                //writer.append(getStoreServices().createFeature(featureProvider));
353
                writer.add(featureProvider);
354
                return null;
355
            }
356
        });
357
    }
358

    
359
    @Override
360
    @SuppressWarnings("Convert2Lambda")
361
    public void beginAppend() throws DataException {
362
        this.close();
363
        getResource().execute(new ResourceAction() {
364
            @Override
365
            public Object run() throws Exception {
366
                writer.initialize(
367
                        getCSVParameters(),
368
                        getCSVParameters().getFile(),
369
                        getFeatureStore().getDefaultFeatureType(),
370
                        getCSVPreferences()
371
                );
372
                writer.beginAppend();
373
                return null;
374
            }
375
        });
376

    
377
    }
378

    
379
    @Override
380
    @SuppressWarnings("Convert2Lambda")
381
    public void endAppend() {
382
        try {
383
            getResource().execute(new ResourceAction() {
384
                @Override
385
                public Object run() throws Exception {
386
                    writer.end();
387
                    resource.notifyChanges(); //resourcesNotifyChanges();
388
                    counterNewsOIDs = -1;
389
                    return null;
390
                }
391
            });
392
            writer.end();
393
        } catch (PerformEditingException ex) {
394
            LOGGER.warn("Not been able to end append '" + this.getFullName() + "'.", ex);
395
        }
396
    }
397

    
398
    public void saveToState(PersistentState state) throws PersistenceException {
399
        throw new NotYetImplemented();
400
    }
401

    
402
    public void loadFromState(PersistentState state) throws PersistenceException {
403
        throw new NotYetImplemented();
404
    }
405

    
406
    @Override
407
    public Object createNewOID() {
408
        return counterNewsOIDs++;
409
    }
410

    
411
    protected void initializeFeatureTypes() throws InitializeException {
412
        try {
413
            this.open();
414
        } catch (OpenException e) {
415
            throw new InitializeException(this.getProviderName(), e);
416
        }
417
    }
418

    
419
    @Override
420
    @SuppressWarnings("Convert2Lambda")
421
    public Envelope getEnvelope() throws DataException {
422
        this.open();
423
        if (this.envelope != null) {
424
            return this.envelope;
425
        }
426
        if (!this.need_calculate_envelope) {
427
            return null;
428
        }
429
        try {
430
            I18nManager i18n = ToolsLocator.getI18nManager();
431
            this.taskStatus.add();
432
            this.taskStatus.message(i18n.getTranslation("_Calculating_envelope"));
433
            FeatureStore fs = this.getFeatureStore();
434
            FeatureType ft = fs.getDefaultFeatureType();
435
            FeatureAttributeDescriptor fad = ft.getAttributeDescriptor(ft.getDefaultGeometryAttributeIndex());
436
            this.taskStatus.setRangeOfValues(0, fs.getFeatureCount());
437
            this.envelope = GeometryLocator.getGeometryManager().createEnvelope(fad.getGeomType().getSubType());
438
            fs.accept(new Visitor() {
439
                @Override
440
                public void visit(Object obj) throws VisitCanceledException, BaseException {
441
                    taskStatus.incrementCurrentValue();
442
                    if(taskStatus.isCancellationRequested()){
443
                        taskStatus.cancel();
444
                        throw new VisitCanceledException();
445
                    }
446
                    Feature f = (Feature) obj;
447
                    Geometry geom = f.getDefaultGeometry();
448
                    if (geom != null) {
449
                        envelope.add(geom.getEnvelope());
450
                    }
451
                }
452
            });
453
            taskStatus.terminate();
454
        } catch (VisitCanceledException e) {
455
            return null;
456
        } catch (BaseException e) {
457
            taskStatus.abort();
458
            LOGGER.warn("Can't calculate the envelope of CSV file '" + this.getFullName() + "'.", e);
459
            return null;
460
        }
461

    
462
        this.need_calculate_envelope = false;
463
        return this.envelope;
464
    }
465

    
466
    @Override
467
    public Object getDynValue(String name) throws DynFieldNotFoundException {
468
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
469
            try {
470
                return this.getEnvelope();
471
            } catch (DataException e) {
472
                return null;
473
            }
474
        } else {
475
            if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
476
                IProjection pro = CSVStoreParameters.getCRS(this.getCSVParameters());
477
                if (pro != null) {
478
                    return pro;
479
                }
480
            }
481
        }
482
        return super.getDynValue(name);
483
    }
484

    
485
    @Override
486
    public void resourceChanged(ResourceProvider resource) {
487
        this.getStoreServices().notifyChange(
488
                DataStoreNotification.RESOURCE_CHANGED,
489
                resource);
490
    }
491

    
492
    @Override
493
    public Object getSourceId() {
494
        return this.getCSVParameters().getFile();
495
    }
496

    
497
    @Override
498
    public String getName() {
499
        String name = this.getCSVParameters().getFile().getName();
500
        return FilenameUtils.getBaseName(name);
501
    }
502

    
503
    @Override
504
    public String getFullName() {
505
        return this.getCSVParameters().getFile().getAbsolutePath();
506
    }
507

    
508
    @Override
509
    public ResourceProvider getResource() {
510
        return resource;
511
    }
512

    
513
    private boolean isEmpty(String s) {
514
        if (s == null) {
515
            return true;
516
        }
517
        return s.trim().length() == 0;
518
    }
519

    
520
    private void init(CSVStoreParameters parameters, DataStoreProviderServices storeServices) {
521
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
522
    }
523

    
524
    static class ToPointEvaluaror extends AbstractEvaluator {
525

    
526
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
527

    
528
        private GeometryManager geommgr = null;
529
        private String xname = null;
530
        private String yname = null;
531
        private String zname = null;
532
        private final Coercion toDouble;
533
        private int errorcount = 0;
534

    
535
        ToPointEvaluaror(String[] pointDimensionNames) {
536
            this.xname = pointDimensionNames[0];
537
            this.yname = pointDimensionNames[1];
538
            if (pointDimensionNames.length > 2) {
539
                this.zname = pointDimensionNames[2];
540
            }
541
            this.geommgr = GeometryLocator.getGeometryManager();
542
            this.toDouble = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.DOUBLE);
543
        }
544

    
545
        @Override
546
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
547
            try {
548
                double x = ((Double) toDouble.coerce(data.getDataValue(xname)));
549
                double y = ((Double) toDouble.coerce(data.getDataValue(yname)));
550
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
551
                if (zname != null) {
552
                    double z = ((Double) toDouble.coerce(data.getDataValue(zname)));
553
                    point.setCoordinateAt(2, z);
554
                }
555
                return point;
556
            } catch (Exception ex) {
557
                if (++errorcount < 5) {
558
                    logger.warn("[" + errorcount + "] Can't create point in CSV provider. XNAME='"
559
                            + xname + "', YNAME='" + yname + "', ZNAME='" + zname + "', data=" + data.toString());
560
                }
561
                return null;
562
            }
563
        }
564

    
565
        @Override
566
        public String getName() {
567
            return "ToPointEvaluaror";
568
        }
569

    
570
    }
571

    
572
    public static class RowToFeatureTranslator {
573

    
574
        private Coercion coercion[];
575
        private CoercionContext coercionContext[];
576
        private int sizes[];
577
        private String[] names;
578
        private final boolean ignore_errors;
579
        private long count_errors;
580
        private FeatureType csvFeatureType;
581

    
582
        public RowToFeatureTranslator(boolean ignore_errors) {
583
            this.ignore_errors = ignore_errors;
584
            this.count_errors = 0;
585
        }
586

    
587
        public int getColumnSize(int column) {
588
            return this.sizes[column];
589
        }
590

    
591
        public void initialize(FeatureType ftype) {
592
            this.csvFeatureType = ftype;
593
            int columns = this.csvFeatureType.size();
594
            this.names = new String[columns];
595
            this.coercion = new Coercion[columns];
596
            this.coercionContext = new CoercionContext[columns];
597
            this.sizes = new int[columns];
598
            int index = 0;
599
            for (int i = 0; i < this.csvFeatureType.size(); i++) {
600
                FeatureAttributeDescriptor ad = this.csvFeatureType.getAttributeDescriptor(i);
601
                names[i] = null;
602
                if( ad.isComputed() ) {
603
                    continue;
604
                }
605
                names[index] = ad.getName();
606
                coercion[index] = ad.getCoercion();
607
                coercionContext[index] = ad.getCoercionContext();
608
                sizes[index] = ad.getSize();
609
                index++;
610
            }
611
        }
612

    
613
        public void translate(long rowindex, List<String> row, FeatureProvider feature) throws Exception {
614

    
615
            feature.setOID(rowindex);
616
            for (int i = 0; i < names.length; i++) {
617
                String name = names[i];
618
                if( name == null ) {
619
                    break;
620
                }
621
                Object rawvalue = row.get(i);
622
                try {
623
                    Object value = null;
624
                    if (coercion[i] != null) {
625
                        value = coercion[i].coerce(rawvalue, coercionContext[i]);
626
                    }
627
                    int findex = feature.getType().getIndex(name);
628
                    if( findex>=0 ) {
629
                        // Ojo que puede que se este filtrando el featuretype y no 
630
                        // tenga todos los atributos, por ejemplo al pintar la vista.
631
                        feature.set(findex, value);
632
                    }
633
                    if (sizes[i] >= 0
634
                            && (value instanceof String || value instanceof URL
635
                            || value instanceof URI || value instanceof File)) {
636
                        int x = value.toString().length();
637
                        if (sizes[i] < x) {
638
                            sizes[i] = x;
639
                        }
640
                    }
641
                } catch (Exception ex) {
642
                    if (!ignore_errors) {
643
                        throw ex;
644
                    }
645
                    if (count_errors++ < 10) {
646
                        LOGGER.warn("Can't load value of attribute " + name +"/" +i+" in row " + rowindex + ".", ex);
647
                    }
648
                    if (count_errors == 10) {
649
                        LOGGER.info("Too many errors, suppress messages.");
650
                    }
651
                }
652
            }
653
        }
654
    }
655

    
656
    private void loadFeatures() {
657
        InputStreamReader in = null;
658
        SimpleReader reader = null;
659
        try {
660
            taskStatus.setTitle("CSV "+this.getName());
661
            taskStatus.add();
662
//            boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
663

    
664
            // Initialize the feature types
665
            EditableFeatureType edftype = getStoreServices().createFeatureType(this.getName());
666
            CSVUtils.loadFeatureType(getCSVParameters(), edftype, true, taskStatus);
667
            FeatureType ftype = edftype.getNotEditableCopy();
668
            this.setFeatureType(ftype);
669

    
670
            in = CSVUtils.openFile(
671
                    this.getCSVParameters().getFile(),
672
                    CSVStoreParameters.getCharset(this.getCSVParameters())
673
            );
674
            reader = CSVUtils.getSimpleReader(getCSVParameters(), in);
675
            if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
676
                reader.getHeader(); // Skip and ignore the header of file
677
            }
678
            this.rowToFeatureTranslator = new RowToFeatureTranslator(
679
                    CSVStoreParameters.getIgnoreErrors(getCSVParameters())
680
            );
681
            this.rowToFeatureTranslator.initialize(ftype);
682
            if (ftype.getDefaultGeometryAttributeName() != null) {
683
                this.need_calculate_envelope = true;
684
            }
685
            I18nManager i18n = ToolsLocator.getI18nManager();
686
            taskStatus.message(i18n.getTranslation("_Loading"));
687

    
688
            if(this.virtualrows != null && this.virtualrows instanceof Closeable){
689
                IOUtils.closeQuietly((Closeable) this.virtualrows);
690
                this.virtualrows = null;
691
            }
692
            
693
            this.virtualrows = ((AbstractSimpleReader) reader).getVirtualRows(this.taskStatus);
694
            if (this.virtualrows == null) {
695

    
696
                List<String> row = reader.read();
697

    
698
                int skipLines = CSVStoreParameters.getSkipLines(getCSVParameters());
699
                if (skipLines > 0) {
700
                    row = reader.skip(skipLines);
701
                }
702
                int limit = CSVStoreParameters.getLimit(getCSVParameters());
703
                while (row != null) {
704
                    taskStatus.incrementCurrentValue();
705
                    if( taskStatus.isCancellationRequested() ) {
706
                        taskStatus.cancel();
707
                        break;
708
                    }
709
                    FeatureProvider feature = this.createFeatureProvider(ftype);
710
                    this.rowToFeatureTranslator.translate(reader.getLine(), row, feature);
711

    
712
                    this.addFeatureProvider(feature);
713
                    if (limit > 0) {
714
                        if (limit < this.data.size()) {
715
                            break;
716
                        }
717
                    }
718
                    row = reader.read();
719
                }
720
                for (int i = 0; i < ftype.size(); i++) {
721
                    if (this.rowToFeatureTranslator.getColumnSize(i) > 0) {
722
//                    if (sizes[i] > 0) {
723
                        EditableFeatureAttributeDescriptor efad = ((EditableFeatureAttributeDescriptor) edftype.getAttributeDescriptor(i));
724
//                        efad.setSize(sizes[i]);
725
                        efad.setSize(this.rowToFeatureTranslator.getColumnSize(i));
726
                    }
727
                }
728
                // Volvemos a asignar al store el featuretype, ya que puede
729
                // haber cambiado.
730
                ftype = edftype.getNotEditableCopy();
731
                this.setFeatureType(ftype);
732
            }
733
            if( taskStatus.isRunning() ) {
734
                taskStatus.terminate();
735
            }
736
        } catch (Throwable ex) {
737
            taskStatus.abort();
738
            int lineno = 0;
739
            if (reader != null) {
740
                lineno = reader.getLine();
741
            }
742
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
743

    
744
        } finally {
745
            if (reader != null) {
746
                try {
747
                    reader.close();
748
                } catch (Exception ex) {
749
                    // Do nothing
750
                }
751
//                reader = null;
752
            }
753
            if (in != null) {
754
                try {
755
                    in.close();
756
                } catch (Exception ex) {
757
                    // Do nothing
758
                }
759
//                in = null;
760
            }
761
        }
762
    }
763

    
764
    @Override
765
    public void fixFeatureTypeFromParameters() {
766
        String param_types_def = CSVStoreParameters.getRawFieldTypes(this.getParameters());
767
        String[] pointDimensionNames = CSVStoreParameters.getPointDimensionNames(this.getParameters());
768
        String geometry_column = CSVStoreParameters.getGeometryColumn(this.getParameters());
769
        if (StringUtils.isNotBlank(param_types_def)
770
                || pointDimensionNames != null
771
                || !StringUtils.isBlank(geometry_column)) {
772
            this.setFeatureType(featureType);
773
        }
774
    }
775

    
776
    private void setFeatureType(FeatureType ftype) {
777
        List<FeatureType> ftypes = new ArrayList<>();
778
        ftypes.add(ftype);
779
        this.featureType = ftype;
780
        this.getStoreServices().setFeatureTypes(ftypes, ftype);
781
    }
782

    
783
    @Override
784
    public FeatureSetProvider createSet(FeatureQuery query, FeatureType featureType)
785
            throws DataException {
786
        if (this.virtualrows == null) {
787
            return super.createSet(query, featureType);
788
        }
789
        return new CSVSetProvider(this, query, featureType);
790
    }
791

    
792
    public List<String> getRowByIndex(long index) {
793
        if (this.virtualrows == null) {
794
            return null;
795
        }
796
        return this.virtualrows.get64(index);
797
    }
798

    
799
    public RowToFeatureTranslator getRowToFeatureTranslator() {
800
        if (this.rowToFeatureTranslator == null) {
801
            boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
802
            this.rowToFeatureTranslator = new RowToFeatureTranslator(ignore_errors);
803
            this.rowToFeatureTranslator.initialize(featureType);
804
        }
805
        return this.rowToFeatureTranslator;
806
    }
807

    
808
    @Override
809
    public long getFeatureCount() throws DataException {
810
        if (this.virtualrows == null) {
811
            return super.getFeatureCount();
812
        }
813
        return this.virtualrows.size64();
814
    }
815

    
816
    @Override
817
    public long getDataSize() throws DataException {
818
        if (this.virtualrows == null) {
819
            return super.getDataSize();
820
        }
821
        return this.virtualrows.size64();
822
    }
823

    
824
    @Override
825
    protected FeatureProvider internalGetFeatureProviderByReference(
826
            FeatureReferenceProviderServices reference) throws DataException {
827
        if (this.virtualrows == null) {
828
            return super.internalGetFeatureProviderByReference(reference);
829
        }
830
        int oid = ((Long) reference.getOID()).intValue();
831
        RowToFeatureTranslator translator = getRowToFeatureTranslator();
832
        FeatureProvider feature = this.createFeatureProvider(this.featureType);
833
        try {
834
            translator.translate(oid, this.virtualrows.get64(oid), feature);
835
        } catch (Exception ex) {
836
            throw new CreateFeatureException(ex, this.getName());
837
        }
838
        return feature;
839
    }
840

    
841
    @Override
842
    protected void doDispose() throws BaseException {
843
        super.doDispose();
844
        if (this.virtualrows != null && this.virtualrows instanceof Closeable) {
845
            IOUtils.closeQuietly((Closeable) this.virtualrows);
846
            this.virtualrows = null;
847
        }
848
    }
849
    
850
    
851

    
852
}