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 / simplereader / SimpleReaderStoreProvider.java @ 47652

History | View | Annotate | Download (33.6 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 47634 fdiaz
package org.gvsig.fmap.dal.store.simplereader;
24 40846 jjdelcerro
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 47634 fdiaz
import java.io.Reader;
30 43425 jjdelcerro
import java.net.URI;
31 41062 jjdelcerro
import java.net.URL;
32 47199 jjdelcerro
import java.nio.charset.StandardCharsets;
33 40846 jjdelcerro
import java.util.ArrayList;
34
import java.util.HashMap;
35 41006 jjdelcerro
import java.util.Iterator;
36 40846 jjdelcerro
import java.util.List;
37 47199 jjdelcerro
import java.util.Objects;
38 45836 fdiaz
import org.apache.commons.io.FileUtils;
39 41006 jjdelcerro
import org.apache.commons.io.FilenameUtils;
40 45836 fdiaz
import org.apache.commons.io.IOUtils;
41 40846 jjdelcerro
import org.cresques.cts.IProjection;
42
import org.gvsig.fmap.dal.DALLocator;
43
import org.gvsig.fmap.dal.DataManager;
44
import org.gvsig.fmap.dal.DataServerExplorer;
45
import org.gvsig.fmap.dal.DataStore;
46
import org.gvsig.fmap.dal.DataStoreNotification;
47
import org.gvsig.fmap.dal.DataTypes;
48 46608 fdiaz
import org.gvsig.fmap.dal.exception.CloseException;
49 40846 jjdelcerro
import org.gvsig.fmap.dal.exception.DataException;
50
import org.gvsig.fmap.dal.exception.InitializeException;
51
import org.gvsig.fmap.dal.exception.OpenException;
52
import org.gvsig.fmap.dal.exception.ReadException;
53 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
54 40846 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureType;
55 41059 jjdelcerro
import org.gvsig.fmap.dal.feature.Feature;
56 41006 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
57 45727 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureQuery;
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
import org.gvsig.fmap.dal.resource.file.FileResource;
67
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
68
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
69
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
70
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
71
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
72 47638 jjdelcerro
import org.gvsig.fmap.dal.store.simplereader.simplereaders.AbstractSimpleReader;
73
import org.gvsig.fmap.dal.store.simplereader.simplereaders.SimpleReader;
74 40846 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
75
import org.gvsig.fmap.geom.GeometryLocator;
76
import org.gvsig.fmap.geom.GeometryManager;
77 47199 jjdelcerro
import org.gvsig.fmap.geom.SpatialIndex;
78
import org.gvsig.fmap.geom.SpatialIndexFactory;
79 40846 jjdelcerro
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 47636 fdiaz
import org.gvsig.tools.dataTypes.CoercionContext;
84 41006 jjdelcerro
import org.gvsig.tools.dispose.DisposableIterator;
85 47636 fdiaz
import org.gvsig.tools.dispose.DisposeUtils;
86
import org.gvsig.tools.dynobject.DynObject;
87 40846 jjdelcerro
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
88 41006 jjdelcerro
import org.gvsig.tools.evaluator.AbstractEvaluator;
89
import org.gvsig.tools.evaluator.EvaluatorData;
90
import org.gvsig.tools.evaluator.EvaluatorException;
91 41059 jjdelcerro
import org.gvsig.tools.exception.BaseException;
92 40846 jjdelcerro
import org.gvsig.tools.exception.NotYetImplemented;
93 47636 fdiaz
import org.gvsig.tools.i18n.I18nManager;
94 40846 jjdelcerro
import org.gvsig.tools.persistence.PersistentState;
95
import org.gvsig.tools.persistence.exception.PersistenceException;
96
import org.gvsig.tools.task.SimpleTaskStatus;
97
import org.gvsig.tools.task.TaskStatusManager;
98 47636 fdiaz
import org.gvsig.tools.util.GetItemWithSize64;
99 41059 jjdelcerro
import org.gvsig.tools.visitor.VisitCanceledException;
100
import org.gvsig.tools.visitor.Visitor;
101 40846 jjdelcerro
import org.slf4j.Logger;
102
import org.slf4j.LoggerFactory;
103
104 44309 omartinez
@SuppressWarnings("UseSpecificCatch")
105 47636 fdiaz
public abstract class SimpleReaderStoreProvider extends AbstractMemoryStoreProvider implements
106 41617 jjdelcerro
        ResourceConsumer {
107
108 47636 fdiaz
    protected static final Logger LOGGER = LoggerFactory.getLogger(SimpleReaderStoreProvider.class);
109 40846 jjdelcerro
110 47638 jjdelcerro
//    public static final String NAME = DataStore.CSV_PROVIDER_NAME;
111
//    public static final String DESCRIPTION = "CSV file";
112
//
113
//    public static final String METADATA_DEFINITION_NAME = NAME;
114 40846 jjdelcerro
115 47636 fdiaz
    protected final ResourceProvider resource;
116 40846 jjdelcerro
117 47636 fdiaz
    protected long counterNewsOIDs = 0;
118
    protected Envelope envelope;
119
    protected boolean need_calculate_envelope = false;
120
    protected final SimpleTaskStatus taskStatus;
121
    protected FeatureType featureType;
122
    protected GetItemWithSize64<List<String>> virtualrows;
123
    protected RowToFeatureTranslator rowToFeatureTranslator;
124
    protected SpatialIndex spatialIndex;
125 47199 jjdelcerro
126 45721 jjdelcerro
    @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
127 47634 fdiaz
    public SimpleReaderStoreProvider(
128 47636 fdiaz
            SimpleReaderStoreParameters parameters,
129
            DataStoreProviderServices storeServices,
130
            DynObject metadata
131 47199 jjdelcerro
        ) throws InitializeException {
132 40846 jjdelcerro
        super(
133 41617 jjdelcerro
                parameters,
134
                storeServices,
135 47636 fdiaz
                metadata
136 40846 jjdelcerro
        );
137
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
138
        this.taskStatus = manager.createDefaultSimpleTaskStatus("CSV");
139 45836 fdiaz
        this.taskStatus.setAutoremove(true);
140 40846 jjdelcerro
141
        counterNewsOIDs = 0;
142
143 47636 fdiaz
        File file = getSimpleReaderParameters().getFile();
144 40846 jjdelcerro
        resource = this.createResource(
145 41617 jjdelcerro
                FileResource.NAME,
146
                new Object[]{file.getAbsolutePath()}
147 40846 jjdelcerro
        );
148
149
        resource.addConsumer(this);
150 44309 omartinez
151 41006 jjdelcerro
        initializeFeatureTypes();
152 40846 jjdelcerro
    }
153
154 47636 fdiaz
    private SimpleReaderStoreParameters getSimpleReaderParameters() {
155
        return (SimpleReaderStoreParameters) this.getParameters();
156 40846 jjdelcerro
    }
157
158 44309 omartinez
    @Override
159 47638 jjdelcerro
    public abstract String getProviderName();
160 40846 jjdelcerro
161 44309 omartinez
    @Override
162 40846 jjdelcerro
    public boolean allowWrite() {
163 47636 fdiaz
        return false;
164 40846 jjdelcerro
    }
165
166 47636 fdiaz
    protected String getFullFileName() {
167 41617 jjdelcerro
        // Usar solo para mostrar mensajes en el logger.
168 44309 omartinez
        String s;
169 41617 jjdelcerro
        try {
170 47636 fdiaz
            s = getSimpleReaderParameters().getFile().getAbsolutePath();
171 41617 jjdelcerro
        } 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 47636 fdiaz
            params.setRoot(this.getSimpleReaderParameters().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 47636 fdiaz
        throw new UnsupportedOperationException();
215 40846 jjdelcerro
    }
216
217 44309 omartinez
    @Override
218 40846 jjdelcerro
    public boolean closeResourceRequested(ResourceProvider resource) {
219
        return true;
220
    }
221
222 44309 omartinez
    @Override
223 40846 jjdelcerro
    public int getOIDType() {
224
        return DataTypes.LONG;
225
    }
226
227 44309 omartinez
    @Override
228 40846 jjdelcerro
    public boolean supportsAppendMode() {
229 47636 fdiaz
        return false;
230 40846 jjdelcerro
    }
231
232 44309 omartinez
    @Override
233 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
234 44309 omartinez
    public void append(final FeatureProvider featureProvider) {
235 47636 fdiaz
        throw new UnsupportedOperationException();
236 40846 jjdelcerro
    }
237
238 44309 omartinez
    @Override
239 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
240 44309 omartinez
    public void beginAppend() throws DataException {
241 47636 fdiaz
        throw new UnsupportedOperationException();
242 40846 jjdelcerro
    }
243
244 44309 omartinez
    @Override
245 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
246 40846 jjdelcerro
    public void endAppend() {
247 47636 fdiaz
        throw new UnsupportedOperationException();
248 40846 jjdelcerro
    }
249
250
    public void saveToState(PersistentState state) throws PersistenceException {
251
        throw new NotYetImplemented();
252
    }
253
254
    public void loadFromState(PersistentState state) throws PersistenceException {
255
        throw new NotYetImplemented();
256
    }
257
258 44309 omartinez
    @Override
259 40846 jjdelcerro
    public Object createNewOID() {
260 44309 omartinez
        return counterNewsOIDs++;
261 40846 jjdelcerro
    }
262
263
    protected void initializeFeatureTypes() throws InitializeException {
264
        try {
265
            this.open();
266
        } catch (OpenException e) {
267
            throw new InitializeException(this.getProviderName(), e);
268
        }
269
    }
270
271 44309 omartinez
    @Override
272 45684 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
273 40846 jjdelcerro
    public Envelope getEnvelope() throws DataException {
274
        this.open();
275 42775 jjdelcerro
        if (this.envelope != null) {
276 41617 jjdelcerro
            return this.envelope;
277 41059 jjdelcerro
        }
278 47199 jjdelcerro
        this.envelope = bboxFileLoad();
279
        if (this.envelope != null) {
280
            return this.envelope;
281
        }
282 42775 jjdelcerro
        if (!this.need_calculate_envelope) {
283 41617 jjdelcerro
            return null;
284 41059 jjdelcerro
        }
285
        try {
286 45929 jjdelcerro
            I18nManager i18n = ToolsLocator.getI18nManager();
287 45836 fdiaz
            this.taskStatus.add();
288 45929 jjdelcerro
            this.taskStatus.message(i18n.getTranslation("_Calculating_envelope"));
289 45836 fdiaz
            FeatureStore fs = this.getFeatureStore();
290
            FeatureType ft = fs.getDefaultFeatureType();
291
            FeatureAttributeDescriptor fad = ft.getAttributeDescriptor(ft.getDefaultGeometryAttributeIndex());
292
            this.taskStatus.setRangeOfValues(0, fs.getFeatureCount());
293 41059 jjdelcerro
            this.envelope = GeometryLocator.getGeometryManager().createEnvelope(fad.getGeomType().getSubType());
294 41617 jjdelcerro
            fs.accept(new Visitor() {
295 44309 omartinez
                @Override
296 41617 jjdelcerro
                public void visit(Object obj) throws VisitCanceledException, BaseException {
297 45836 fdiaz
                    taskStatus.incrementCurrentValue();
298
                    if(taskStatus.isCancellationRequested()){
299
                        taskStatus.cancel();
300
                        throw new VisitCanceledException();
301
                    }
302 41617 jjdelcerro
                    Feature f = (Feature) obj;
303
                    Geometry geom = f.getDefaultGeometry();
304 42775 jjdelcerro
                    if (geom != null) {
305 47199 jjdelcerro
                        try {
306
                            Envelope env = geom.getEnvelope();
307
                            envelope.add(env);
308
                        } catch(Exception ex) {
309
                            LOGGER.warn("Can't calculate envelop of geometry in feature '"+Objects.toString(f.getReference())+"'.",ex);
310
                        }
311 41617 jjdelcerro
                    }
312
                }
313
            });
314 47199 jjdelcerro
            bboxFileSave(envelope);
315 45836 fdiaz
            taskStatus.terminate();
316
        } catch (VisitCanceledException e) {
317
            return null;
318 41617 jjdelcerro
        } catch (BaseException e) {
319 45836 fdiaz
            taskStatus.abort();
320 44408 jjdelcerro
            LOGGER.warn("Can't calculate the envelope of CSV file '" + this.getFullName() + "'.", e);
321 45836 fdiaz
            return null;
322 41617 jjdelcerro
        }
323
324 41059 jjdelcerro
        this.need_calculate_envelope = false;
325 40846 jjdelcerro
        return this.envelope;
326
    }
327
328 44309 omartinez
    @Override
329 40846 jjdelcerro
    public Object getDynValue(String name) throws DynFieldNotFoundException {
330 42775 jjdelcerro
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
331 40846 jjdelcerro
            try {
332
                return this.getEnvelope();
333
            } catch (DataException e) {
334
                return null;
335
            }
336
        } else {
337 42775 jjdelcerro
            if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
338 47636 fdiaz
                IProjection pro = SimpleReaderStoreParameters.getCRS(this.getSimpleReaderParameters());
339 42775 jjdelcerro
                if (pro != null) {
340 40846 jjdelcerro
                    return pro;
341
                }
342
            }
343
        }
344
        return super.getDynValue(name);
345
    }
346
347 44309 omartinez
    @Override
348 40846 jjdelcerro
    public void resourceChanged(ResourceProvider resource) {
349
        this.getStoreServices().notifyChange(
350 41617 jjdelcerro
                DataStoreNotification.RESOURCE_CHANGED,
351
                resource);
352 40846 jjdelcerro
    }
353
354 44309 omartinez
    @Override
355 40846 jjdelcerro
    public Object getSourceId() {
356 47636 fdiaz
        return this.getSimpleReaderParameters().getFile();
357 40846 jjdelcerro
    }
358
359 44309 omartinez
    @Override
360 40846 jjdelcerro
    public String getName() {
361 47636 fdiaz
        String name = this.getSimpleReaderParameters().getFile().getName();
362 41006 jjdelcerro
        return FilenameUtils.getBaseName(name);
363 40846 jjdelcerro
    }
364
365 44309 omartinez
    @Override
366 40846 jjdelcerro
    public String getFullName() {
367 47636 fdiaz
        return this.getSimpleReaderParameters().getFile().getAbsolutePath();
368 40846 jjdelcerro
    }
369
370 44309 omartinez
    @Override
371 40846 jjdelcerro
    public ResourceProvider getResource() {
372
        return resource;
373
    }
374
375
    private boolean isEmpty(String s) {
376 42775 jjdelcerro
        if (s == null) {
377 41617 jjdelcerro
            return true;
378
        }
379
        return s.trim().length() == 0;
380 40846 jjdelcerro
    }
381 40878 jjdelcerro
382 47636 fdiaz
    private void init(SimpleReaderStoreParameters parameters, DataStoreProviderServices storeServices) {
383 44309 omartinez
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
384
    }
385 41617 jjdelcerro
386 41006 jjdelcerro
    static class ToPointEvaluaror extends AbstractEvaluator {
387 40846 jjdelcerro
388 41335 jjdelcerro
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
389 40846 jjdelcerro
390 41335 jjdelcerro
        private GeometryManager geommgr = null;
391
        private String xname = null;
392
        private String yname = null;
393
        private String zname = null;
394 45684 jjdelcerro
        private final Coercion toDouble;
395 41335 jjdelcerro
        private int errorcount = 0;
396
397
        ToPointEvaluaror(String[] pointDimensionNames) {
398
            this.xname = pointDimensionNames[0];
399
            this.yname = pointDimensionNames[1];
400 42775 jjdelcerro
            if (pointDimensionNames.length > 2) {
401 41335 jjdelcerro
                this.zname = pointDimensionNames[2];
402
            }
403
            this.geommgr = GeometryLocator.getGeometryManager();
404
            this.toDouble = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.DOUBLE);
405
        }
406
407 44309 omartinez
        @Override
408 41335 jjdelcerro
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
409
            try {
410 45684 jjdelcerro
                double x = ((Double) toDouble.coerce(data.getDataValue(xname)));
411
                double y = ((Double) toDouble.coerce(data.getDataValue(yname)));
412 41335 jjdelcerro
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
413 42775 jjdelcerro
                if (zname != null) {
414 45684 jjdelcerro
                    double z = ((Double) toDouble.coerce(data.getDataValue(zname)));
415 41335 jjdelcerro
                    point.setCoordinateAt(2, z);
416
                }
417
                return point;
418
            } catch (Exception ex) {
419 42775 jjdelcerro
                if (++errorcount < 5) {
420 41335 jjdelcerro
                    logger.warn("[" + errorcount + "] Can't create point in CSV provider. XNAME='"
421
                            + xname + "', YNAME='" + yname + "', ZNAME='" + zname + "', data=" + data.toString());
422
                }
423
                return null;
424
            }
425
        }
