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

History | View | Annotate | Download (35.2 KB)

1 40846 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6 42775 jjdelcerro
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10 40846 jjdelcerro
 *
11 42775 jjdelcerro
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15 40846 jjdelcerro
 *
16 42775 jjdelcerro
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 40846 jjdelcerro
 *
20 42775 jjdelcerro
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22 40846 jjdelcerro
 */
23
package org.gvsig.fmap.dal.store.csv;
24
25 45836 fdiaz
import java.io.Closeable;
26 40846 jjdelcerro
import java.io.File;
27 45836 fdiaz
import java.io.IOException;
28 43283 jjdelcerro
import java.io.InputStreamReader;
29 43425 jjdelcerro
import java.net.URI;
30 41062 jjdelcerro
import java.net.URL;
31 40846 jjdelcerro
import java.util.ArrayList;
32
import java.util.HashMap;
33 41006 jjdelcerro
import java.util.Iterator;
34 40846 jjdelcerro
import java.util.List;
35 41069 jjdelcerro
import java.util.Locale;
36 45836 fdiaz
import java.util.logging.Level;
37
import org.apache.commons.io.FileUtils;
38 40846 jjdelcerro
39 41006 jjdelcerro
import org.apache.commons.io.FilenameUtils;
40 45836 fdiaz
import org.apache.commons.io.IOUtils;
41 41876 jjdelcerro
import org.apache.commons.lang3.StringUtils;
42 40846 jjdelcerro
import org.cresques.cts.IProjection;
43
import org.gvsig.fmap.dal.DALLocator;
44
import org.gvsig.fmap.dal.DataManager;
45
import org.gvsig.fmap.dal.DataServerExplorer;
46
import org.gvsig.fmap.dal.DataStore;
47
import org.gvsig.fmap.dal.DataStoreNotification;
48
import org.gvsig.fmap.dal.DataTypes;
49
import org.gvsig.fmap.dal.FileHelper;
50
import org.gvsig.fmap.dal.exception.DataException;
51
import org.gvsig.fmap.dal.exception.InitializeException;
52
import org.gvsig.fmap.dal.exception.OpenException;
53
import org.gvsig.fmap.dal.exception.ReadException;
54 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
55 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureType;
56 41059 jjdelcerro
import org.gvsig.fmap.dal.feature.Feature;
57 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
58 45727 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureQuery;
59 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureSet;
60 41059 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStore;
61 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
62 45836 fdiaz
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
63 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
64 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
65 45836 fdiaz
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
66 45727 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
67 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.memory.AbstractMemoryStoreProvider;
68 41006 jjdelcerro
import org.gvsig.fmap.dal.resource.ResourceAction;
69 40846 jjdelcerro
import org.gvsig.fmap.dal.resource.file.FileResource;
70
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
71
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
72
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
73
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
74
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
75 45727 jjdelcerro
import org.gvsig.fmap.dal.store.csv.simplereaders.AbstractSimpleReader;
76 45685 jjdelcerro
import org.gvsig.fmap.dal.store.csv.simplereaders.CSVReaderSuperCSV;
77 41617 jjdelcerro
import org.gvsig.fmap.dal.store.csv.simplereaders.SimpleReader;
78 40846 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
79
import org.gvsig.fmap.geom.GeometryLocator;
80
import org.gvsig.fmap.geom.GeometryManager;
81
import org.gvsig.fmap.geom.primitive.Envelope;
82 41006 jjdelcerro
import org.gvsig.fmap.geom.primitive.Point;
83 40846 jjdelcerro
import org.gvsig.tools.ToolsLocator;
84 44669 jjdelcerro
import org.gvsig.tools.dataTypes.Coercion;
85 41006 jjdelcerro
import org.gvsig.tools.dispose.DisposableIterator;
86 40846 jjdelcerro
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
87 41006 jjdelcerro
import org.gvsig.tools.evaluator.AbstractEvaluator;
88
import org.gvsig.tools.evaluator.EvaluatorData;
89
import org.gvsig.tools.evaluator.EvaluatorException;
90 41059 jjdelcerro
import org.gvsig.tools.exception.BaseException;
91 40846 jjdelcerro
import org.gvsig.tools.exception.NotYetImplemented;
92
import org.gvsig.tools.persistence.PersistentState;
93
import org.gvsig.tools.persistence.exception.PersistenceException;
94
import org.gvsig.tools.task.SimpleTaskStatus;
95
import org.gvsig.tools.task.TaskStatusManager;
96 41059 jjdelcerro
import org.gvsig.tools.visitor.VisitCanceledException;
97
import org.gvsig.tools.visitor.Visitor;
98 40846 jjdelcerro
import org.slf4j.Logger;
99
import org.slf4j.LoggerFactory;
100 40878 jjdelcerro
import org.supercsv.prefs.CsvPreference;
101 44669 jjdelcerro
import org.gvsig.tools.dataTypes.CoercionContext;
102 45727 jjdelcerro
import org.gvsig.tools.util.GetItemWithSize64;
103 40846 jjdelcerro
104 44309 omartinez
@SuppressWarnings("UseSpecificCatch")
105 40846 jjdelcerro
public class CSVStoreProvider extends AbstractMemoryStoreProvider implements
106 41617 jjdelcerro
        ResourceConsumer {
107
108 44408 jjdelcerro
    private static final Logger LOGGER = LoggerFactory.getLogger(CSVStoreProvider.class);
109 40846 jjdelcerro
110 44669 jjdelcerro
    public static final String NAME = DataStore.CSV_PROVIDER_NAME;
111 40846 jjdelcerro
    public static final String DESCRIPTION = "CSV file";
112
113
    public static final String METADATA_DEFINITION_NAME = NAME;
114
115 45721 jjdelcerro
    private final ResourceProvider resource;
116 40846 jjdelcerro
117
    private long counterNewsOIDs = 0;
118
    private Envelope envelope;
119 41059 jjdelcerro
    private boolean need_calculate_envelope = false;
120 44309 omartinez
    private final SimpleTaskStatus taskStatus;
121
    private final CSVFeatureWriter writer;
122 45359 omartinez
    private FeatureType featureType;
123 45727 jjdelcerro
    private GetItemWithSize64<List<String>> virtualrows;
124 45836 fdiaz
    private RowToFeatureTranslator rowToFeatureTranslator;
125 40846 jjdelcerro
126 45721 jjdelcerro
    @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
127 40846 jjdelcerro
    public CSVStoreProvider(CSVStoreParameters parameters,
128 41617 jjdelcerro
            DataStoreProviderServices storeServices) throws InitializeException {
129 40846 jjdelcerro
        super(
130 41617 jjdelcerro
                parameters,
131
                storeServices,
132
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
133 40846 jjdelcerro
        );
134 44309 omartinez
        this.writer = new CSVFeatureWriter();
135 40846 jjdelcerro
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
136
        this.taskStatus = manager.createDefaultSimpleTaskStatus("CSV");
137 45836 fdiaz
        this.taskStatus.setAutoremove(true);
138 40846 jjdelcerro
139
        counterNewsOIDs = 0;
140
141
        File file = getCSVParameters().getFile();
142
        resource = this.createResource(
143 41617 jjdelcerro
                FileResource.NAME,
144
                new Object[]{file.getAbsolutePath()}
145 40846 jjdelcerro
        );
146
147
        resource.addConsumer(this);
148 44309 omartinez
149 41006 jjdelcerro
        initializeFeatureTypes();
150 40846 jjdelcerro
    }
151
152
    private CSVStoreParameters getCSVParameters() {
153
        return (CSVStoreParameters) this.getParameters();
154
    }
155
156 44309 omartinez
    @Override
157 40846 jjdelcerro
    public String getProviderName() {
158
        return NAME;
159
    }
160
161 44309 omartinez
    @Override
162 40846 jjdelcerro
    public boolean allowWrite() {
163 44309 omartinez
        return true;
164 40846 jjdelcerro
    }
165
166 41006 jjdelcerro
    private String getFullFileName() {
167 41617 jjdelcerro
        // Usar solo para mostrar mensajes en el logger.
168 44309 omartinez
        String s;
169 41617 jjdelcerro
        try {
170
            s = getCSVParameters().getFile().getAbsolutePath();
171
        } catch (Exception e2) {
172
            s = "(unknow)";
173
        }
174
        return s;
175 41006 jjdelcerro
    }
176 41617 jjdelcerro
177 44309 omartinez
    @Override
178 40846 jjdelcerro
    public void open() throws OpenException {
179 42775 jjdelcerro
        if (this.data != null) {
180 40846 jjdelcerro
            return;
181
        }
182 43215 jjdelcerro
        this.data = new ArrayList<>();
183 41006 jjdelcerro
        resource.setData(new HashMap());
184
        counterNewsOIDs = 0;
185 41617 jjdelcerro
        try {
186
            loadFeatures();
187
        } catch (RuntimeException e) {
188 44408 jjdelcerro
            LOGGER.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
189 41617 jjdelcerro
            throw e;
190
        } catch (Exception e) {
191 44408 jjdelcerro
            LOGGER.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
192 41617 jjdelcerro
            throw new RuntimeException(e);
193
        }
194 40846 jjdelcerro
    }
195
196 44309 omartinez
    @Override
197 40846 jjdelcerro
    public DataServerExplorer getExplorer() throws ReadException {
198
        DataManager manager = DALLocator.getDataManager();
199 41006 jjdelcerro
        FilesystemServerExplorerParameters params;
200 40846 jjdelcerro
        try {
201
            params = (FilesystemServerExplorerParameters) manager
202 41617 jjdelcerro
                    .createServerExplorerParameters(FilesystemServerExplorer.NAME);
203 40846 jjdelcerro
            params.setRoot(this.getCSVParameters().getFile().getParent());
204 41617 jjdelcerro
            return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
205 45684 jjdelcerro
        } catch (Exception e) {
206 40846 jjdelcerro
            throw new ReadException(this.getProviderName(), e);
207
        }
208
209
    }
210
211 44309 omartinez
    @Override
212 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
213 40846 jjdelcerro
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
214
215
        try {
216
            this.taskStatus.add();
217
            taskStatus.message("_preparing");
218 44309 omartinez
            this.getResource().closeRequest();
219 40846 jjdelcerro
            getResource().execute(new ResourceAction() {
220 44309 omartinez
                @Override
221 40846 jjdelcerro
                public Object run() throws Exception {
222
                    FeatureSet features = null;
223
                    DisposableIterator it = null;
224
                    try {
225
                        File file = (File) resource.get();
226 45836 fdiaz
                        features = getStoreServices().getFeatureStore().getFeatureSet();
227 41617 jjdelcerro
228 45836 fdiaz
                        if (virtualrows == null) {
229
                            List<FeatureProvider> newdata = new ArrayList<>();
230
                            FeatureType ftype = getStoreServices().getDefaultFeatureType();
231
                            writer.initialize(getCSVParameters(), file, ftype, getCSVPreferences());
232
                            writer.begin();
233
                            it = features.fastIterator();
234
                            taskStatus.setRangeOfValues(0, 0);
235
                            long counter = 0;
236
                            while (it.hasNext()) {
237
                                taskStatus.setCurValue(counter++);
238
                                FeatureProvider feature = getStoreServices().getFeatureProviderFromFeature(
239
                                        (org.gvsig.fmap.dal.feature.Feature) it.next());
240
                                writer.add(feature);
241
                                if (feature.getOID() == null) {
242
                                    LOGGER.warn("feature without OID");
243
                                    feature.setOID(createNewOID());
244
                                }
245
                                newdata.add(feature);
246 40846 jjdelcerro
                            }
247 45836 fdiaz
                            data = newdata;
248
                            if (writer.getEnvelope() != null) {
249
                                envelope = writer.getEnvelope().getGeometry().getEnvelope();
250
                            }
251
                            resource.notifyChanges();
252
                            writer.end();
253
254
                        } else {
255
256
                            CSVStoreParameters csvParams = getCSVParameters();
257
                            CSVStoreParameters tmpParams = (CSVStoreParameters) csvParams.getCopy();
258
259
                            String tmpBase = File.createTempFile("tmp_" + System.currentTimeMillis(), null).getAbsolutePath();
260
                            File tmpFile = new File(tmpBase + ".csv");
261
                            tmpParams.setFile(tmpFile);
262
263
                            FeatureType ftype = getStoreServices().getDefaultFeatureType();
264
                            writer.initialize(tmpParams, tmpFile, ftype, getCSVPreferences());
265
                            writer.begin();
266
                            it = features.fastIterator();
267
                            taskStatus.setRangeOfValues(0, 0);
268
                            long counter = 0;
269
                            while (it.hasNext()) {
270
                                taskStatus.setCurValue(counter++);
271
                                FeatureProvider feature = getStoreServices().getFeatureProviderFromFeature(
272
                                        (org.gvsig.fmap.dal.feature.Feature) it.next());
273
                                writer.add(feature);
274
                                if (feature.getOID() == null) {
275
                                    LOGGER.warn("feature without OID");
276
                                    feature.setOID(createNewOID());
277
                                }
278
                            }
279
                            if (writer.getEnvelope() != null) {
280
                                envelope = writer.getEnvelope().getGeometry().getEnvelope();
281
                            }
282
                            resource.notifyChanges();
283
                            writer.end();
284
285
                            if (!csvParams.getFile().delete()) {
286
                                LOGGER.debug("Can't delete csv file '" + csvParams.getFile() + "'.");
287
                                throw new IOException("Can't delete csv '"
288
                                        + FilenameUtils.getBaseName(csvParams.getFile().getAbsolutePath())
289
                                        + "' file to replace with the new csv.\nThe new csv is in temporary file '" + tmpFile.getAbsolutePath()
290
                                        + "'");
291
                            }
292
293
                            File csvFile = csvParams.getFile();
294
                            FileUtils.moveFile(tmpParams.getFile(), csvFile);
295
                            FileUtils.delete(new File(FilenameUtils.removeExtension(csvFile.getAbsolutePath())+".idx"));
296
297
                            loadFeatures();
298 40846 jjdelcerro
                        }
299
                    } finally {
300 42775 jjdelcerro
                        if (it != null) {
301 40846 jjdelcerro
                            it.dispose();
302
                        }
303 42775 jjdelcerro
                        if (features != null) {
304 40846 jjdelcerro
                            features.dispose();
305
                        }
306
                    }
307
                    return null;
308
                }
309 41617 jjdelcerro
310 40846 jjdelcerro
            });
311
            this.taskStatus.terminate();
312
        } catch (Exception e) {
313
            this.taskStatus.abort();
314
            throw new PerformEditingException(getResource().toString(), e);
315
        }
316
    }
