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 / CSVFeatureWriter.java @ 47656

History | View | Annotate | Download (11.4 KB)

1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package org.gvsig.fmap.dal.store.csv;
7

    
8
import java.io.File;
9
import java.io.FileOutputStream;
10
import java.io.IOException;
11
import java.io.OutputStreamWriter;
12
import java.io.Writer;
13
import java.nio.file.Files;
14
import java.util.HashMap;
15
import java.util.Locale;
16
import java.util.Map;
17
import org.apache.commons.lang3.ArrayUtils;
18
import org.apache.commons.lang3.StringUtils;
19
import org.apache.commons.text.StringEscapeUtils;
20
import org.gvsig.fmap.dal.DataTypes;
21
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
22
import org.gvsig.fmap.dal.feature.FeatureType;
23
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
24
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
25
import org.gvsig.fmap.dal.store.csv.simplereaders.CSVReaderSuperCSV;
26
import org.gvsig.fmap.geom.Geometry;
27
import org.gvsig.fmap.geom.GeometryLocator;
28
import org.gvsig.fmap.geom.GeometryManager;
29
import org.gvsig.fmap.geom.SpatialIndex;
30
import org.gvsig.fmap.geom.operation.GeometryOperationException;
31
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
32
import org.gvsig.fmap.geom.primitive.Envelope;
33
import org.gvsig.tools.ToolsLocator;
34
import org.gvsig.tools.dataTypes.Coercion;
35
import org.gvsig.tools.dataTypes.CoercionException;
36
import org.gvsig.tools.dynobject.Tags;
37
import org.slf4j.Logger;
38
import org.slf4j.LoggerFactory;
39
import org.supercsv.io.CsvListWriter;
40
import org.supercsv.prefs.CsvPreference;
41

    
42
/**
43
 *
44
 * @author osc
45
 */
46
@SuppressWarnings("UseSpecificCatch")
47
public class CSVFeatureWriter {
48

    
49
  private static final Logger LOGGER = LoggerFactory.getLogger(CSVFeatureWriter.class);
50

    
51
  private Map<String,Envelope> envelopes = null;
52
  private boolean calculate_envelope = false;
53
  private CsvListWriter listWriter = null;
54
  private CsvPreference csvpreferences = null;
55
  private Writer writer = null;
56
  private FeatureType ftype;
57
  private File file;
58
  private String[] values;
59
  private FeatureAttributeDescriptor[] descriptors;
60
  private Coercion convert = null;
61
//  private CoercionContext converContext = null;
62
  private int errorcounts = 0;
63
  private Throwable lasterror = null;
64
  private CSVStoreParameters storeParameters;
65
  private String charset = null;
66
  private boolean includeMetadataInHeader;
67
    private Locale locale;
68
    private GeometryManager geometryManager;
69
    private Map<String,SpatialIndex> spatialIndexes;
70

    
71
  public void initialize(
72
          CSVStoreParameters storeParameters, 
73
          File file, 
74
          FeatureType ftype, 
75
          CsvPreference csvpreferences
76
    ) {
77
      this.initialize(storeParameters, file, ftype, csvpreferences, null);
78
  }
79
  
80
  public void initialize(
81
          CSVStoreParameters storeParameters, 
82
          File file, 
83
          FeatureType ftype, 
84
          CsvPreference csvpreferences,
85
          Map<String,SpatialIndex> spatialIndex
86
    ) {
87
    this.file = file;
88
    this.ftype = ftype;
89
    this.storeParameters = storeParameters;
90
    if (csvpreferences == null) {
91
      this.csvpreferences = CSVStoreParameters.getPredefinedCSVPreferences(storeParameters);
92
    } else {
93
      this.csvpreferences = csvpreferences;
94
    }
95

    
96
    if (this.ftype != null) {
97
      this.descriptors = this.ftype.getAttributeDescriptors();
98
      if (ftype.getDefaultGeometryAttributeName() != null) {
99
        this.calculate_envelope = true;
100
      }
101
    }
102
    this.convert = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.STRING);
103
//    this.converContext = DataTypeUtils.coerceContextLocale(CSVStoreParameters.getLocale(this.storeParameters));
104
    this.errorcounts = 0;
105
    this.charset = CSVStoreParameters.getCharset(storeParameters);
106
    this.includeMetadataInHeader = CSVStoreParameters.getIncludeMetadataInHeader(storeParameters);
107
    this.locale = CSVStoreParameters.getLocale(storeParameters);
108
    this.geometryManager = GeometryLocator.getGeometryManager();
109
    this.spatialIndexes = spatialIndex;
110
    if( spatialIndex != null ) {
111
        for (SpatialIndex index : spatialIndex.values()) {
112
            index.removeAll();
113
        }
114
    }
115
  }
