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 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 45836 fdiaz
import org.apache.commons.io.FileUtils;
36 40846 jjdelcerro
37 41006 jjdelcerro
import org.apache.commons.io.FilenameUtils;
38 45836 fdiaz
import org.apache.commons.io.IOUtils;
39 41876 jjdelcerro
import org.apache.commons.lang3.StringUtils;
40 40846 jjdelcerro
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 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
53 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureType;
54 41059 jjdelcerro
import org.gvsig.fmap.dal.feature.Feature;
55 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
56 45727 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureQuery;
57 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureSet;
58 41059 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStore;
59 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
60 45836 fdiaz
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
61 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
62 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
63 45836 fdiaz
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
64 45727 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
65 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.memory.AbstractMemoryStoreProvider;
66 41006 jjdelcerro
import org.gvsig.fmap.dal.resource.ResourceAction;
67 40846 jjdelcerro
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 45727 jjdelcerro
import org.gvsig.fmap.dal.store.csv.simplereaders.AbstractSimpleReader;
74 45685 jjdelcerro
import org.gvsig.fmap.dal.store.csv.simplereaders.CSVReaderSuperCSV;
75 41617 jjdelcerro
import org.gvsig.fmap.dal.store.csv.simplereaders.SimpleReader;
76 40846 jjdelcerro
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 41006 jjdelcerro
import org.gvsig.fmap.geom.primitive.Point;
81 40846 jjdelcerro
import org.gvsig.tools.ToolsLocator;
82 44669 jjdelcerro
import org.gvsig.tools.dataTypes.Coercion;
83 41006 jjdelcerro
import org.gvsig.tools.dispose.DisposableIterator;
84 40846 jjdelcerro
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
85 41006 jjdelcerro
import org.gvsig.tools.evaluator.AbstractEvaluator;
86
import org.gvsig.tools.evaluator.EvaluatorData;
87
import org.gvsig.tools.evaluator.EvaluatorException;
88 41059 jjdelcerro
import org.gvsig.tools.exception.BaseException;
89 40846 jjdelcerro
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 41059 jjdelcerro
import org.gvsig.tools.visitor.VisitCanceledException;
95
import org.gvsig.tools.visitor.Visitor;
96 40846 jjdelcerro
import org.slf4j.Logger;
97
import org.slf4j.LoggerFactory;
98 40878 jjdelcerro
import org.supercsv.prefs.CsvPreference;
99 44669 jjdelcerro
import org.gvsig.tools.dataTypes.CoercionContext;
100 45929 jjdelcerro
import org.gvsig.tools.i18n.I18nManager;
101 45727 jjdelcerro
import org.gvsig.tools.util.GetItemWithSize64;
102 40846 jjdelcerro
103 44309 omartinez
@SuppressWarnings("UseSpecificCatch")
104 40846 jjdelcerro
public class CSVStoreProvider extends AbstractMemoryStoreProvider implements
105 41617 jjdelcerro
        ResourceConsumer {
106
107 44408 jjdelcerro
    private static final Logger LOGGER = LoggerFactory.getLogger(CSVStoreProvider.class);
108 40846 jjdelcerro
109 44669 jjdelcerro
    public static final String NAME = DataStore.CSV_PROVIDER_NAME;
110 40846 jjdelcerro
    public static final String DESCRIPTION = "CSV file";
111
112
    public static final String METADATA_DEFINITION_NAME = NAME;
113
114 45721 jjdelcerro
    private final ResourceProvider resource;
115 40846 jjdelcerro
116
    private long counterNewsOIDs = 0;
117
    private Envelope envelope;
118 41059 jjdelcerro
    private boolean need_calculate_envelope = false;
119 44309 omartinez
    private final SimpleTaskStatus taskStatus;
120
    private final CSVFeatureWriter writer;
121 45359 omartinez
    private FeatureType featureType;
122 45727 jjdelcerro
    private GetItemWithSize64<List<String>> virtualrows;
123 45836 fdiaz
    private RowToFeatureTranslator rowToFeatureTranslator;
124 40846 jjdelcerro
125 45721 jjdelcerro
    @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
126 40846 jjdelcerro
    public CSVStoreProvider(CSVStoreParameters parameters,
127 41617 jjdelcerro
            DataStoreProviderServices storeServices) throws InitializeException {
128 40846 jjdelcerro
        super(
129 41617 jjdelcerro
                parameters,
130
                storeServices,
131
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
132 40846 jjdelcerro
        );
133 44309 omartinez
        this.writer = new CSVFeatureWriter();
134 40846 jjdelcerro
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
135
        this.taskStatus = manager.createDefaultSimpleTaskStatus("CSV");
136 45836 fdiaz
        this.taskStatus.setAutoremove(true);
137 40846 jjdelcerro
138
        counterNewsOIDs = 0;
139
140
        File file = getCSVParameters().getFile();
141
        resource = this.createResource(
142 41617 jjdelcerro
                FileResource.NAME,
143
                new Object[]{file.getAbsolutePath()}
144 40846 jjdelcerro
        );
145
146
        resource.addConsumer(this);
147 44309 omartinez
148 41006 jjdelcerro
        initializeFeatureTypes();
149 40846 jjdelcerro
    }
150
151
    private CSVStoreParameters getCSVParameters() {
152
        return (CSVStoreParameters) this.getParameters();
153
    }
154
155 44309 omartinez
    @Override
156 40846 jjdelcerro
    public String getProviderName() {
157
        return NAME;
158
    }
159
160 44309 omartinez
    @Override
161 40846 jjdelcerro
    public boolean allowWrite() {
162 44309 omartinez
        return true;
163 40846 jjdelcerro
    }
164
165 41006 jjdelcerro
    private String getFullFileName() {
166 41617 jjdelcerro
        // Usar solo para mostrar mensajes en el logger.
167 44309 omartinez
        String s;
168 41617 jjdelcerro
        try {
169
            s = getCSVParameters().getFile().getAbsolutePath();
170
        } catch (Exception e2) {
171
            s = "(unknow)";
172
        }
173
        return s;
174 41006 jjdelcerro
    }
175 41617 jjdelcerro
176 44309 omartinez
    @Override
177 40846 jjdelcerro
    public void open() throws OpenException {
178 42775 jjdelcerro
        if (this.data != null) {
179 40846 jjdelcerro
            return;
180
        }
181 43215 jjdelcerro
        this.data = new ArrayList<>();
182 41006 jjdelcerro
        resource.setData(new HashMap());
183
        counterNewsOIDs = 0;
184 41617 jjdelcerro
        try {
185
            loadFeatures();
186
        } catch (RuntimeException e) {
187 44408 jjdelcerro
            LOGGER.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
188 41617 jjdelcerro
            throw e;
189
        } catch (Exception e) {
190 44408 jjdelcerro
            LOGGER.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
191 41617 jjdelcerro
            throw new RuntimeException(e);
192
        }
193 40846 jjdelcerro
    }
194
195 44309 omartinez
    @Override
196 40846 jjdelcerro
    public DataServerExplorer getExplorer() throws ReadException {
197
        DataManager manager = DALLocator.getDataManager();
198 41006 jjdelcerro
        FilesystemServerExplorerParameters params;
199 40846 jjdelcerro
        try {
200
            params = (FilesystemServerExplorerParameters) manager
201 41617 jjdelcerro
                    .createServerExplorerParameters(FilesystemServerExplorer.NAME);
202 40846 jjdelcerro
            params.setRoot(this.getCSVParameters().getFile().getParent());
203 41617 jjdelcerro
            return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
204 45684 jjdelcerro
        } catch (Exception e) {
205 40846 jjdelcerro
            throw new ReadException(this.getProviderName(), e);
206
        }
207
208
    }
209
210 44309 omartinez
    @Override
211 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
212 40846 jjdelcerro
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
213
214
        try {
215 45929 jjdelcerro
            I18nManager i18n = ToolsLocator.getI18nManager();
216 40846 jjdelcerro
            this.taskStatus.add();
217 45929 jjdelcerro
            taskStatus.message(i18n.getTranslation("_Preparing_writing"));
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 45929 jjdelcerro
                        taskStatus.message(i18n.getTranslation("_Writing_records"));
229 45836 fdiaz
                        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 45929 jjdelcerro
                            taskStatus.setRangeOfValues(0, features.getSize());
236
                            taskStatus.setCurValue(0);
237 45836 fdiaz
                            while (it.hasNext()) {
238 45929 jjdelcerro
                                taskStatus.incrementCurrentValue();
239 45836 fdiaz
                                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 40846 jjdelcerro
                            }
248 45836 fdiaz
                            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 45929 jjdelcerro
                            taskStatus.setIndeterminate();
269
                            taskStatus.setCurValue(0);
270 45836 fdiaz
                            while (it.hasNext()) {
271 45929 jjdelcerro
                                taskStatus.incrementCurrentValue();
272
                                if( taskStatus.isCancellationRequested() ) {
273
                                    taskStatus.cancel();
274
                                    LOGGER.info("CSV writing canceled ("+getFullFileName()+")");
275
                                    break;
276
                                }
277 45836 fdiaz
                                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 45929 jjdelcerro
                            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 45836 fdiaz
299 45929 jjdelcerro
                                File csvFile = csvParams.getFile();
300
                                FileUtils.moveFile(tmpParams.getFile(), csvFile);
301
                                FileUtils.delete(new File(FilenameUtils.removeExtension(csvFile.getAbsolutePath())+".idx"));
302 45836 fdiaz
303 45929 jjdelcerro
                                loadFeatures();
304
                            }
305 40846 jjdelcerro
                        }
306
                    } finally {
307 42775 jjdelcerro
                        if (it != null) {
308 40846 jjdelcerro
                            it.dispose();
309
                        }
310 42775 jjdelcerro
                        if (features != null) {
311 40846 jjdelcerro
                            features.dispose();
312
                        }
313
                    }