426
427 44309 omartinez
        @Override
428 41335 jjdelcerro
        public String getName() {
429
            return "ToPointEvaluaror";
430
        }
431
432 40846 jjdelcerro
    }
433 41335 jjdelcerro
434 45727 jjdelcerro
    public static class RowToFeatureTranslator {
435 45836 fdiaz
436 45727 jjdelcerro
        private Coercion coercion[];
437
        private CoercionContext coercionContext[];
438
        private int sizes[];
439 45990 jjdelcerro
        private String[] names;
440 45727 jjdelcerro
        private final boolean ignore_errors;
441
        private long count_errors;
442 45836 fdiaz
        private FeatureType csvFeatureType;
443 45727 jjdelcerro
444
        public RowToFeatureTranslator(boolean ignore_errors) {
445
            this.ignore_errors = ignore_errors;
446
            this.count_errors = 0;
447
        }
448
449
        public int getColumnSize(int column) {
450
            return this.sizes[column];
451
        }
452 45836 fdiaz
453 45727 jjdelcerro
        public void initialize(FeatureType ftype) {
454 45836 fdiaz
            this.csvFeatureType = ftype;
455
            int columns = this.csvFeatureType.size();
456 45990 jjdelcerro
            this.names = new String[columns];
457 45727 jjdelcerro
            this.coercion = new Coercion[columns];
458
            this.coercionContext = new CoercionContext[columns];
459
            this.sizes = new int[columns];
460 45990 jjdelcerro
            int index = 0;
461 45836 fdiaz
            for (int i = 0; i < this.csvFeatureType.size(); i++) {
462
                FeatureAttributeDescriptor ad = this.csvFeatureType.getAttributeDescriptor(i);
463 45990 jjdelcerro
                names[i] = null;
464
                if( ad.isComputed() ) {
465
                    continue;
466
                }
467
                names[index] = ad.getName();
468
                coercion[index] = ad.getCoercion();
469
                coercionContext[index] = ad.getCoercionContext();
470
                sizes[index] = ad.getSize();
471
                index++;
472 45727 jjdelcerro
            }
473
        }
474 45836 fdiaz
475 45727 jjdelcerro
        public void translate(long rowindex, List<String> row, FeatureProvider feature) throws Exception {
476
477 45836 fdiaz
            feature.setOID(rowindex);
478 45990 jjdelcerro
            for (int i = 0; i < names.length; i++) {
479
                String name = names[i];
480
                if( name == null ) {
481
                    break;
482
                }
483
                Object rawvalue = row.get(i);
484 45727 jjdelcerro
                try {
485
                    Object value = null;
486 45990 jjdelcerro
                    if (coercion[i] != null) {
487
                        value = coercion[i].coerce(rawvalue, coercionContext[i]);
488 45727 jjdelcerro
                    }
489 46080 jjdelcerro
                    int findex = feature.getType().getIndex(name);
490
                    if( findex>=0 ) {
491
                        // Ojo que puede que se este filtrando el featuretype y no
492
                        // tenga todos los atributos, por ejemplo al pintar la vista.
493
                        feature.set(findex, value);
494
                    }
495 45990 jjdelcerro
                    if (sizes[i] >= 0
496 45727 jjdelcerro
                            && (value instanceof String || value instanceof URL
497
                            || value instanceof URI || value instanceof File)) {
498
                        int x = value.toString().length();
499 45990 jjdelcerro
                        if (sizes[i] < x) {
500
                            sizes[i] = x;
501 45727 jjdelcerro
                        }
502
                    }
503
                } catch (Exception ex) {
504
                    if (!ignore_errors) {
505
                        throw ex;
506
                    }
507
                    if (count_errors++ < 10) {
508 45990 jjdelcerro
                        LOGGER.warn("Can't load value of attribute " + name +"/" +i+" in row " + rowindex + ".", ex);
509 45727 jjdelcerro
                    }
510
                    if (count_errors == 10) {
511
                        LOGGER.info("Too many errors, suppress messages.");
512
                    }
513
                }
514
            }
515
        }
516
    }