317
318 44309 omartinez
    private CsvPreference getCSVPreferences() {
319 45685 jjdelcerro
        CSVReaderSuperCSV reader = new CSVReaderSuperCSV(getCSVParameters());
320 44309 omartinez
        return reader.getCSVPreferences();
321
    }
322
323
    @Override
324 40846 jjdelcerro
    public boolean closeResourceRequested(ResourceProvider resource) {
325
        return true;
326
    }
327
328 44309 omartinez
    @Override
329 40846 jjdelcerro
    public int getOIDType() {
330
        return DataTypes.LONG;
331
    }
332
333 44309 omartinez
    @Override
334 40846 jjdelcerro
    public boolean supportsAppendMode() {
335 44309 omartinez
        return true;
336 40846 jjdelcerro
    }
337
338 44309 omartinez
    @Override
339 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
340 44309 omartinez
    public void append(final FeatureProvider featureProvider) {
341
        //todo
342
        getResource().execute(new ResourceAction() {
343
            @Override
344
            public Object run() throws Exception {
345
                //writer.append(getStoreServices().createFeature(featureProvider));
346
                writer.add(featureProvider);
347
                return null;
348
            }
349
        });
350 40846 jjdelcerro
    }
351
352 44309 omartinez
    @Override
353 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
354 44309 omartinez
    public void beginAppend() throws DataException {
355
        this.close();
356
        getResource().execute(new ResourceAction() {
357 45684 jjdelcerro
            @Override
358 44309 omartinez
            public Object run() throws Exception {
359
                writer.initialize(
360
                        getCSVParameters(),
361
                        getCSVParameters().getFile(),
362
                        getFeatureStore().getDefaultFeatureType(),
363 44388 omartinez
                        getCSVPreferences()
364 44309 omartinez
                );
365
                writer.beginAppend();
366
                return null;
367
            }
368
        });
369
370 40846 jjdelcerro
    }
