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

History | View | Annotate | Download (14.7 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.dal.store.csv;
24

    
25
import java.io.File;
26
import java.io.IOException;
27
import java.io.Reader;
28
import java.util.ArrayList;
29
import java.util.Iterator;
30
import java.util.List;
31
import org.apache.commons.io.FileUtils;
32
import org.apache.commons.io.FilenameUtils;
33
import org.apache.commons.lang3.StringUtils;
34
import org.gvsig.fmap.dal.DataStore;
35
import org.gvsig.fmap.dal.DataTypes;
36
import org.gvsig.fmap.dal.FileHelper;
37
import org.gvsig.fmap.dal.exception.DataException;
38
import org.gvsig.fmap.dal.exception.InitializeException;
39
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
40
import org.gvsig.fmap.dal.feature.FeatureSet;
41
import org.gvsig.fmap.dal.feature.FeatureType;
42
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
43
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
44
import org.gvsig.fmap.dal.resource.ResourceAction;
45
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
46
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
47
import org.gvsig.fmap.dal.store.csv.simplereaders.CSVReaderSuperCSV;
48
import org.gvsig.fmap.dal.store.csv.simplereaders.FixedLenReader;
49
import org.gvsig.fmap.dal.store.simplereader.simplereaders.SimpleReader;
50
import org.gvsig.fmap.dal.store.simplereader.SimpleReaderFeatureTypeLoader;
51
import org.gvsig.fmap.dal.store.simplereader.SimpleReaderStoreParameters;
52
import org.gvsig.fmap.dal.store.simplereader.SimpleReaderStoreProvider;
53
import org.gvsig.tools.ToolsLocator;
54
import org.gvsig.tools.dispose.DisposableIterator;
55
import org.gvsig.tools.i18n.I18nManager;
56
import org.slf4j.Logger;
57
import org.slf4j.LoggerFactory;
58
import org.supercsv.prefs.CsvPreference;
59

    
60
@SuppressWarnings("UseSpecificCatch")
61
public class CSVStoreProvider extends SimpleReaderStoreProvider implements
62
        ResourceConsumer {
63

    
64
    private static final Logger LOGGER = LoggerFactory.getLogger(CSVStoreProvider.class);
65

    
66
    public static final String NAME = DataStore.CSV_PROVIDER_NAME;
67
    public static final String DESCRIPTION = "CSV file";
68

    
69
    public static final String METADATA_DEFINITION_NAME = NAME;
70

    
71
    protected final CSVFeatureWriter writer;
72

    
73
    @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
74
    public CSVStoreProvider(
75
            CSVStoreParameters parameters,
76
            DataStoreProviderServices storeServices
77
        ) throws InitializeException {
78
        super(
79
                parameters,
80
                storeServices,
81
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
82
        );
83
        this.writer = new CSVFeatureWriter();
84
    }
85

    
86
    private CSVStoreParameters getCSVParameters() {
87
        return (CSVStoreParameters) this.getParameters();
88
    }
89

    
90
    @Override
91
    public String getProviderName() {
92
        return NAME;
93
    }
94

    
95
    @Override
96
    public boolean allowWrite() {
97
        return true;
98
    }
99

    
100
    @Override
101
    @SuppressWarnings("Convert2Lambda")
102
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
103

    
104
        try {
105
            I18nManager i18n = ToolsLocator.getI18nManager();
106
            this.taskStatus.add();
107
            taskStatus.message(i18n.getTranslation("_Preparing_writing"));
108
            this.getResource().closeRequest();
109
            getResource().execute(new ResourceAction() {
110
                @Override
111
                public Object run() throws Exception {
112
                    FeatureSet features = null;
113
                    DisposableIterator it = null;
114
                    try {
115
                        File file = (File) resource.get();
116
                        features = getStoreServices().getFeatureStore().getFeatureSet();
117

    
118
                        taskStatus.message(i18n.getTranslation("_Writing_records"));
119
                        if (virtualrows == null) {
120
                            List<FeatureProvider> newdata = new ArrayList<>();
121
                            FeatureType ftype = getStoreServices().getDefaultFeatureType();
122
                            writer.initialize(getCSVParameters(), file, ftype, getCSVPreferences(), spatialIndexes);
123
                            writer.begin();
124
                            it = features.fastIterator();
125
                            taskStatus.setRangeOfValues(0, features.getSize());
126
                            taskStatus.setCurValue(0);
127
                            while (it.hasNext()) {
128
                                taskStatus.incrementCurrentValue();
129
                                FeatureProvider feature = getStoreServices().getFeatureProviderFromFeature(
130
                                        (org.gvsig.fmap.dal.feature.Feature) it.next());
131
                                writer.add(feature);
132
                                if (feature.getOID() == null) {
133
                                    LOGGER.warn("feature without OID");
134
                                    feature.setOID(createNewOID());
135
                                }
136
                                newdata.add(feature);
137
                            }
138
                            data = newdata;
139
                            if (writer.getEnvelopes() != null) {
140
                                envelopes = writer.getEnvelopes();
141
                            } else {
142
                                envelopes = null;
143
                            }
144
                            resource.notifyChanges();
145
                            writer.end();
146
                            bboxFileSave(envelopes);
147
                        } else {
148

    
149
                            CSVStoreParameters csvParams = getCSVParameters();
150
                            CSVStoreParameters tmpParams = (CSVStoreParameters) csvParams.getCopy();
151

    
152
                            String tmpBase = File.createTempFile("tmp_" + System.currentTimeMillis(), null).getAbsolutePath();
153
                            File tmpFile = new File(tmpBase + ".csv");
154
                            tmpParams.setFile(tmpFile);
155

    
156
                            FeatureType ftype = getStoreServices().getDefaultFeatureType();
157
                            writer.initialize(tmpParams, tmpFile, ftype, getCSVPreferences(),spatialIndexes);
158
                            writer.begin();
159
                            it = features.fastIterator();
160
                            taskStatus.setIndeterminate();
161
                            taskStatus.setCurValue(0);
162
                            while (it.hasNext()) {
163
                                taskStatus.incrementCurrentValue();
164
                                if( taskStatus.isCancellationRequested() ) {
165
                                    taskStatus.cancel();
166
                                    LOGGER.info("CSV writing canceled ("+getFullFileName()+")");
167
                                    break;
168
                                }
169
                                FeatureProvider feature = getStoreServices().getFeatureProviderFromFeature(
170
                                        (org.gvsig.fmap.dal.feature.Feature) it.next());
171
                                writer.add(feature);
172
                                if (feature.getOID() == null) {
173
                                    LOGGER.warn("feature without OID");
174
                                    feature.setOID(createNewOID());
175
                                }
176
                            }
177
                            if (writer.getEnvelopes() != null) {
178
                                envelopes = writer.getEnvelopes();
179
                            } else {
180
                                envelopes = null;
181
                            }
182
                            resource.notifyChanges();
183
                            writer.end();
184
                            if( !taskStatus.isCancelled() ) {
185
                                if (!csvParams.getFile().delete()) {
186
                                    LOGGER.debug("Can't delete csv file '" + csvParams.getFile() + "'.");
187
                                    throw new IOException("Can't delete csv '"
188
                                            + FilenameUtils.getBaseName(csvParams.getFile().getAbsolutePath())
189
                                            + "' file to replace with the new csv.\nThe new csv is in temporary file '" + tmpFile.getAbsolutePath()
190
                                            + "'");
191
                                }
192

    
193
                                File csvFile = csvParams.getFile();
194
                                FileUtils.moveFile(tmpParams.getFile(), csvFile);
195
                                FileUtils.delete(new File(FilenameUtils.removeExtension(csvFile.getAbsolutePath())+".idx"));
196

    
197
                                bboxFileSave(envelopes);
198

    
199
                                loadFeatures();
200
                            }
201
                        }
202
                    } finally {
203
                        if (it != null) {
204
                            it.dispose();
205
                        }
206
                        if (features != null) {
207
                            features.dispose();
208
                        }
209
                    }
210
                    return null;
211
                }
212

    
213
            });
214
            this.taskStatus.terminate();
215
        } catch (Exception e) {
216
            this.taskStatus.abort();
217
            throw new PerformEditingException(getResource().toString(), e);
218
        }
219
    }
220

    
221
    private CsvPreference getCSVPreferences() {
222
        CSVReaderSuperCSV reader = new CSVReaderSuperCSV(getCSVParameters());
223
        return reader.getCSVPreferences();
224
    }
225

    
226
    @Override
227
    public boolean supportsAppendMode() {
228
        return true;
229
    }
230

    
231
    @Override
232
    @SuppressWarnings("Convert2Lambda")
233
    public void append(final FeatureProvider featureProvider) {
234
        //todo
235
        getResource().execute(new ResourceAction() {
236
            @Override
237
            public Object run() throws Exception {
238
                //writer.append(getStoreServices().createFeature(featureProvider));
239
                writer.add(featureProvider);
240
                return null;
241
            }
242
        });
243
    }
244

    
245
    @Override
246
    @SuppressWarnings("Convert2Lambda")
247
    public void beginAppend() throws DataException {
248
        getResource().execute(new ResourceAction() {
249
            @Override
250
            public Object run() throws Exception {
251
                writer.initialize(getCSVParameters(),
252
                        getCSVParameters().getFile(),
253
                        getFeatureStore().getDefaultFeatureType(),
254
                        getCSVPreferences(),
255
                        spatialIndexes
256
                );
257
                writer.beginAppend();
258
                return null;
259
            }
260
        });
261

    
262
    }
263

    
264
    @Override
265
    @SuppressWarnings("Convert2Lambda")
266
    public void endAppend() {
267
        try {
268
            getResource().execute(new ResourceAction() {
269
                @Override
270
                public Object run() throws Exception {
271
                    writer.end();
272
                    resource.notifyChanges(); //resourcesNotifyChanges();
273
                    counterNewsOIDs = -1;
274
                    return null;
275
                }
276
            });
277
            if (writer.getEnvelopes() != null) {
278
                envelopes = writer.getEnvelopes();
279
            } else {
280
                envelopes = null;
281
            }
282
            writer.end();
283
            this.close();
284
            bboxFileSave(envelopes);            
285
            
286
        } catch (Exception ex) {
287
            LOGGER.warn("Not been able to end append '" + this.getFullName() + "'.", ex);
288
        }
289
    }
290
    
291
    @Override
292
    protected boolean mustFixFeatureType() {
293
        try {
294
            String param_types_def = CSVStoreParameters.getRawFieldTypes(this.getParameters());
295
            String[] pointDimensionNames = CSVStoreParameters.getPointDimensionNames(this.getParameters());
296
            String geometry_column = CSVStoreParameters.getGeometryColumn(this.getParameters());
297
            
298
            
299
            FeatureType dalFeatureType = this.getStoreServices().getDefaultFeatureType();
300
            if (StringUtils.isNotBlank(geometry_column)){
301
                FeatureAttributeDescriptor attr = dalFeatureType.getAttributeDescriptor(geometry_column);
302
                if(attr == null || attr.getType() !=  DataTypes.GEOMETRY){
303
                    return true;
304
                }
305
            }
306
            if (StringUtils.isNotBlank(param_types_def)
307
                    || pointDimensionNames != null) {
308
                for (FeatureAttributeDescriptor dalAttr : dalFeatureType) {
309
                    if(dalAttr.isComputed()){
310
                        continue;
311
                    }
312
                    FeatureAttributeDescriptor csvAttr = featureType.getAttributeDescriptor(dalAttr.getName());
313
                    if(csvAttr == null){
314
                        return true;
315
                    }
316
                    if(!dalAttr.get("all").equals(csvAttr.get("all"))){
317
                        return true;
318
                    }
319
                }
320
            }
321
        } catch (DataException ex) {
322
            LOGGER.warn("Can't check if should fix the feature type", ex);
323
        }
324
        return false;
325
    }
326

    
327
    @Override
328
    protected SimpleReader getSimpleReader(SimpleReaderStoreParameters parameters, Reader in) throws IOException {
329
        SimpleReader reader;
330
        if (CSVStoreParameters.getRawFieldsDefinition(parameters) != null) {
331
            reader = new FixedLenReader(in, (CSVStoreParameters) parameters);
332
        } else {
333
            reader = new CSVReaderSuperCSV(in, (CSVStoreParameters) parameters);
334
        }
335
        return reader;
336
    }
337

    
338
    @Override
339
    protected SimpleReaderFeatureTypeLoader getFeatureTypeLoader() {
340
        return new CSVFeatureTypeLoader(getCSVParameters());
341
    }
342

    
343
    @Override
344
    public List<String> getRowByIndex(long index) {
345
        List<String> line = super.getRowByIndex(index);
346
        if( line!=null ) {
347
            for (int i = 0; i < line.size(); i++) {
348
                String s = line.get(i);
349
                line.set(i, CSVReaderSuperCSV.unescapeCRLF(s));
350
            }
351
        }      
352
        return line;
353
    }
354

    
355
}