517
518 47636 fdiaz
    protected abstract SimpleReaderFeatureTypeLoader getFeatureTypeLoader();
519
520
    protected void loadFeatures() {
521 45684 jjdelcerro
        InputStreamReader in = null;
522
        SimpleReader reader = null;
523
        try {
524 45929 jjdelcerro
            taskStatus.setTitle("CSV "+this.getName());
525 45817 jjdelcerro
            taskStatus.add();
526 45727 jjdelcerro
//            boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
527 45684 jjdelcerro
528
            // Initialize the feature types
529
            EditableFeatureType edftype = getStoreServices().createFeatureType(this.getName());
530 47636 fdiaz
            SimpleReaderFeatureTypeLoader featureTypeLoader = getFeatureTypeLoader();
531 47652 fdiaz
            featureTypeLoader.loadFeatureType(edftype, taskStatus);
532 41617 jjdelcerro
            FeatureType ftype = edftype.getNotEditableCopy();
533 45359 omartinez
            this.setFeatureType(ftype);
534 41059 jjdelcerro
535 47636 fdiaz
            in = SimpleReaderUtils.openFile(
536
                    this.getSimpleReaderParameters().getFile(),
537
                    SimpleReaderStoreParameters.getCharset(this.getSimpleReaderParameters())
538 45684 jjdelcerro
            );
539 47636 fdiaz
            reader = getSimpleReader(getSimpleReaderParameters(), in);
540
            if (featureTypeLoader.isFirstLineHeader()) {
541 45684 jjdelcerro
                reader.getHeader(); // Skip and ignore the header of file
542
            }
543 45727 jjdelcerro
            this.rowToFeatureTranslator = new RowToFeatureTranslator(
544 47636 fdiaz
                    SimpleReaderStoreParameters.getIgnoreErrors(getSimpleReaderParameters())
545 45727 jjdelcerro
            );
546
            this.rowToFeatureTranslator.initialize(ftype);
547 42775 jjdelcerro
            if (ftype.getDefaultGeometryAttributeName() != null) {
548 41617 jjdelcerro
                this.need_calculate_envelope = true;
549
            }
550 45929 jjdelcerro
            I18nManager i18n = ToolsLocator.getI18nManager();
551
            taskStatus.message(i18n.getTranslation("_Loading"));
552 41006 jjdelcerro
553 45836 fdiaz
            if(this.virtualrows != null && this.virtualrows instanceof Closeable){
554
                IOUtils.closeQuietly((Closeable) this.virtualrows);
555
                this.virtualrows = null;
556
            }
557
558
            this.virtualrows = ((AbstractSimpleReader) reader).getVirtualRows(this.taskStatus);
559
            if (this.virtualrows == null) {
560 41062 jjdelcerro
561 47652 fdiaz
                taskStatus.message(i18n.getTranslation("_Loading"));
562
                taskStatus.setIndeterminate();
563
564 45727 jjdelcerro
                List<String> row = reader.read();
565 41062 jjdelcerro
566 47636 fdiaz
                int skipLines = SimpleReaderStoreParameters.getSkipLines(getSimpleReaderParameters());
567 45727 jjdelcerro
                if (skipLines > 0) {
568
                    row = reader.skip(skipLines);
569
                }
570 47636 fdiaz
                int limit = SimpleReaderStoreParameters.getLimit(getSimpleReaderParameters());
571 45727 jjdelcerro
                while (row != null) {
572 45929 jjdelcerro
                    taskStatus.incrementCurrentValue();
573
                    if( taskStatus.isCancellationRequested() ) {
574
                        taskStatus.cancel();
575
                        break;
576
                    }
577 45727 jjdelcerro
                    FeatureProvider feature = this.createFeatureProvider(ftype);
578 45929 jjdelcerro
                    this.rowToFeatureTranslator.translate(reader.getLine(), row, feature);
579 45836 fdiaz
580 45727 jjdelcerro
                    this.addFeatureProvider(feature);
581
                    if (limit > 0) {
582
                        if (limit < this.data.size()) {
583
                            break;
584 44749 jjdelcerro
                        }
585 41617 jjdelcerro
                    }
586 45727 jjdelcerro
                    row = reader.read();
587 41617 jjdelcerro
                }
588 45727 jjdelcerro
                for (int i = 0; i < ftype.size(); i++) {
589 45836 fdiaz
                    if (this.rowToFeatureTranslator.getColumnSize(i) > 0) {
590 45727 jjdelcerro
//                    if (sizes[i] > 0) {
591
                        EditableFeatureAttributeDescriptor efad = ((EditableFeatureAttributeDescriptor) edftype.getAttributeDescriptor(i));
592
//                        efad.setSize(sizes[i]);
593
                        efad.setSize(this.rowToFeatureTranslator.getColumnSize(i));
594 42775 jjdelcerro
                    }
595
                }
596 45727 jjdelcerro
                // Volvemos a asignar al store el featuretype, ya que puede
597
                // haber cambiado.
598
                ftype = edftype.getNotEditableCopy();
599
                this.setFeatureType(ftype);
600 47199 jjdelcerro
            } else {
601
                this.loadOrCreateSpatialIndex();
602 41617 jjdelcerro
            }
603 45929 jjdelcerro
            if( taskStatus.isRunning() ) {
604
                taskStatus.terminate();
605
            }
606 44963 jjdelcerro
        } catch (Throwable ex) {
607 45817 jjdelcerro
            taskStatus.abort();
608 41643 jjdelcerro
            int lineno = 0;
609 42775 jjdelcerro
            if (reader != null) {
610 41643 jjdelcerro
                lineno = reader.getLine();
611
            }
612 42775 jjdelcerro
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
613 41643 jjdelcerro
614 41617 jjdelcerro
        } finally {
615 42775 jjdelcerro
            if (reader != null) {
616 41617 jjdelcerro
                try {
617
                    reader.close();
618
                } catch (Exception ex) {
619
                    // Do nothing
620
                }
621 45684 jjdelcerro
//                reader = null;
622 41617 jjdelcerro
            }
623 42775 jjdelcerro
            if (in != null) {
624 41617 jjdelcerro
                try {
625
                    in.close();
626
                } catch (Exception ex) {
627
                    // Do nothing
628
                }
629 45684 jjdelcerro
//                in = null;
630 41617 jjdelcerro
            }
631 47199 jjdelcerro
            taskStatus.remove();
632 41617 jjdelcerro
        }
633
    }