371
372 44309 omartinez
    @Override
373 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
374 40846 jjdelcerro
    public void endAppend() {
375 44309 omartinez
        try {
376
            getResource().execute(new ResourceAction() {
377 45684 jjdelcerro
                @Override
378 44309 omartinez
                public Object run() throws Exception {
379
                    writer.end();
380
                    resource.notifyChanges(); //resourcesNotifyChanges();
381
                    counterNewsOIDs = -1;
382
                    return null;
383
                }
384
            });
385
            writer.end();
386
        } catch (PerformEditingException ex) {
387 44408 jjdelcerro
            LOGGER.warn("Not been able to end append '" + this.getFullName() + "'.", ex);
388 44309 omartinez
        }
389 40846 jjdelcerro
    }
390
391
    public void saveToState(PersistentState state) throws PersistenceException {
392
        throw new NotYetImplemented();
393
    }
394
395
    public void loadFromState(PersistentState state) throws PersistenceException {
396
        throw new NotYetImplemented();
397
    }
398
399 44309 omartinez
    @Override
400 40846 jjdelcerro
    public Object createNewOID() {
401 44309 omartinez
        return counterNewsOIDs++;
402 40846 jjdelcerro
    }
403
404
    protected void initializeFeatureTypes() throws InitializeException {
405
        try {
406
            this.open();
407
        } catch (OpenException e) {
408
            throw new InitializeException(this.getProviderName(), e);
409
        }
410
    }