314
                    return null;
315
                }
316 41617 jjdelcerro
317 40846 jjdelcerro
            });
318
            this.taskStatus.terminate();
319
        } catch (Exception e) {
320
            this.taskStatus.abort();
321
            throw new PerformEditingException(getResource().toString(), e);
322
        }
323
    }
324
325 44309 omartinez
    private CsvPreference getCSVPreferences() {
326 45685 jjdelcerro
        CSVReaderSuperCSV reader = new CSVReaderSuperCSV(getCSVParameters());
327 44309 omartinez
        return reader.getCSVPreferences();
328
    }
329
330
    @Override
331 40846 jjdelcerro
    public boolean closeResourceRequested(ResourceProvider resource) {
332
        return true;
333
    }
334
335 44309 omartinez
    @Override
336 40846 jjdelcerro
    public int getOIDType() {
337
        return DataTypes.LONG;
338
    }
339
340 44309 omartinez
    @Override
341 40846 jjdelcerro
    public boolean supportsAppendMode() {
342 44309 omartinez
        return true;
343 40846 jjdelcerro
    }
344
345 44309 omartinez
    @Override
346 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
347 44309 omartinez
    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 40846 jjdelcerro
    }
358
359 44309 omartinez
    @Override
360 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
361 44309 omartinez
    public void beginAppend() throws DataException {
362
        this.close();
363
        getResource().execute(new ResourceAction() {
364 45684 jjdelcerro
            @Override
365 44309 omartinez
            public Object run() throws Exception {
366
                writer.initialize(
367
                        getCSVParameters(),
368
                        getCSVParameters().getFile(),
369
                        getFeatureStore().getDefaultFeatureType(),
370 44388 omartinez
                        getCSVPreferences()
371 44309 omartinez
                );
372
                writer.beginAppend();
373
                return null;
374
            }
375
        });
376
377 40846 jjdelcerro
    }