634 41062 jjdelcerro
635 45359 omartinez
    @Override
636
    public void fixFeatureTypeFromParameters() {
637 46608 fdiaz
        if(mustFixFeatureType() && featureType != null){
638
            this.setFeatureType(featureType);
639
        }
640
    }
641
642 47636 fdiaz
    protected boolean mustFixFeatureType() {
643 46608 fdiaz
        return false;
644 45359 omartinez
    }
645 45836 fdiaz
646 45359 omartinez
    private void setFeatureType(FeatureType ftype) {
647 46608 fdiaz
        try {
648
            List<FeatureType> ftypes = new ArrayList<>();
649
            ftypes.add(ftype);
650
            this.featureType = ftype;
651
            if(this.getStoreServices().getDefaultFeatureType() == null){
652
                this.getStoreServices().setFeatureTypes(ftypes, ftype);
653
                return;
654
            }
655
            if(mustFixFeatureType()){
656
                this.getStoreServices().setFeatureTypes(ftypes, ftype);
657
            }
658
        } catch (DataException ex) {
659
            LOGGER.warn("Cant set feature type", ex);
660
        }
661 45359 omartinez
    }
662 42775 jjdelcerro
663 45727 jjdelcerro
    @Override
664 47557 fdiaz
    public FeatureSetProvider createSet(FeatureQuery query, FeatureType providerFeatureType, FeatureType featureType)