411
412 44309 omartinez
    @Override
413 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
414 40846 jjdelcerro
    public Envelope getEnvelope() throws DataException {
415
        this.open();
416 42775 jjdelcerro
        if (this.envelope != null) {
417 41617 jjdelcerro
            return this.envelope;
418 41059 jjdelcerro
        }
419 42775 jjdelcerro
        if (!this.need_calculate_envelope) {
420 41617 jjdelcerro
            return null;
421 41059 jjdelcerro
        }
422
        try {
423 45836 fdiaz
            this.taskStatus.add();
424
            this.taskStatus.message("Calculating envelope");
425
            FeatureStore fs = this.getFeatureStore();
426
            FeatureType ft = fs.getDefaultFeatureType();
427
            FeatureAttributeDescriptor fad = ft.getAttributeDescriptor(ft.getDefaultGeometryAttributeIndex());
428
            this.taskStatus.setRangeOfValues(0, fs.getFeatureCount());
429 41059 jjdelcerro
            this.envelope = GeometryLocator.getGeometryManager().createEnvelope(fad.getGeomType().getSubType());
430 41617 jjdelcerro
            fs.accept(new Visitor() {
431 44309 omartinez
                @Override
432 41617 jjdelcerro
                public void visit(Object obj) throws VisitCanceledException, BaseException {
433 45836 fdiaz
                    taskStatus.incrementCurrentValue();
434
                    if(taskStatus.isCancellationRequested()){
435
                        taskStatus.cancel();
436
                        throw new VisitCanceledException();
437
                    }
438 41617 jjdelcerro
                    Feature f = (Feature) obj;
439
                    Geometry geom = f.getDefaultGeometry();
440 42775 jjdelcerro
                    if (geom != null) {
441 41617 jjdelcerro
                        envelope.add(geom.getEnvelope());
442
                    }
443
                }
444
            });
445 45836 fdiaz
            taskStatus.terminate();
446
        } catch (VisitCanceledException e) {
447
            return null;
448 41617 jjdelcerro
        } catch (BaseException e) {
449 45836 fdiaz
            taskStatus.abort();
450 44408 jjdelcerro
            LOGGER.warn("Can't calculate the envelope of CSV file '" + this.getFullName() + "'.", e);
451 45836 fdiaz
            return null;
452 41617 jjdelcerro
        }
453
454 41059 jjdelcerro
        this.need_calculate_envelope = false;
455 40846 jjdelcerro
        return this.envelope;
456
    }