378
379 44309 omartinez
    @Override
380 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
381 40846 jjdelcerro
    public void endAppend() {
382 44309 omartinez
        try {
383
            getResource().execute(new ResourceAction() {
384 45684 jjdelcerro
                @Override
385 44309 omartinez
                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 44408 jjdelcerro
            LOGGER.warn("Not been able to end append '" + this.getFullName() + "'.", ex);
395 44309 omartinez
        }
396 40846 jjdelcerro
    }
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 44309 omartinez
    @Override
407 40846 jjdelcerro
    public Object createNewOID() {
408 44309 omartinez
        return counterNewsOIDs++;
409 40846 jjdelcerro
    }
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 44309 omartinez
    @Override
420 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
421 40846 jjdelcerro
    public Envelope getEnvelope() throws DataException {
422
        this.open();
423 42775 jjdelcerro
        if (this.envelope != null) {
424 41617 jjdelcerro
            return this.envelope;
425 41059 jjdelcerro
        }
426 42775 jjdelcerro
        if (!this.need_calculate_envelope) {
427 41617 jjdelcerro
            return null;
428 41059 jjdelcerro
        }
429
        try {
430 45929 jjdelcerro
            I18nManager i18n = ToolsLocator.getI18nManager();
431 45836 fdiaz
            this.taskStatus.add();
432 45929 jjdelcerro
            this.taskStatus.message(i18n.getTranslation("_Calculating_envelope"));
433 45836 fdiaz
            FeatureStore fs = this.getFeatureStore();
434
            FeatureType ft = fs.getDefaultFeatureType();
435
            FeatureAttributeDescriptor fad = ft.getAttributeDescriptor(ft.getDefaultGeometryAttributeIndex());
436
            this.taskStatus.setRangeOfValues(0, fs.getFeatureCount());
437 41059 jjdelcerro
            this.envelope = GeometryLocator.getGeometryManager().createEnvelope(fad.getGeomType().getSubType());
438 41617 jjdelcerro
            fs.accept(new Visitor() {
439 44309 omartinez
                @Override
440 41617 jjdelcerro
                public void visit(Object obj) throws VisitCanceledException, BaseException {
441 45836 fdiaz
                    taskStatus.incrementCurrentValue();
442
                    if(taskStatus.isCancellationRequested()){
443
                        taskStatus.cancel();
444
                        throw new VisitCanceledException();
445
                    }
446 41617 jjdelcerro
                    Feature f = (Feature) obj;
447
                    Geometry geom = f.getDefaultGeometry();
448 42775 jjdelcerro
                    if (geom != null) {
449 41617 jjdelcerro
                        envelope.add(geom.getEnvelope());
450
                    }
451
                }
452
            });
453 45836 fdiaz
            taskStatus.terminate();
454
        } catch (VisitCanceledException e) {
455
            return null;
456 41617 jjdelcerro
        } catch (BaseException e) {
457 45836 fdiaz
            taskStatus.abort();
458 44408 jjdelcerro
            LOGGER.warn("Can't calculate the envelope of CSV file '" + this.getFullName() + "'.", e);
459 45836 fdiaz
            return null;
460 41617 jjdelcerro
        }
461
462 41059 jjdelcerro
        this.need_calculate_envelope = false;
463 40846 jjdelcerro
        return this.envelope;
464
    }
465
466 44309 omartinez
    @Override
467 40846 jjdelcerro
    public Object getDynValue(String name) throws DynFieldNotFoundException {
468 42775 jjdelcerro
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
469 40846 jjdelcerro
            try {
470
                return this.getEnvelope();
471
            } catch (DataException e) {
472
                return null;
473
            }
474
        } else {
475 42775 jjdelcerro
            if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
476 40878 jjdelcerro
                IProjection pro = CSVStoreParameters.getCRS(this.getCSVParameters());
477 42775 jjdelcerro
                if (pro != null) {
478 40846 jjdelcerro
                    return pro;
479
                }
480
            }
481
        }
482
        return super.getDynValue(name);
483
    }