665
            throws DataException {
666
        this.open();
667
        if (this.virtualrows == null) {
668
            return super.createSet(query, providerFeatureType, featureType);
669
        }
670 47634 fdiaz
        return new SimpleReaderSetProvider(this, query, providerFeatureType, featureType);
671 47557 fdiaz
    }
672
673
    @Override
674 45727 jjdelcerro
    public FeatureSetProvider createSet(FeatureQuery query, FeatureType featureType)
675
            throws DataException {
676 47199 jjdelcerro
        this.open();
677 45836 fdiaz
        if (this.virtualrows == null) {
678 45727 jjdelcerro
            return super.createSet(query, featureType);
679
        }
680 47634 fdiaz
        return new SimpleReaderSetProvider(this, query, featureType, featureType);
681 45836 fdiaz
    }
682 45727 jjdelcerro
683
    public List<String> getRowByIndex(long index) {
684 47199 jjdelcerro
        try {
685
            this.open();
686
        } catch(Exception ex) {
687
            throw new RuntimeException("Can't get row by index", ex);
688
        }
689 45836 fdiaz
        if (this.virtualrows == null) {
690 45727 jjdelcerro
            return null;
691
        }
692 46136 jjdelcerro
        List<String> line = this.virtualrows.get64(index);
693
        return line;
694 45727 jjdelcerro
    }