457
458 44309 omartinez
    @Override
459 40846 jjdelcerro
    public Object getDynValue(String name) throws DynFieldNotFoundException {
460 42775 jjdelcerro
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
461 40846 jjdelcerro
            try {
462
                return this.getEnvelope();
463
            } catch (DataException e) {
464
                return null;
465
            }
466
        } else {
467 42775 jjdelcerro
            if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
468 40878 jjdelcerro
                IProjection pro = CSVStoreParameters.getCRS(this.getCSVParameters());
469 42775 jjdelcerro
                if (pro != null) {
470 40846 jjdelcerro
                    return pro;
471
                }
472
            }
473
        }
474
        return super.getDynValue(name);
475
    }
476
477 44309 omartinez
    @Override
478 40846 jjdelcerro
    public void resourceChanged(ResourceProvider resource) {
479
        this.getStoreServices().notifyChange(
480 41617 jjdelcerro
                DataStoreNotification.RESOURCE_CHANGED,
481
                resource);
482 40846 jjdelcerro
    }
483
484 44309 omartinez
    @Override
485 40846 jjdelcerro
    public Object getSourceId() {
486
        return this.getCSVParameters().getFile();
487
    }
488
489 44309 omartinez
    @Override
490 40846 jjdelcerro
    public String getName() {
491 40878 jjdelcerro
        String name = this.getCSVParameters().getFile().getName();
492 41006 jjdelcerro
        return FilenameUtils.getBaseName(name);
493 40846 jjdelcerro
    }
494
495 44309 omartinez
    @Override
496 40846 jjdelcerro
    public String getFullName() {
497
        return this.getCSVParameters().getFile().getAbsolutePath();
498
    }
499
500 44309 omartinez
    @Override
501 40846 jjdelcerro
    public ResourceProvider getResource() {
502
        return resource;
503
    }
504
505
    private boolean isEmpty(String s) {
506 42775 jjdelcerro
        if (s == null) {
507 41617 jjdelcerro
            return true;
508
        }
509
        return s.trim().length() == 0;
510 40846 jjdelcerro
    }
511 40878 jjdelcerro
512 44309 omartinez
    private void init(CSVStoreParameters parameters, DataStoreProviderServices storeServices) {
513
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
514
    }
515 41617 jjdelcerro
516 41006 jjdelcerro
    static class ToPointEvaluaror extends AbstractEvaluator {
517 40846 jjdelcerro
518 41335 jjdelcerro
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
519 40846 jjdelcerro
520 41335 jjdelcerro
        private GeometryManager geommgr = null;
521
        private String xname = null;
522
        private String yname = null;
523
        private String zname = null;
524 45684 jjdelcerro
        private final Coercion toDouble;
525 41335 jjdelcerro
        private int errorcount = 0;
526
527
        ToPointEvaluaror(String[] pointDimensionNames) {
528
            this.xname = pointDimensionNames[0];
529
            this.yname = pointDimensionNames[1];
530 42775 jjdelcerro
            if (pointDimensionNames.length > 2) {
531 41335 jjdelcerro
                this.zname = pointDimensionNames[2];
532
            }
533
            this.geommgr = GeometryLocator.getGeometryManager();
534
            this.toDouble = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.DOUBLE);
535
        }
536
537 44309 omartinez
        @Override
538 41335 jjdelcerro
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
539
            try {
540 45684 jjdelcerro
                double x = ((Double) toDouble.coerce(data.getDataValue(xname)));
541
                double y = ((Double) toDouble.coerce(data.getDataValue(yname)));
542 41335 jjdelcerro
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
543 42775 jjdelcerro
                if (zname != null) {
544 45684 jjdelcerro
                    double z = ((Double) toDouble.coerce(data.getDataValue(zname)));
545 41335 jjdelcerro
                    point.setCoordinateAt(2, z);
546
                }
547
                return point;
548
            } catch (Exception ex) {
549 42775 jjdelcerro
                if (++errorcount < 5) {
550 41335 jjdelcerro
                    logger.warn("[" + errorcount + "] Can't create point in CSV provider. XNAME='"
551
                            + xname + "', YNAME='" + yname + "', ZNAME='" + zname + "', data=" + data.toString());
552
                }
553
                return null;
554
            }
555
        }
556
557 44309 omartinez
        @Override
558 41335 jjdelcerro
        public String getName() {
559
            return "ToPointEvaluaror";
560
        }
561
562 40846 jjdelcerro
    }