484
485 44309 omartinez
    @Override
486 40846 jjdelcerro
    public void resourceChanged(ResourceProvider resource) {
487
        this.getStoreServices().notifyChange(
488 41617 jjdelcerro
                DataStoreNotification.RESOURCE_CHANGED,
489
                resource);
490 40846 jjdelcerro
    }
491
492 44309 omartinez
    @Override
493 40846 jjdelcerro
    public Object getSourceId() {
494
        return this.getCSVParameters().getFile();
495
    }
496
497 44309 omartinez
    @Override
498 40846 jjdelcerro
    public String getName() {
499 40878 jjdelcerro
        String name = this.getCSVParameters().getFile().getName();
500 41006 jjdelcerro
        return FilenameUtils.getBaseName(name);
501 40846 jjdelcerro
    }
502
503 44309 omartinez
    @Override
504 40846 jjdelcerro
    public String getFullName() {
505
        return this.getCSVParameters().getFile().getAbsolutePath();
506
    }
507
508 44309 omartinez
    @Override
509 40846 jjdelcerro
    public ResourceProvider getResource() {
510
        return resource;
511
    }
512
513
    private boolean isEmpty(String s) {
514 42775 jjdelcerro
        if (s == null) {
515 41617 jjdelcerro
            return true;
516
        }
517
        return s.trim().length() == 0;
518 40846 jjdelcerro
    }