695 45836 fdiaz
696 45727 jjdelcerro
    public RowToFeatureTranslator getRowToFeatureTranslator() {
697 45836 fdiaz
        if (this.rowToFeatureTranslator == null) {
698 47636 fdiaz
            boolean ignore_errors = SimpleReaderStoreParameters.getIgnoreErrors(getSimpleReaderParameters());
699 45727 jjdelcerro
            this.rowToFeatureTranslator = new RowToFeatureTranslator(ignore_errors);
700
            this.rowToFeatureTranslator.initialize(featureType);
701
        }
702
        return this.rowToFeatureTranslator;
703
    }
704
705
    @Override
706
    public long getFeatureCount() throws DataException {
707 47199 jjdelcerro
        this.open();
708 45836 fdiaz
        if (this.virtualrows == null) {
709
            return super.getFeatureCount();
710 45727 jjdelcerro
        }
711
        return this.virtualrows.size64();
712
    }
713 45836 fdiaz
714 45929 jjdelcerro
    @Override
715 45836 fdiaz
    public long getDataSize() throws DataException {
716 47199 jjdelcerro
        this.open();
717 45836 fdiaz
        if (this.virtualrows == null) {
718
            return super.getDataSize();
719
        }
720
        return this.virtualrows.size64();
721
    }