116

    
117
  public void beginAppend() {
118
    try {
119
      FileOutputStream fos = new FileOutputStream(file, true);
120
      if (this.charset != null) {
121
        this.writer = new OutputStreamWriter(fos, this.charset);
122
      } else {
123
        this.writer = new OutputStreamWriter(fos);
124
      }
125
      this.listWriter = new CsvListWriter(this.writer, this.csvpreferences);
126
      if (ftype != null) {
127
        this.descriptors = ftype.getAttributeDescriptors();
128
        int n = 0;
129
        for (FeatureAttributeDescriptor descriptor : descriptors) {
130
          if (descriptor.getEvaluator() == null) {
131
            n++;
132
          }
133
        }
134
        this.values = new String[n];
135
      }
136
    } catch (IOException e) {
137
      LOGGER.warn("Can't open file for write (" + file.getAbsolutePath() + ").", e);
138
      throw new RuntimeException(e);
139
    }
140
  }
141

    
142
  public void begin() {
143
    try {
144
      FileOutputStream fos = new FileOutputStream(file, false);
145
      if (this.charset != null) {
146
        this.writer = new OutputStreamWriter(fos, this.charset);
147
      } else {
148
        this.writer = new OutputStreamWriter(fos);
149
      }
150
    } catch (IOException e) {
151
      LOGGER.warn("Can't open file for write (" + file.getAbsolutePath() + ").", e);
152
      throw new RuntimeException(e);
153
    }
154
    this.listWriter = new CsvListWriter(this.writer, this.csvpreferences);
155
    int n = 0;
156
    for (FeatureAttributeDescriptor descriptor : descriptors) {
157
      if (!descriptor.isComputed()) { //descriptor.getEvaluator() == null) {
158
        n++;
159
      }
160
    }
161

    
162
    String[] header = new String[n];
163
    this.values = new String[n];
164
    n = 0;
165
      for (FeatureAttributeDescriptor descriptor : descriptors) {
166
          if (!descriptor.isComputed()) {
167
              if (includeMetadataInHeader) {
168
                header[n++] = (String) descriptor.get("all");
169
              } else {
170
                header[n++] = (String) descriptor.getName();
171
              }
172
          }
173
      }
174
      if (includeMetadataInHeader) {
175
        Tags tags = this.ftype.getTags();
176
        if( tags!=null && !tags.isEmpty() ) {
177
          String s = header[0];
178
            for (String tagName : tags) {
179
                String value = tags.getString(tagName, null);
180
                if( value!=null ) {
181
                    String sep = "/";
182
                    if(value.contains(sep)){
183
                        value = StringEscapeUtils.escapeHtml3(value);
184
                        value = StringUtils.replace(value, sep, "&#"+((int)(sep.charAt(0)))+";");
185
                        s += sep+"typetagesc"+sep+"html"+sep+tagName+"="+value;
186
                    } else {
187
                        s += sep+"typetag"+sep+tagName+"="+value;
188
                    }
189
                }
190
            }
191
            header[0] = s;
192
        }
193
      }
194
    try {
195
      listWriter.writeHeader(header);
196
    } catch (Exception e) {
197
      LOGGER.warn("Can't write header '" + ArrayUtils.toString(header) + "' file for write (" + file.getAbsolutePath() + ").", e);
198
      throw new RuntimeException(e);
199
    }
200
  }