519 40878 jjdelcerro
520 44309 omartinez
    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 41617 jjdelcerro
524 41006 jjdelcerro
    static class ToPointEvaluaror extends AbstractEvaluator {
525 40846 jjdelcerro
526 41335 jjdelcerro
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
527 40846 jjdelcerro
528 41335 jjdelcerro
        private GeometryManager geommgr = null;
529
        private String xname = null;
530
        private String yname = null;
531
        private String zname = null;
532 45684 jjdelcerro
        private final Coercion toDouble;
533 41335 jjdelcerro
        private int errorcount = 0;
534
535
        ToPointEvaluaror(String[] pointDimensionNames) {
536
            this.xname = pointDimensionNames[0];
537
            this.yname = pointDimensionNames[1];
538 42775 jjdelcerro
            if (pointDimensionNames.length > 2) {
539 41335 jjdelcerro
                this.zname = pointDimensionNames[2];
540
            }
541
            this.geommgr = GeometryLocator.getGeometryManager();
542
            this.toDouble = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.DOUBLE);
543
        }
544
545 44309 omartinez
        @Override
546 41335 jjdelcerro
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
547
            try {
548 45684 jjdelcerro
                double x = ((Double) toDouble.coerce(data.getDataValue(xname)));
549
                double y = ((Double) toDouble.coerce(data.getDataValue(yname)));
550 41335 jjdelcerro
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
551 42775 jjdelcerro
                if (zname != null) {
552 45684 jjdelcerro
                    double z = ((Double) toDouble.coerce(data.getDataValue(zname)));
553 41335 jjdelcerro
                    point.setCoordinateAt(2, z);
554
                }
555
                return point;
556
            } catch (Exception ex) {
557 42775 jjdelcerro
                if (++errorcount < 5) {
558 41335 jjdelcerro
                    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 44309 omartinez
        @Override
566 41335 jjdelcerro
        public String getName() {
567
            return "ToPointEvaluaror";
568
        }
569
570 40846 jjdelcerro
    }
571 41335 jjdelcerro
572 45727 jjdelcerro
    public static class RowToFeatureTranslator {
573 45836 fdiaz
574 45727 jjdelcerro
        private Coercion coercion[];
575
        private CoercionContext coercionContext[];
576
        private int sizes[];
577 45990 jjdelcerro
        private String[] names;
578 45727 jjdelcerro
        private final boolean ignore_errors;
579
        private long count_errors;
580 45836 fdiaz
        private FeatureType csvFeatureType;
581 45727 jjdelcerro
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 45836 fdiaz
591 45727 jjdelcerro
        public void initialize(FeatureType ftype) {
592 45836 fdiaz
            this.csvFeatureType = ftype;
593
            int columns = this.csvFeatureType.size();
594 45990 jjdelcerro
            this.names = new String[columns];
595 45727 jjdelcerro
            this.coercion = new Coercion[columns];
596
            this.coercionContext = new CoercionContext[columns];
597
            this.sizes = new int[columns];
598 45990 jjdelcerro
            int index = 0;
599 45836 fdiaz
            for (int i = 0; i < this.csvFeatureType.size(); i++) {
600
                FeatureAttributeDescriptor ad = this.csvFeatureType.getAttributeDescriptor(i);
601 45990 jjdelcerro
                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 45727 jjdelcerro
            }
611
        }
612 45836 fdiaz
613 45727 jjdelcerro
        public void translate(long rowindex, List<String> row, FeatureProvider feature) throws Exception {
614
615 45836 fdiaz
            feature.setOID(rowindex);
616 45990 jjdelcerro
            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 45727 jjdelcerro
                try {
623
                    Object value = null;
624 45990 jjdelcerro
                    if (coercion[i] != null) {
625
                        value = coercion[i].coerce(rawvalue, coercionContext[i]);
626 45727 jjdelcerro
                    }
627 46080 jjdelcerro
                    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 45990 jjdelcerro
                    if (sizes[i] >= 0
634 45727 jjdelcerro
                            && (value instanceof String || value instanceof URL
635
                            || value instanceof URI || value instanceof File)) {
636
                        int x = value.toString().length();
637 45990 jjdelcerro
                        if (sizes[i] < x) {
638
                            sizes[i] = x;
639 45727 jjdelcerro
                        }
640
                    }
641
                } catch (Exception ex) {
642
                    if (!ignore_errors) {
643
                        throw ex;
644
                    }
645
                    if (count_errors++ < 10) {
646 45990 jjdelcerro
                        LOGGER.warn("Can't load value of attribute " + name +"/" +i+" in row " + rowindex + ".", ex);
647 45727 jjdelcerro
                    }
648
                    if (count_errors == 10) {
649
                        LOGGER.info("Too many errors, suppress messages.");
650
                    }
651
                }
652
            }
653
        }
654
    }