722
723
    @Override
724
    protected FeatureProvider internalGetFeatureProviderByReference(
725
            FeatureReferenceProviderServices reference) throws DataException {
726 47199 jjdelcerro
        this.open();
727 45836 fdiaz
        if (this.virtualrows == null) {
728
            return super.internalGetFeatureProviderByReference(reference);
729
        }
730
        int oid = ((Long) reference.getOID()).intValue();
731
        RowToFeatureTranslator translator = getRowToFeatureTranslator();
732
        FeatureProvider feature = this.createFeatureProvider(this.featureType);
733
        try {
734
            translator.translate(oid, this.virtualrows.get64(oid), feature);
735
        } catch (Exception ex) {
736
            throw new CreateFeatureException(ex, this.getName());
737
        }
738
        return feature;
739
    }
740
741
    @Override
742
    protected void doDispose() throws BaseException {
743
        super.doDispose();
744
        if (this.virtualrows != null && this.virtualrows instanceof Closeable) {
745
            IOUtils.closeQuietly((Closeable) this.virtualrows);
746
            this.virtualrows = null;
747
        }
748
    }
749 45727 jjdelcerro
750 47199 jjdelcerro
    @Override
751 46608 fdiaz
     public void refresh() throws OpenException {
752
        try {
753
            this.close();
754
        } catch (CloseException e) {
755
            throw new OpenException(this.getProviderName(), e);
756
        }
757
        this.open();
758
    }
759
760
    @Override
761
    public void close() throws CloseException {
762
        super.close(); //To change body of generated methods, choose Tools | Templates.
763
        this.data = null;
764 46614 fdiaz
        if(this.virtualrows != null && this.virtualrows instanceof Closeable){
765
            IOUtils.closeQuietly((Closeable) this.virtualrows);
766
            this.virtualrows = null;
767 47199 jjdelcerro
            this.envelope = null;
768
            this.spatialIndex = null;
769 46614 fdiaz
        }
770
771 46608 fdiaz
    }