201

    
202
  public void add(FeatureProvider feature) {
203
    if (this.calculate_envelope) {
204
        if (envelopes == null) {
205
            envelopes = new HashMap<>();
206
        }
207
        for (FeatureAttributeDescriptor featureAttributeDescriptor : ftype) {
208
            if(featureAttributeDescriptor.getType()==DataTypes.GEOMETRY){
209
                String geomName = featureAttributeDescriptor.getName();
210
                Geometry geom = (Geometry) feature.get(geomName);
211
                Envelope env = envelopes.get(geomName);
212
                if (env == null) {
213
                    if (geom == null) {
214
                        envelopes.put(geomName, null);
215
                    } else {
216
                        try {
217
                            envelopes.put(geomName, (Envelope) geom.getEnvelope().clone());
218
                        } catch (CloneNotSupportedException e) {
219
                            LOGGER.warn("Este error no deberia pasar, siempre se puede hacer un clone de un envelope.", e);
220
                        }
221
                    }
222
                } else {
223
                    if (geom != null){
224
                        env.add(geom.getEnvelope());
225
                    }
226
                }
227
            }
228
        }
229
    }
230

    
231
    if(spatialIndexes == null){
232
        spatialIndexes = new HashMap<>();
233
    }
234

    
235
    for (int i = 0; i < descriptors.length; i++) {
236
      FeatureAttributeDescriptor descriptor = descriptors[i];
237
      if (descriptor.getEvaluator() == null) {
238
        Object value = feature.get(i);
239
        try {
240
          if( descriptor.getType()==DataTypes.GEOMETRY ) {
241
              String geomName = descriptor.getName();
242
              Geometry geom = (Geometry) value;
243
              if(geom != null){
244
                SpatialIndex index = spatialIndexes.get(geomName);
245
                if(index != null){
246
                    index.insert(geom, feature.getOID());
247
                }
248
                if( StringUtils.equalsIgnoreCase("WKT", CSVStoreParameters.getGeometryFormat(storeParameters))) {
249
                  values[i] = geom.convertToWKT();
250
                } else {
251
                  values[i] = geom.convertToHexWKB();
252
                }
253
              }
254
          } else {
255
            values[i] = (String) this.convert.coerce(value, descriptor.getCoercionContext());
256
          }
257
        } catch (CoercionException|GeometryOperationNotSupportedException|GeometryOperationException e) {
258
          try {
259
            values[i] = value.toString();
260
          } catch (Exception ex) {
261
            values[i] = "";
262
          }
263
          if (errorcounts++ <= 10) {
264
            this.lasterror = e;
265
            LOGGER.warn("Can't convert value of field " + i + " to string in CVS file '" + this.file.getAbsolutePath() + "'.", e);
266
            if (errorcounts == 10) {
267
              LOGGER.warn("Too many error writing CVS file '" + this.file.getAbsolutePath() + "', don't output more.");
268
            }
269
          }
270
        }
271
        values[i] = CSVReaderSuperCSV.escapeCRLF(values[i]);
272
      }
273
    }
274
    try {
275
      this.listWriter.write(values);
276
    } catch (IOException e) {
277
      if (errorcounts++ <= 10) {
278
        this.lasterror = e;
279
        LOGGER.warn("Can't write values to CVS file '" + this.file.getAbsolutePath() + "'.", e);
280
        if (errorcounts == 10) {
281
          LOGGER.warn("Too many error writing CVS file '" + this.file.getAbsolutePath() + "', don't output more.");
282
        }
283
      }
284
    }
285

    
286
  }
287

    
288
  public void end() throws PerformEditingException {
289
    if (this.errorcounts > 0) {
290
      throw new PerformEditingException(this.file.getAbsolutePath(), lasterror);
291
    }
292
    if (listWriter != null) {
293
      try {
294
        listWriter.close();
295
      } catch (Exception ex) {
296
        // Ignore error
297
      }
298
      listWriter = null;
299
    }
300
    if (writer != null) {
301
      try {
302
        writer.close();
303
      } catch (Exception ex) {
304
        // Ignore error
305
      }
306
      writer = null;
307
    }
308
    File indexFile = null;
309
    try {
310
        indexFile = CSVReaderSuperCSV.getIndexFile(this.file);
311
        if(indexFile != null){
312
            Files.deleteIfExists(indexFile.toPath());
313
        }
314
    } catch (Exception ex){
315
        LOGGER.warn("Can't delete index file '"+(indexFile == null?"null":indexFile.getAbsolutePath())+"'", ex);
316
    }
317
    if( spatialIndexes!=null ) {
318
        for (SpatialIndex index : spatialIndexes.values()) {
319
            index.flush();
320
        }
321
    }
322
  }
323

    
324
  public Map<String,Envelope> getEnvelopes() {
325
    return this.envelopes;
326
  }
327
}