563 41335 jjdelcerro
564 45727 jjdelcerro
    public static class RowToFeatureTranslator {
565 45836 fdiaz
566 45727 jjdelcerro
        private Coercion coercion[];
567
        private CoercionContext coercionContext[];
568
        private int sizes[];
569
        private final boolean ignore_errors;
570
        private long count_errors;
571 45836 fdiaz
        private FeatureType csvFeatureType;
572 45727 jjdelcerro
573
        public RowToFeatureTranslator(boolean ignore_errors) {
574
            this.ignore_errors = ignore_errors;
575
            this.count_errors = 0;
576
        }
577
578
        public int getColumnSize(int column) {
579
            return this.sizes[column];
580
        }
581 45836 fdiaz
582 45727 jjdelcerro
        public void initialize(FeatureType ftype) {
583 45836 fdiaz
            this.csvFeatureType = ftype;
584
            int columns = this.csvFeatureType.size();
585 45727 jjdelcerro
            this.coercion = new Coercion[columns];
586
            this.coercionContext = new CoercionContext[columns];
587
            this.sizes = new int[columns];
588 45836 fdiaz
            for (int i = 0; i < this.csvFeatureType.size(); i++) {
589
                FeatureAttributeDescriptor ad = this.csvFeatureType.getAttributeDescriptor(i);
590 45727 jjdelcerro
                coercion[i] = ad.getCoercion();
591
                coercionContext[i] = ad.getCoercionContext();
592
                sizes[i] = ad.getSize();
593
//                sizes[i] = -1;
594
//                switch (ad.getDataType().getType()) {
595
//                    case DataTypes.INT:
596
//                        sizes[i] = 0;
597
//                        break;
598
//                    case DataTypes.LONG:
599
//                        sizes[i] = 0;
600
//                        break;
601
//                    case DataTypes.STRING:
602
//                        if (ad.getSize() == 0) {
603
//                            // Es un string y no tiene un size asignado.
604
//                            // Lo ponemos a cero para calcularlo.
605
//                            sizes[i] = 0;
606
//                        }
607
//                        break;
608
//                    case DataTypes.URL:
609
//                    case DataTypes.URI:
610
//                    case DataTypes.FILE:
611
//                        sizes[i] = 0;
612
//                }
613
            }
614
        }
615 45836 fdiaz
616 45727 jjdelcerro
        public void translate(long rowindex, List<String> row, FeatureProvider feature) throws Exception {
617
618 45836 fdiaz
            feature.setOID(rowindex);
619
            FeatureType featureType = feature.getType();
620
621
            for (FeatureAttributeDescriptor attr : featureType) {
622
                int featureAttrIndex = attr.getIndex();
623
                int csvAttrIndex = csvFeatureType.getAttributeDescriptor(attr.getName()).getIndex();
624
                Object rawvalue = row.get(csvAttrIndex);
625 45727 jjdelcerro
                try {
626
                    Object value = null;
627 45836 fdiaz
                    if (coercion[csvAttrIndex] != null) {
628
                        value = coercion[csvAttrIndex].coerce(rawvalue, coercionContext[csvAttrIndex]);
629 45727 jjdelcerro
                    }
630 45836 fdiaz
                    feature.set(featureAttrIndex, value);
631
                    if (sizes[csvAttrIndex] >= 0
632 45727 jjdelcerro
                            && (value instanceof String || value instanceof URL
633
                            || value instanceof URI || value instanceof File)) {
634
                        int x = value.toString().length();
635 45836 fdiaz
                        if (sizes[csvAttrIndex] < x) {
636
                            sizes[csvAttrIndex] = x;
637 45727 jjdelcerro
                        }
638
                    }
639
                } catch (Exception ex) {
640
                    if (!ignore_errors) {
641
                        throw ex;
642
                    }
643
                    if (count_errors++ < 10) {
644 45836 fdiaz
                        LOGGER.warn("Can't load value of attribute " + featureAttrIndex + " in row " + rowindex + ".", ex);
645 45727 jjdelcerro
                    }
646
                    if (count_errors == 10) {
647
                        LOGGER.info("Too many errors, suppress messages.");
648
                    }
649
                }
650
            }
651
        }
652
    }