655
656 45684 jjdelcerro
    private void loadFeatures() {
657
        InputStreamReader in = null;
658
        SimpleReader reader = null;
659
        try {
660 45929 jjdelcerro
            taskStatus.setTitle("CSV "+this.getName());
661 45817 jjdelcerro
            taskStatus.add();
662 45727 jjdelcerro
//            boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
663 45684 jjdelcerro
664
            // Initialize the feature types
665
            EditableFeatureType edftype = getStoreServices().createFeatureType(this.getName());
666 45929 jjdelcerro
            CSVUtils.loadFeatureType(getCSVParameters(), edftype, true, taskStatus);
667 41617 jjdelcerro
            FeatureType ftype = edftype.getNotEditableCopy();
668 45359 omartinez
            this.setFeatureType(ftype);
669 41059 jjdelcerro
670 45685 jjdelcerro
            in = CSVUtils.openFile(
671 45684 jjdelcerro
                    this.getCSVParameters().getFile(),
672
                    CSVStoreParameters.getCharset(this.getCSVParameters())
673
            );
674 45685 jjdelcerro
            reader = CSVUtils.getSimpleReader(getCSVParameters(), in);
675 45684 jjdelcerro
            if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
676
                reader.getHeader(); // Skip and ignore the header of file
677
            }
678 45727 jjdelcerro
            this.rowToFeatureTranslator = new RowToFeatureTranslator(
679
                    CSVStoreParameters.getIgnoreErrors(getCSVParameters())
680
            );
681
            this.rowToFeatureTranslator.initialize(ftype);
682 42775 jjdelcerro
            if (ftype.getDefaultGeometryAttributeName() != null) {
683 41617 jjdelcerro
                this.need_calculate_envelope = true;
684
            }
685 45929 jjdelcerro
            I18nManager i18n = ToolsLocator.getI18nManager();
686
            taskStatus.message(i18n.getTranslation("_Loading"));
687 41006 jjdelcerro
688 45836 fdiaz
            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 41062 jjdelcerro
696 45727 jjdelcerro
                List<String> row = reader.read();
697 41062 jjdelcerro
698 45727 jjdelcerro
                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 45929 jjdelcerro
                    taskStatus.incrementCurrentValue();
705
                    if( taskStatus.isCancellationRequested() ) {
706
                        taskStatus.cancel();
707
                        break;
708
                    }
709 45727 jjdelcerro
                    FeatureProvider feature = this.createFeatureProvider(ftype);
710 45929 jjdelcerro
                    this.rowToFeatureTranslator.translate(reader.getLine(), row, feature);
711 45836 fdiaz
712 45727 jjdelcerro
                    this.addFeatureProvider(feature);
713
                    if (limit > 0) {
714
                        if (limit < this.data.size()) {
715
                            break;
716 44749 jjdelcerro
                        }
717 41617 jjdelcerro
                    }
718 45727 jjdelcerro
                    row = reader.read();
719 41617 jjdelcerro
                }