772
773 45727 jjdelcerro
774 47199 jjdelcerro
    private void loadOrCreateSpatialIndex() {
775
        FeatureSetProvider set = null;
776
        DisposableIterator<FeatureProvider> it = null;
777
        try {
778
            if( this.virtualrows == null ) {
779
                return;
780
            }
781
            FeatureAttributeDescriptor geomdesc = this.featureType.getDefaultGeometryAttribute();
782
            if( geomdesc == null ) {
783
                return;
784
            }
785
//            String indexTypeName = "MVRTree";
786
//            String extname = "mvtree";
787
            String indexTypeName = GeometryManager.SPATIALINDEX_DEFAULT_QUADTREE;
788
            String extname = "qtree";
789
790
            this.envelope = bboxFileLoad();
791
            File indexfile = this.getAuxFile(extname);
792
            boolean createIndex = !indexfile.exists();
793 45836 fdiaz
794 47199 jjdelcerro
            GeometryManager geomManager = GeometryLocator.getGeometryManager();
795
            SpatialIndexFactory indexfactory = geomManager.getSpatialIndexFactory(indexTypeName);
796
            DynObject params = indexfactory.createParameters();
797
            params.setDynValue("file", indexfile);
798
            SpatialIndex index = geomManager.createSpatialIndex(indexTypeName, params);
799
            if( createIndex ) {
800
                I18nManager i18n = ToolsLocator.getI18nManager();
801
                this.taskStatus.add();
802
                taskStatus.message(i18n.getTranslation("_Creating_spatial_index"));
803
                taskStatus.setRangeOfValues(0, this.virtualrows.size64());
804
                taskStatus.setCurValue(0);
805
                Envelope theEnvelope = geomManager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
806
                set = this.createSet(null, featureType);
807
                it = set.fastIterator();
808
                while( it.hasNext() ) {
809
                    taskStatus.incrementCurrentValue();
810
                    if( taskStatus.isCancellationRequested() ) {
811
                        taskStatus.cancel();
812
                        LOGGER.info("CSV spatial index creation canceled ("+getFullFileName()+")");
813
                        break;
814
                    }
815
                    FeatureProvider f = it.next();
816
                    if( f == null ) {
817
                        continue;
818
                    }
819
                    Object oid = null;
820
                    try {
821
                        oid = f.getOID();
822
                        Geometry geom = (Geometry) f.get(geomdesc.getName());
823 47652 fdiaz
                        if(geom!= null){
824
                            index.insert(geom, oid);
825
                            theEnvelope.add(geom);
826
                        }
827
                    } catch(Throwable ex) {
828 47199 jjdelcerro
                        LOGGER.debug("Can't insert feature '"+Objects.toString(oid)+"' in spatial index.",ex);
829
                    }
830
                }
831
                taskStatus.message(i18n.getTranslation("_Saving_spatial_index"));
832
                taskStatus.setIndeterminate();
833
                index.flush();
834
                bboxFileSave(theEnvelope);
835
                taskStatus.terminate();
836
                this.envelope = theEnvelope;
837
            }
838
            this.spatialIndex = index;
839
        } catch (Exception ex) {
840
            taskStatus.abort();
841
            LOGGER.warn("Can't create spatial index.",ex);
842
        } finally {
843
            DisposeUtils.disposeQuietly(it);
844
            DisposeUtils.disposeQuietly(set);
845
            taskStatus.remove();
846
        }
847
    }
848
849
    public File getAuxFile(String extension) {
850 47636 fdiaz
        File data_file = SimpleReaderStoreParameters.getFile(this.getSimpleReaderParameters());
851 47199 jjdelcerro
        if (data_file == null){
852
            return null;
853
        }
854
        File index_file = new File(FilenameUtils.removeExtension(data_file.getAbsolutePath()) + "." + extension);
855
        return index_file;
856
    }
857
858
    public SpatialIndex getSpatialIndex() {
859
        return spatialIndex;
860
    }
861
862 47636 fdiaz
    protected void bboxFileSave(Envelope envelope) {
863 47199 jjdelcerro
        File bboxfile = this.getAuxFile("bbox");
864
        bboxFileSave(bboxfile, envelope);
865
    }
866
867 47636 fdiaz
    protected void bboxFileSave(File bboxfile, Envelope envelope) {
868 47199 jjdelcerro
        if( envelope == null ) {
869
            bboxfile.delete();
870
            return;
871
        }
872
        try {
873
            FileUtils.write(
874
                    bboxfile,
875
                    envelope.getBox2D().convertToWKTQuietly(),
876
                    StandardCharsets.UTF_8
877
            );
878
        } catch(Exception ex) {
879
            LOGGER.warn("Can't write bbox file '"+Objects.toString(bboxfile)+"'.",ex);
880
        }
881
    }
882
883 47636 fdiaz
    protected Envelope bboxFileLoad() {
884 47199 jjdelcerro
        File bboxfile = this.getAuxFile("bbox");
885
        return bboxFileLoad(bboxfile);
886
    }
887
888 47636 fdiaz
    protected Envelope bboxFileLoad(File bboxfile) {
889 47199 jjdelcerro
        try {
890
            if( bboxfile.exists() ) {
891
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
892
                String wkt = FileUtils.readFileToString(bboxfile, StandardCharsets.UTF_8);
893
                Geometry geom = geomManager.createFrom(wkt);
894
                if( geom!=null ) {
895
                    return geom.getEnvelope();
896
                }
897
            }
898
        } catch(Exception ex) {
899
            LOGGER.warn("Can't load bbox file",ex);
900
        }
901
        return null;
902
    }
903
904 47636 fdiaz
    protected abstract SimpleReader getSimpleReader(SimpleReaderStoreParameters parameters, Reader in) throws IOException ;//{
905
//        return CSVUtils.getSimpleReader(getSimpleReaderParameters(), in);
906
//    }
907 47634 fdiaz
908 40846 jjdelcerro
}