653
654 45684 jjdelcerro
    private void loadFeatures() {
655
        InputStreamReader in = null;
656
        SimpleReader reader = null;
657
        try {
658 45817 jjdelcerro
            taskStatus.add();
659 45727 jjdelcerro
//            boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
660 45684 jjdelcerro
661
            // Initialize the feature types
662
            EditableFeatureType edftype = getStoreServices().createFeatureType(this.getName());
663 45685 jjdelcerro
            CSVUtils.loadFeatureType(getCSVParameters(), edftype, true);
664 41617 jjdelcerro
            FeatureType ftype = edftype.getNotEditableCopy();
665 45359 omartinez
            this.setFeatureType(ftype);
666 41059 jjdelcerro
667 45685 jjdelcerro
            in = CSVUtils.openFile(
668 45684 jjdelcerro
                    this.getCSVParameters().getFile(),
669
                    CSVStoreParameters.getCharset(this.getCSVParameters())
670
            );
671 45685 jjdelcerro
            reader = CSVUtils.getSimpleReader(getCSVParameters(), in);
672 45684 jjdelcerro
            if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
673
                reader.getHeader(); // Skip and ignore the header of file
674
            }
675 45727 jjdelcerro
            this.rowToFeatureTranslator = new RowToFeatureTranslator(
676
                    CSVStoreParameters.getIgnoreErrors(getCSVParameters())
677
            );
678
            this.rowToFeatureTranslator.initialize(ftype);
679
//            Coercion coercion[] = new Coercion[ftype.size()];
680
//            CoercionContext coercionContext[] = new CoercionContext[ftype.size()];
681
//            int sizes[] = new int[ftype.size()];
682
//            for (int i = 0; i < ftype.size(); i++) {
683
//                sizes[i] = -1;
684
//                FeatureAttributeDescriptor ad = ftype.getAttributeDescriptor(i);
685
//                coercion[i] = ad.getCoercion();
686
//                coercionContext[i] = ad.getCoercionContext();
687
//                switch (ad.getDataType().getType()) {
688
//                    case DataTypes.INT:
689
//                        sizes[i] = 0;
690
//                        break;
691
//                    case DataTypes.LONG:
692
//                        sizes[i] = 0;
693
//                        break;
694
//                    case DataTypes.STRING:
695
//                        if (ad.getSize() == 0) {
696
//                            // Es un string y no tiene un size asignado.
697
//                            // Lo ponemos a cero para calcularlo.
698
//                            sizes[i] = 0;
699
//                        }
700
//                        break;
701
//                    case DataTypes.URL:
702
//                    case DataTypes.URI:
703
//                    case DataTypes.FILE:
704
//                        sizes[i] = 0;
705
//                }
706
//            }
707 42775 jjdelcerro
            if (ftype.getDefaultGeometryAttributeName() != null) {
708 41617 jjdelcerro
                this.need_calculate_envelope = true;
709
            }
710 41006 jjdelcerro
711 41617 jjdelcerro
            Locale locale = CSVStoreParameters.getLocale(getCSVParameters());
712
            taskStatus.message("_loading");
713
            int count = 0;
714 41062 jjdelcerro
715 45836 fdiaz
            if(this.virtualrows != null && this.virtualrows instanceof Closeable){
716
                IOUtils.closeQuietly((Closeable) this.virtualrows);
717
                this.virtualrows = null;
718
            }
719
720
            this.virtualrows = ((AbstractSimpleReader) reader).getVirtualRows(this.taskStatus);
721
            if (this.virtualrows == null) {
722 41062 jjdelcerro
723 45727 jjdelcerro
                List<String> row = reader.read();
724 41062 jjdelcerro
725 45727 jjdelcerro
                int skipLines = CSVStoreParameters.getSkipLines(getCSVParameters());
726
                if (skipLines > 0) {
727
                    row = reader.skip(skipLines);
728
                }
729
                int limit = CSVStoreParameters.getLimit(getCSVParameters());
730
                while (row != null) {
731
                    taskStatus.setCurValue(++count);
732
                    FeatureProvider feature = this.createFeatureProvider(ftype);
733
                    this.rowToFeatureTranslator.translate(count, row, feature);
734
//                    for (int i = 0; i < row.size(); i++) {
735
//                        Object rawvalue = row.get(i);
736
//                        try {
737
//                            Object value = null;
738
//                            if( coercion[i]!=null ) {
739
//                              value = coercion[i].coerce(rawvalue, coercionContext[i]);
740
//                            }
741
//                            feature.set(i, value);
742
//                            if (sizes[i] >= 0
743
//                                    && (value instanceof String || value instanceof URL
744
//                                    || value instanceof URI || value instanceof File)) {
745
//                                int x = value.toString().length();
746
//                                if (sizes[i] < x) {
747
//                                    sizes[i] = x;
748
//                                }
749
//                            }
750
//                        } catch (Exception ex) {
751
//                            if (!ignore_errors) {
752
//                                throw ex;
753
//                            }
754
//                            if (count_errors++ < 10) {
755
//                                LOGGER.warn("Can't load value of attribute " + i + " in row " + count + ".", ex);
756
//                            }
757
//                            if (count_errors == 10) {
758
//                                LOGGER.info("Too many errors, suppress messages.");
759
//                            }
760
//                        }
761
//                    }
762 45836 fdiaz
763 45727 jjdelcerro
                    this.addFeatureProvider(feature);
764
                    if (limit > 0) {
765
                        if (limit < this.data.size()) {
766
                            break;
767 44749 jjdelcerro
                        }
768 41617 jjdelcerro
                    }
769 45727 jjdelcerro
                    row = reader.read();
770 41617 jjdelcerro
                }
771 45727 jjdelcerro
                for (int i = 0; i < ftype.size(); i++) {
772 45836 fdiaz
                    if (this.rowToFeatureTranslator.getColumnSize(i) > 0) {
773 45727 jjdelcerro
//                    if (sizes[i] > 0) {
774
                        EditableFeatureAttributeDescriptor efad = ((EditableFeatureAttributeDescriptor) edftype.getAttributeDescriptor(i));
775
//                        efad.setSize(sizes[i]);
776
                        efad.setSize(this.rowToFeatureTranslator.getColumnSize(i));
777 42775 jjdelcerro
                    }
778
                }
779 45727 jjdelcerro
                // Volvemos a asignar al store el featuretype, ya que puede
780
                // haber cambiado.
781
                ftype = edftype.getNotEditableCopy();
782
                this.setFeatureType(ftype);
783 41617 jjdelcerro
            }
784 45836 fdiaz
785 41617 jjdelcerro
            taskStatus.terminate();
786 44963 jjdelcerro
        } catch (Throwable ex) {
787 45817 jjdelcerro
            taskStatus.abort();
788 41643 jjdelcerro
            int lineno = 0;
789 42775 jjdelcerro
            if (reader != null) {
790 41643 jjdelcerro
                lineno = reader.getLine();
791
            }
792 42775 jjdelcerro
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
793 41643 jjdelcerro
794 41617 jjdelcerro
        } finally {
795 42775 jjdelcerro
            if (reader != null) {
796 41617 jjdelcerro
                try {
797
                    reader.close();
798
                } catch (Exception ex) {
799
                    // Do nothing
800
                }
801 45684 jjdelcerro
//                reader = null;
802 41617 jjdelcerro
            }
803 42775 jjdelcerro
            if (in != null) {
804 41617 jjdelcerro
                try {
805
                    in.close();
806
                } catch (Exception ex) {
807
                    // Do nothing
808
                }
809 45684 jjdelcerro
//                in = null;
810 41617 jjdelcerro
            }
811
        }