720 45727 jjdelcerro
                for (int i = 0; i < ftype.size(); i++) {
721 45836 fdiaz
                    if (this.rowToFeatureTranslator.getColumnSize(i) > 0) {
722 45727 jjdelcerro
//                    if (sizes[i] > 0) {
723
                        EditableFeatureAttributeDescriptor efad = ((EditableFeatureAttributeDescriptor) edftype.getAttributeDescriptor(i));
724
//                        efad.setSize(sizes[i]);
725
                        efad.setSize(this.rowToFeatureTranslator.getColumnSize(i));
726 42775 jjdelcerro
                    }
727
                }
728 45727 jjdelcerro
                // Volvemos a asignar al store el featuretype, ya que puede
729
                // haber cambiado.
730
                ftype = edftype.getNotEditableCopy();
731
                this.setFeatureType(ftype);
732 41617 jjdelcerro
            }
733 45929 jjdelcerro
            if( taskStatus.isRunning() ) {
734
                taskStatus.terminate();
735
            }
736 44963 jjdelcerro
        } catch (Throwable ex) {
737 45817 jjdelcerro
            taskStatus.abort();
738 41643 jjdelcerro
            int lineno = 0;
739 42775 jjdelcerro
            if (reader != null) {
740 41643 jjdelcerro
                lineno = reader.getLine();
741
            }
742 42775 jjdelcerro
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
743 41643 jjdelcerro
744 41617 jjdelcerro
        } finally {
745 42775 jjdelcerro
            if (reader != null) {
746 41617 jjdelcerro
                try {
747
                    reader.close();
748
                } catch (Exception ex) {
749
                    // Do nothing
750
                }
751 45684 jjdelcerro
//                reader = null;
752 41617 jjdelcerro
            }
753 42775 jjdelcerro
            if (in != null) {
754 41617 jjdelcerro
                try {
755
                    in.close();
756
                } catch (Exception ex) {
757
                    // Do nothing
758
                }
759 45684 jjdelcerro
//                in = null;
760 41617 jjdelcerro
            }
761
        }
762
    }
763 41062 jjdelcerro
764 45359 omartinez
    @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 45836 fdiaz
        if (StringUtils.isNotBlank(param_types_def)
770
                || pointDimensionNames != null
771
                || !StringUtils.isBlank(geometry_column)) {
772 45359 omartinez
            this.setFeatureType(featureType);
773
        }
774
    }
775 45836 fdiaz
776 45359 omartinez
    private void setFeatureType(FeatureType ftype) {
777
        List<FeatureType> ftypes = new ArrayList<>();
778
        ftypes.add(ftype);
779
        this.featureType = ftype;
780 45684 jjdelcerro
        this.getStoreServices().setFeatureTypes(ftypes, ftype);
781 45359 omartinez
    }
782 42775 jjdelcerro
783 45727 jjdelcerro
    @Override
784
    public FeatureSetProvider createSet(FeatureQuery query, FeatureType featureType)
785
            throws DataException {
786 45836 fdiaz
        if (this.virtualrows == null) {
787 45727 jjdelcerro
            return super.createSet(query, featureType);
788
        }
789
        return new CSVSetProvider(this, query, featureType);
790 45836 fdiaz
    }
791 45727 jjdelcerro
792
    public List<String> getRowByIndex(long index) {
793 45836 fdiaz
        if (this.virtualrows == null) {
794 45727 jjdelcerro
            return null;
795
        }
796
        return this.virtualrows.get64(index);
797
    }
798 45836 fdiaz
799 45727 jjdelcerro
    public RowToFeatureTranslator getRowToFeatureTranslator() {
800 45836 fdiaz
        if (this.rowToFeatureTranslator == null) {
801 45727 jjdelcerro
            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 45836 fdiaz
        if (this.virtualrows == null) {
811
            return super.getFeatureCount();
812 45727 jjdelcerro
        }
813
        return this.virtualrows.size64();
814
    }
815 45836 fdiaz
816 45929 jjdelcerro
    @Override
817 45836 fdiaz
    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 45727 jjdelcerro
850
851 45836 fdiaz
852 40846 jjdelcerro
}