812
    }
813 41062 jjdelcerro
814 45359 omartinez
    @Override
815
    public void fixFeatureTypeFromParameters() {
816
        String param_types_def = CSVStoreParameters.getRawFieldTypes(this.getParameters());
817
        String[] pointDimensionNames = CSVStoreParameters.getPointDimensionNames(this.getParameters());
818
        String geometry_column = CSVStoreParameters.getGeometryColumn(this.getParameters());
819 45836 fdiaz
        if (StringUtils.isNotBlank(param_types_def)
820
                || pointDimensionNames != null
821
                || !StringUtils.isBlank(geometry_column)) {
822 45359 omartinez
            this.setFeatureType(featureType);
823
        }
824
    }
825 45836 fdiaz
826 45359 omartinez
    private void setFeatureType(FeatureType ftype) {
827
        List<FeatureType> ftypes = new ArrayList<>();
828
        ftypes.add(ftype);
829
        this.featureType = ftype;
830 45684 jjdelcerro
        this.getStoreServices().setFeatureTypes(ftypes, ftype);
831 45359 omartinez
    }
832 42775 jjdelcerro
833 45727 jjdelcerro
    @Override
834
    public FeatureSetProvider createSet(FeatureQuery query, FeatureType featureType)
835
            throws DataException {
836 45836 fdiaz
        if (this.virtualrows == null) {
837 45727 jjdelcerro
            return super.createSet(query, featureType);
838
        }
839
        return new CSVSetProvider(this, query, featureType);
840 45836 fdiaz
    }
841 45727 jjdelcerro
842
    public List<String> getRowByIndex(long index) {
843 45836 fdiaz
        if (this.virtualrows == null) {
844 45727 jjdelcerro
            return null;
845
        }
846
        return this.virtualrows.get64(index);
847
    }
848 45836 fdiaz
849 45727 jjdelcerro
    public RowToFeatureTranslator getRowToFeatureTranslator() {
850 45836 fdiaz
        if (this.rowToFeatureTranslator == null) {
851 45727 jjdelcerro
            boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
852
            this.rowToFeatureTranslator = new RowToFeatureTranslator(ignore_errors);
853
            this.rowToFeatureTranslator.initialize(featureType);
854
        }
855
        return this.rowToFeatureTranslator;
856
    }
857
858
    @Override
859
    public long getFeatureCount() throws DataException {
860 45836 fdiaz
        if (this.virtualrows == null) {
861
            return super.getFeatureCount();
862 45727 jjdelcerro
        }
863
        return this.virtualrows.size64();
864
    }
865 45836 fdiaz
866
    public long getDataSize() throws DataException {
867
        if (this.virtualrows == null) {
868
            return super.getDataSize();
869
        }
870
        return this.virtualrows.size64();
871
    }
872
873
    @Override
874
    protected FeatureProvider internalGetFeatureProviderByReference(
875
            FeatureReferenceProviderServices reference) throws DataException {
876
        if (this.virtualrows == null) {
877
            return super.internalGetFeatureProviderByReference(reference);
878
        }
879
        int oid = ((Long) reference.getOID()).intValue();
880
        RowToFeatureTranslator translator = getRowToFeatureTranslator();
881
        FeatureProvider feature = this.createFeatureProvider(this.featureType);
882
        try {
883
            translator.translate(oid, this.virtualrows.get64(oid), feature);
884
        } catch (Exception ex) {
885
            throw new CreateFeatureException(ex, this.getName());
886
        }
887
        return feature;
888
    }
889
890
    @Override
891
    protected void doDispose() throws BaseException {
892
        super.doDispose();
893
        if (this.virtualrows != null && this.virtualrows instanceof Closeable) {
894
            IOUtils.closeQuietly((Closeable) this.virtualrows);
895
            this.virtualrows = null;
896
        }
897
    }
898 45727 jjdelcerro
899
900 45836 fdiaz
901 40846 jjdelcerro
}