Revision 47636

View differences:

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

  
26
import java.util.Iterator;
27
import java.util.List;
28
import java.util.NoSuchElementException;
29

  
30
import org.gvsig.fmap.dal.exception.DataException;
31
import org.gvsig.fmap.dal.exception.ReadRuntimeException;
32
import org.gvsig.fmap.dal.feature.FeatureQuery;
33
import org.gvsig.fmap.dal.feature.FeatureType;
34
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureProviderIterator;
35
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureSetProvider;
36
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
37
import org.gvsig.tools.exception.BaseException;
38

  
39
/**
40
 * @author jjdelcerro
41
 *
42
 */
43
public class CSVSetProvider extends AbstractFeatureSetProvider {
44

  
45
    private static class CSVFeatureProvider extends AbstractFeatureProviderLoadedOnDemand {
46

  
47
        protected CSVStoreProvider store;
48

  
49
        public CSVFeatureProvider(CSVStoreProvider store, FeatureType type) {
50
            super(type);
51
            this.store = store;
52
        }
53

  
54
        @Override
55
        protected void doLoad() {
56
            try {
57
                CSVStoreProvider.RowToFeatureTranslator translator = this.store.getRowToFeatureTranslator();
58
                long index = this.getOID();
59
                List<String> row = this.store.getRowByIndex(index);
60
                translator.translate(index, row, this);
61
            } catch (Exception ex) {
62
                throw new ReadRuntimeException(getStoreFullName(), this.getOID(), ex);
63
            }
64
        }
65

  
66
        @Override
67
        public Long getOID() {
68
            return (Long) super.getOID();
69
        }
70

  
71
        public void setOID(long oid) {
72
            super.setOID(oid); 
73
        }
74

  
75
        private String getStoreFullName() {
76
            try {
77
                return this.store.getFullName();
78
            } catch (Exception ex) {
79
                return "unknown";
80
            }
81
        }
82

  
83
    }
84
    private class CSVIterator extends AbstractFeatureProviderIterator {
85

  
86
        protected long index;
87
        protected FeatureType type;
88
        protected long count;
89
        protected final FeatureQuery query;
90
        protected Iterator spatialIndexIt;
91

  
92
        public CSVIterator(CSVStoreProvider store, FeatureQuery query, FeatureType type,
93
                long startOn) throws DataException {
94
            super(store);
95
            this.index = startOn;
96
            this.type = type;
97
            this.query = query;
98
            this.count = store.getFeatureCount();
99
            if( this.query!=null ) {
100
                this.spatialIndexIt = createSpatialIterator(
101
                        store.getFeatureStore().getDefaultFeatureTypeQuietly(), 
102
                        query, 
103
                        store.getSpatialIndex()
104
                );
105
            }
106
        }
107

  
108
        @Override
109
        protected CSVStoreProvider getFeatureStoreProvider() {
110
            return (CSVStoreProvider) super.getFeatureStoreProvider(); 
111
        }
112

  
113
        @Override
114
        protected boolean internalHasNext() {
115
            if( this.spatialIndexIt != null ) {
116
                return this.spatialIndexIt.hasNext();
117
            }
118
            return this.count > index;
119
        }
120

  
121
        @Override
122
        protected FeatureProvider internalNext() {
123
            CSVFeatureProvider data = new CSVFeatureProvider(getStore(), type);
124
            if( this.spatialIndexIt != null ) {
125
                Object oid = this.spatialIndexIt.next();                
126
                data.setOID(oid);
127
            } else {
128
                if (index >= this.count) {
129
                    throw new NoSuchElementException();
130
                }
131
                data.setOID(index++);
132
            }   
133
            return data;
134
        }
135

  
136
        @Override
137
        public void remove() {
138
            throw new UnsupportedOperationException();
139
        }
140

  
141
        protected void internalDispose() {
142
            type = null;
143
        }
144

  
145
        @Override
146
        protected void doDispose() throws BaseException {
147
            // Nothing to do
148
        }
149
    }
150

  
151
    private class FastCSVIterator extends CSVIterator {
152

  
153
        protected FeatureProvider data;
154

  
155
        public FastCSVIterator(CSVStoreProvider store, FeatureQuery query, FeatureType type,
156
                long startOn) throws DataException {
157
            super(store, query, type, startOn);
158
            this.data = new CSVFeatureProvider(store, type);
159
        }
160

  
161
        @Override
162
        protected FeatureProvider internalNext() {
163
            if( this.spatialIndexIt != null ) {
164
                Object oid = this.spatialIndexIt.next();                
165
                data.setOID(oid);
166
            } else {
167
                if (index >= this.count) {
168
                    throw new NoSuchElementException();
169
                }
170
                data.setOID(index++);
171
            }   
172
            return data;            
173
        }
174

  
175
        @Override
176
        protected void internalDispose() {
177
            super.internalDispose();
178
            data = null;
179
        }
180
    }
181

  
182
    public CSVSetProvider(CSVStoreProvider store, FeatureQuery query,
183
            FeatureType providerFeatureType, FeatureType featureType)
184
            throws DataException {
185
        super(store, query, providerFeatureType, featureType);
186
    }
187

  
188
    @Override
189
    protected CSVStoreProvider getStore() {
190
        return (CSVStoreProvider) super.getStore();
191
    }
192

  
193
    protected String getStoreFullName() {
194
        try {
195
            return this.getStore().getFullName();
196
        } catch (Throwable th) {
197
            return "unknown";
198
        }
199
    }
200

  
201
    @Override
202
    public boolean canFilter() {
203
        return false;
204
    }
205

  
206
    @Override
207
    public boolean canIterateFromIndex() {
208
        return true;
209
    }
210

  
211
    @Override
212
    public boolean canOrder() {
213
        return false;
214
    }
215

  
216
    @Override
217
    public long getSize() throws DataException {
218
        return getStore().getFeatureCount();
219
    }
220

  
221
    @Override
222
    public boolean isEmpty() throws DataException {
223
        return getSize() == 0;
224
    }
225

  
226
    @Override
227
    protected void doDispose() throws BaseException {
228
    }
229

  
230
    @Override
231
    protected AbstractFeatureProviderIterator createIterator(long index)
232
            throws DataException {
233
        return new CSVIterator(
234
                getStore(),
235
                getQuery(),
236
                getProviderFeatureType(),
237
                index
238
        );
239
    }
240

  
241
    @Override
242
    protected AbstractFeatureProviderIterator createFastIterator(long index)
243
            throws DataException {
244
        return new FastCSVIterator(
245
                getStore(),
246
                getQuery(),
247
                getProviderFeatureType(),
248
                index
249
        );
250
    }
251
}
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/AutomaticDetectionOfTypes.java
1
package org.gvsig.fmap.dal.store.csv;
2

  
3
import java.io.IOException;
4
import java.math.BigDecimal;
5
import java.net.URL;
6
import java.util.ArrayList;
7
import java.util.List;
8
import java.util.Locale;
9
import org.apache.commons.lang3.StringUtils;
10
import org.gvsig.fmap.dal.DataTypes;
11
import org.gvsig.fmap.geom.GeometryCoercionContext;
12
import org.gvsig.fmap.geom.GeometryLocator;
13
import org.gvsig.tools.ToolsLocator;
14
import org.gvsig.tools.dataTypes.DataTypeUtils;
15
import org.gvsig.tools.dataTypes.DataTypesManager;
16
import org.gvsig.tools.dataTypes.Coercion;
17
import org.gvsig.tools.dataTypes.CoercionContext;
18
import org.gvsig.tools.i18n.I18nManager;
19
import org.gvsig.tools.task.SimpleTaskStatus;
20

  
21
/**
22
 *
23
 * @author jjdelcerro
24
 */
25
public class AutomaticDetectionOfTypes {
26

  
27
    public interface Rows {
28

  
29
        public List<String> nextRowValues();
30
    }
31
    
32
    public interface DetectedValue {
33
        public int getType();
34
        public int getDisplaySize();
35
        public int getPrecision();
36
        public int getScale();
37
        public boolean isBlank();
38
    }
39
    
40
    private static class DetectedValueImpl implements DetectedValue {
41

  
42
        private int type;
43
        private int displaySize;
44
        private int integerDigits;
45
        private int decimalDigits;
46
        private boolean blank;
47
        
48
        @Override
49
        public int getType() {
50
            return this.type;
51
        }
52

  
53
        @Override
54
        public int getDisplaySize() {
55
            return this.displaySize;
56
        }
57

  
58
        @Override
59
        public int getPrecision() {
60
            return this.decimalDigits + this.integerDigits;
61
        }
62

  
63
        @Override
64
        public int getScale() {
65
            return this.decimalDigits;
66
        }
67
        
68
        public boolean isBlank() {
69
            return this.blank;
70
        }
71
    }
72

  
73
    private static class PossibleDataType {
74

  
75
        public boolean possibleInt = true;
76
        public boolean possibleFloat = true;
77
        public boolean possibleDouble = true;
78
        public boolean possibleDecimal = true;
79
        public boolean possibleLong = true;
80
        public boolean possibleURL = true;
81
        public boolean possibleDate = true;
82
        public boolean possibleTime = true;
83
        public boolean possibleTimestamp = true;
84
        public boolean possibleGeometry = true;
85
    }
86

  
87
    private final String filename;
88

  
89
    public AutomaticDetectionOfTypes() {
90
        this("(unknown)");
91
    }
92

  
93
    public AutomaticDetectionOfTypes(String filename) {
94
        this.filename = filename;
95
    }
96

  
97
    private String getFullFileName() {
98
        return this.filename;
99
    }
100

  
101
    @SuppressWarnings({"UseSpecificCatch", "ResultOfObjectAllocationIgnored"})
102
    public DetectedValue[] detect(int columns,
103
            Rows rows,
104
            boolean isFirstLineHeader,
105
            Locale locale,
106
            SimpleTaskStatus status
107
    ) throws IOException {
108
        List<PossibleDataType> possibleDataTypes;
109
        List<DetectedValueImpl> detectedValues = new ArrayList<>(columns);
110
        I18nManager i18n = ToolsLocator.getI18nManager();
111
        
112
        if( status!=null ) {
113
            status.message(i18n.getTranslation("_Types_detection"));
114
        }
115
        
116
        int lineno = 0;
117
        try {
118
            if (isFirstLineHeader) {
119
                rows.nextRowValues();
120
                lineno++;
121
            }
122
            possibleDataTypes = new ArrayList<>(columns);
123
            for (int i = 0; i < columns; i++) {
124
                possibleDataTypes.add(new PossibleDataType());
125
                detectedValues.add(new DetectedValueImpl());
126
            }
127
            if (locale == null) {
128
                locale = Locale.getDefault();
129
            }
130
            DataTypesManager typeManager = ToolsLocator.getDataTypesManager();
131
            Coercion toDecimal = typeManager.getCoercion(DataTypes.DECIMAL);
132
            Coercion toDouble = typeManager.getCoercion(DataTypes.DOUBLE);
133
            Coercion toFloat = typeManager.getCoercion(DataTypes.FLOAT);
134
            Coercion toDate = typeManager.getCoercion(DataTypes.DATE);
135
            Coercion toTime = typeManager.getCoercion(DataTypes.TIME);
136
            Coercion toTimestamp = typeManager.getCoercion(DataTypes.TIMESTAMP);
137
            Coercion toInt = typeManager.getCoercion(DataTypes.INT);
138
            Coercion toLong = typeManager.getCoercion(DataTypes.LONG);
139
            Coercion toGeom = typeManager.getCoercion(DataTypes.GEOMETRY); 
140

  
141
            GeometryCoercionContext  geometryCoercionContext = GeometryLocator.getGeometryManager().createGeometryCoercionContext();
142
            geometryCoercionContext.setMode(GeometryCoercionContext.MODE_ONERROR_THROW);
143

  
144
            CoercionContext coercionContext = DataTypeUtils.coerceContextLocale(locale);
145
            List<String> row = rows.nextRowValues();
146
            lineno++;
147

  
148
            int detectedValuesSize = detectedValues.size();
149
            while (row != null) {
150
                if( status!=null ) {
151
                    status.incrementCurrentValue();
152
                    if( status.isCancellationRequested() ) {
153
                        status.cancel();
154
                        break;
155
                    }
156
                }
157
                int rowsize = row.size();
158
                if( rowsize>detectedValuesSize ) {
159
                    for (int i = detectedValuesSize; i < rowsize; i++) {
160
                        possibleDataTypes.add(new PossibleDataType());
161
                        detectedValues.add(new DetectedValueImpl());
162
                    }
163
                    detectedValuesSize = detectedValues.size();
164
                }
165
                for (int i = 0; i < rowsize; i++) {
166
                    while( possibleDataTypes.size()<row.size() ) {
167
                        possibleDataTypes.add(new PossibleDataType());
168
                    }
169
                    String rawvalue = row.get(i);
170
                    if( rawvalue == null ) {
171
                       continue; 
172
                    }
173
                    
174
                    PossibleDataType possibleDataType = possibleDataTypes.get(i);
175
                    DetectedValueImpl detectedValue = detectedValues.get(i);
176
                    if( detectedValue.blank ) {
177
                        detectedValue.blank = StringUtils.isBlank(rawvalue);
178
                    }
179
                    int displaySize = rawvalue.length();
180
                    if( displaySize>detectedValue.displaySize ) {
181
                        detectedValue.displaySize = displaySize;
182
                    }
183
                    if (possibleDataType.possibleDecimal) {
184
                        try {
185
                            BigDecimal decimal = (BigDecimal) toDecimal.coerce(rawvalue, coercionContext);
186
                            possibleDataType.possibleDecimal = true;
187
                            if( decimal.scale() > detectedValue.decimalDigits ) {
188
                                detectedValue.decimalDigits = decimal.scale();
189
                            }
190
                            int integerDigits = decimal.precision() - decimal.scale();
191
                            if( integerDigits>detectedValue.integerDigits ) {
192
                                detectedValue.integerDigits = integerDigits;
193
                            }
194
                        } catch (Exception ex) {
195
                            possibleDataType.possibleDecimal = false;
196
                        }
197
                    }
198
                    if (possibleDataType.possibleDouble) {
199
                        try {
200
                            toDouble.coerce(rawvalue, coercionContext);
201
                            possibleDataType.possibleDouble = true;
202
                        } catch (Exception ex) {
203
                            possibleDataType.possibleDouble = false;
204
                        }
205
                    }
206
                    if (possibleDataType.possibleFloat) {
207
                        try {
208
                            toFloat.coerce(rawvalue, coercionContext);
209
                            possibleDataType.possibleFloat = true;
210
                        } catch (Exception ex) {
211
                            possibleDataType.possibleFloat = false;
212
                        }
213
                    }
214
                    if (possibleDataType.possibleLong) {
215
                        possibleDataType.possibleLong = isValidLong(rawvalue);
216
                    }
217
                    if (possibleDataType.possibleInt) {
218
                        possibleDataType.possibleInt = isValidInteger(rawvalue);
219
                    }
220
                    if (possibleDataType.possibleDate) {
221
                        try {
222
                            toDate.coerce(rawvalue, coercionContext);
223
                            possibleDataType.possibleDate = true;
224
                        } catch (Exception ex) {
225
                            possibleDataType.possibleDate = false;
226
                        }
227
                    }
228
                    if (possibleDataType.possibleTime) {
229
                        try {
230
                            toTime.coerce(rawvalue, coercionContext);
231
                            possibleDataType.possibleTime = true;
232
                        } catch (Exception ex) {
233
                            possibleDataType.possibleTime = false;
234
                        }
235
                    }
236
                    if (possibleDataType.possibleTimestamp) {
237
                        try {
238
                            toTimestamp.coerce(rawvalue, coercionContext);
239
                            possibleDataType.possibleTimestamp = true;
240
                        } catch (Exception ex) {
241
                            possibleDataType.possibleTimestamp = false;
242
                        }
243
                    }
244
                    if (possibleDataType.possibleURL) {
245
                        try {
246
                            new URL((String) rawvalue);
247
                            possibleDataType.possibleURL = true;
248
                        } catch (Exception ex) {
249
                            possibleDataType.possibleURL = false;
250
                        }
251
                    }
252
                    
253
                    if (possibleDataType.possibleGeometry) {
254
                        try {
255
                            toGeom.coerce((String) rawvalue, geometryCoercionContext);
256
                            possibleDataType.possibleGeometry = true;
257
                        } catch (Exception ex) {
258
                            possibleDataType.possibleGeometry = false;
259
                        }
260
                    }
261
                }
262
                row = rows.nextRowValues();
263
                lineno++;
264
            }
265
            if( status!=null ) {
266
                status.setRangeOfValues(0, lineno);
267
                status.setCurValue(0);
268
            }
269
            int n = 0;
270
            for (PossibleDataType possibleDataType : possibleDataTypes) {
271
                if (possibleDataType.possibleInt) {
272
                    detectedValues.get(n++).type = DataTypes.INT;
273
                    continue;
274
                }
275
                if (possibleDataType.possibleLong) {
276
                    detectedValues.get(n++).type = DataTypes.LONG;
277
                    continue;
278
                }
279
                if (possibleDataType.possibleDecimal) {
280
                    // Preferimos un Decimal que un Float/Double
281
                    detectedValues.get(n++).type = DataTypes.DECIMAL;
282
                    continue;
283
                }
284
                if (possibleDataType.possibleFloat) {
285
                    // Forzamos los float a double para evitar perder precision
286
                    detectedValues.get(n++).type = DataTypes.DOUBLE;
287
                    continue;
288
                }
289
                if (possibleDataType.possibleDouble) {
290
                    detectedValues.get(n++).type = DataTypes.DOUBLE;
291
                    continue;
292
                }
293
                if (possibleDataType.possibleURL) {
294
                    detectedValues.get(n++).type = DataTypes.URL;
295
                    continue;
296
                }
297
                if (possibleDataType.possibleDate) {
298
                    detectedValues.get(n++).type = DataTypes.DATE;
299
                    continue;
300
                }
301
                if (possibleDataType.possibleTime) {
302
                    detectedValues.get(n++).type = DataTypes.TIME;
303
                    continue;
304
                }
305
                if (possibleDataType.possibleTimestamp) {
306
                    detectedValues.get(n++).type = DataTypes.TIMESTAMP;
307
                    continue;
308
                }
309
                if (possibleDataType.possibleGeometry) {
310
                    detectedValues.get(n++).type = DataTypes.GEOMETRY;
311
                    continue;
312
                }
313
                detectedValues.get(n++).type = DataTypes.STRING;
314
            }
315
        } catch (Throwable ex) {
316
            status.abort();
317
            throw new RuntimeException("Problems reading file '" + this.getFullFileName() + "' near line " + lineno + ".", ex);
318
        }
319
        DetectedValue[] r = detectedValues.toArray(new DetectedValue[detectedValues.size()]);
320
        return r;
321
    }
322

  
323
    @SuppressWarnings("UseSpecificCatch")
324
    private boolean isValidLong(String s) {
325
        if (s == null) {
326
            return true;
327
        }
328
        s = s.trim().toLowerCase();
329
        if (s.isEmpty()) {
330
            return true;
331
        }
332
        try {
333
            if (s.startsWith("0x")) {
334
                Long.valueOf(s.substring(2), 16);
335
            } else {
336
                Long.valueOf(s);
337
            }
338
            return true;
339
        } catch (Exception ex) {
340
            return false;
341
        }
342
    }
343

  
344
    @SuppressWarnings("UseSpecificCatch")
345
    private boolean isValidInteger(String s) {
346
        if (s == null) {
347
            return true;
348
        }
349
        s = s.trim().toLowerCase();
350
        if (s.isEmpty()) {
351
            return true;
352
        }
353
        try {
354
            if (s.startsWith("0x")) {
355
                Integer.valueOf(s.substring(2), 16);
356
            } else {
357
                Integer.valueOf(s);
358
            }
359
            return true;
360
        } catch (Exception ex) {
361
            return false;
362
        }
363
    }
364

  
365
}
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/FieldTypeParser.java
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.util.HashMap;
9
import java.util.Map;
10
import org.apache.commons.lang3.StringUtils;
11
import org.apache.commons.text.StringEscapeUtils;
12
import org.gvsig.fmap.dal.DataTypes;
13
import org.gvsig.fmap.geom.Geometry;
14
import org.gvsig.fmap.geom.GeometryUtils;
15
import org.gvsig.tools.ToolsLocator;
16
import org.gvsig.tools.dataTypes.DataTypesManager;
17
import org.slf4j.Logger;
18
import org.slf4j.LoggerFactory;
19

  
20
/**
21
 *
22
 * @author jjdelcerro
23
 */
24
public class FieldTypeParser {
25
    private static final Logger LOGGER = LoggerFactory.getLogger(FieldTypeParser.class);
26
    
27
    public String name = null;
28
    public int type = DataTypes.UNKNOWN;
29
    public int size = 0;
30
    public int geomType = Geometry.TYPES.GEOMETRY;
31
    public int geomSubtype = Geometry.SUBTYPES.GEOM2D;
32
    public Map<String, String> tags = new HashMap<>();
33
    public Map<String, String> typetags = new HashMap<>();
34
    public Map<String, String> assignments = new HashMap<>();
35
    public Map<String, String> typeAssignments = new HashMap<>();
36
    // Valores obtenidos desde la deteccion automatica desde los datos
37
    public AutomaticDetectionOfTypes.DetectedValue detectedValue = null;
38
    private String typename = "string";
39
    private final String fullFileName;
40
    private final String providerName;
41

  
42
    FieldTypeParser(String providerName, String fullFileName) {
43
        this.providerName = providerName;
44
        this.fullFileName = fullFileName;
45
    }
46

  
47
    public String getProviderName() {
48
        return this.providerName;
49
    }
50

  
51
    public String getFullFileName() {
52
        return this.fullFileName;
53
    }
54

  
55
    public void clear() {
56
        this.name = null;
57
        this.type = DataTypes.UNKNOWN;
58
        this.size = 0;
59
        this.tags = new HashMap<>();
60
        this.typetags = new HashMap<>();
61
        this.assignments = new HashMap<>();
62
        this.typeAssignments = new HashMap<>();
63
    }
64

  
65
    public void copyFrom(FieldTypeParser other) {
66
        this.name = other.name;
67
        this.type = other.type;
68
        this.size = other.size;
69
        this.tags = new HashMap<>();
70
        this.tags.putAll(other.tags);
71
        this.typetags = new HashMap<>();
72
        this.typetags.putAll(other.typetags);
73
        this.assignments = new HashMap<>();
74
        this.assignments.putAll(other.assignments);
75
        this.typeAssignments = new HashMap<>();
76
        this.typeAssignments.putAll(other.typeAssignments);
77
    }
78

  
79
    private int getType(String value) {
80
        DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
81
        return dataTypesManager.getType(typename);
82
    }
83

  
84
    private String[] split(String value, String separators) {
85
        int firstSeparatorPosition = 1000000;
86
        Character sep = null;
87
        for (char ch : separators.toCharArray()) {
88
            int pos = value.indexOf(ch);
89
            if (pos > 0 && pos < firstSeparatorPosition) {
90
                sep = ch;
91
                firstSeparatorPosition = pos;
92
            }
93
        }
94
        if (sep == null) {
95
            return new String[]{value};
96
        }
97
        return value.split("[" + sep + "]");
98
    }
99

  
100
    @SuppressWarnings(value = "UseSpecificCatch")
101
    public boolean parse(String value) {
102
        String[] args;
103
        if (value.contains("__")) {
104
            args = value.split("__");
105
        } else {
106
            args = split(value, ":/#@!;-");
107
            if (args.length == 1) {
108
                this.name = value;
109
                return true;
110
            }
111
        }
112
        int n = 0;
113
        this.name = StringUtils.trim(args[n++]);
114
        if (n >= args.length) {
115
            return true;
116
        }
117
        this.typename = StringUtils.trim(args[n++]);
118
        this.type = this.getType(this.typename);
119
        if (this.type == DataTypes.INVALID) {
120
            this.geomType = GeometryUtils.getGeometryType(this.typename);
121
            if (this.geomType == Geometry.TYPES.UNKNOWN) {
122
                this.type = DataTypes.STRING;
123
                LOGGER.info("Type '" + this.typename + "' not valid for attribute '" + value + "' in '" + getProviderName() + "' file '" + getFullFileName() + "'.");
124
            } else {
125
                this.typename = "GEOMETRY";
126
                this.type = DataTypes.GEOMETRY;
127
            }
128
        }
129
        this.size = 0;
130
        while (n < args.length) {
131
            String escMode = null;
132
            String option = StringUtils.trim(args[n++].toLowerCase());
133
            switch (option) {
134
                case "size":
135
                    try {
136
                        this.size = Integer.parseInt(args[n++]);
137
                    } catch (Exception ex) {
138
                        LOGGER.warn("Ignore incorrect field size for field " + value + " in '" + getProviderName() + "' file '" + getFullFileName() + "'.", ex);
139
                    }
140
                    break;
141
                case "tagesc":
142
                    escMode = StringUtils.trim(args[n++]);
143
                case "tag":
144
                    {
145
                        String x = StringUtils.trim(args[n++]);
146
                        int pos = x.indexOf("=");
147
                        if (pos < 0) {
148
                            this.tags.put(x, null);
149
                        } else {
150
                            String v = StringUtils.trim(StringUtils.substring(x, pos + 1));
151
                            if(escMode != null) {
152
                                if(StringUtils.equalsIgnoreCase(escMode,"html")){
153
                                    v = StringEscapeUtils.unescapeHtml3(v);
154
                                } else {
155
                                    LOGGER.warn("Illegal escape mode for argument '" + option + "' for field '" + this.name + "' in '" + getProviderName() + "' file '" + getFullFileName() + "' (" + value + ").");
156
                                }
157
                            }
158
                            this.tags.put(StringUtils.trim(StringUtils.substring(x, 0, pos)), v);
159
                        }
160
                        break;
161
                    }
162
                case "typetagesc":
163
                    escMode = StringUtils.trim(args[n++]);
164
                case "typetag":
165
                    {
166
                        String x = StringUtils.trim(args[n++]);
167
                        int pos = x.indexOf("=");
168
                        if (pos < 0) {
169
                            this.typetags.put(x, null);
170
                        } else {
171
                            String v = StringUtils.trim(StringUtils.substring(x, pos + 1));
172
                            if(escMode != null) {
173
                                if(StringUtils.equalsIgnoreCase(escMode,"html")){
174
                                    v = StringEscapeUtils.unescapeHtml3(v);
175
                                } else {
176
                                    LOGGER.warn("Illegal escape mode for argument '" + option + "' for field '" + this.name + "' in '" + getProviderName() + "' file '" + getFullFileName() + "' (" + value + ").");
177
                                }
178
                            }
179
                            this.typetags.put(StringUtils.trim(StringUtils.substring(x, 0, pos)), v);
180
                        }
181
                        break;
182
                    }
183
                case "setesc":
184
                        escMode = StringUtils.trim(args[n++]);
185
                case "set":
186
                    {
187
                        String x = StringUtils.trim(args[n++]);
188
                        int pos = x.indexOf("=");
189
                        if (pos < 0) {
190
                            this.assignments.put(x, null);
191
                        } else {
192
                            String v = StringUtils.trim(StringUtils.substring(x, pos + 1));
193
                            if(escMode != null) {
194
                                if(StringUtils.equalsIgnoreCase(escMode,"html")){
195
                                    v = StringEscapeUtils.unescapeHtml3(v);
196
                                } else {
197
                                    LOGGER.warn("Illegal escape mode for argument '" + option + "' for field '" + this.name + "' in '" + getProviderName() + "' file '" + getFullFileName() + "' (" + value + ").");
198
                                }
199
                            }
200
                            this.assignments.put(StringUtils.trim(StringUtils.substring(x, 0, pos)), v);
201
                        }
202
                        break;
203
                    }
204
                case "typesetesc":
205
                        escMode = StringUtils.trim(args[n++]);
206
                case "typeset":
207
                    {
208
                        String x = StringUtils.trim(args[n++]);
209
                        int pos = x.indexOf("=");
210
                        if (pos < 0) {
211
                            this.typeAssignments.put(x, null);
212
                        } else {
213
                            String v = StringUtils.trim(StringUtils.substring(x, pos + 1));
214
                            if(escMode != null) {
215
                                if(StringUtils.equalsIgnoreCase(escMode,"html")){
216
                                    v = StringEscapeUtils.unescapeHtml3(v);
217
                                } else {
218
                                    LOGGER.warn("Illegal escape mode for argument '" + option + "' for field '" + this.name + "' in '" + getProviderName() + "' file '" + getFullFileName() + "' (" + value + ").");
219
                                }
220
                            }
221
                            this.typeAssignments.put(StringUtils.trim(StringUtils.substring(x, 0, pos)), v);
222
                        }
223
                        break;
224
                    }
225
                default:
226
                    if (StringUtils.isNumeric(option) && this.size == 0) {
227
                        try {
228
                            this.size = Integer.parseInt(option);
229
                        } catch (Exception ex) {
230
                            LOGGER.warn("Ignore incorrect field size for field " + value + " in '" + getProviderName() + "' file '" + getFullFileName() + "'.", ex);
231
                        }
232
                        break;
233
                    }
234
                    LOGGER.warn("Illegal argument '" + option + "' for field '" + this.name + "' in '" + getProviderName() + "' file '" + getFullFileName() + "' (" + value + ").");
235
            }
236
        }
237
        return true;
238
    }
239
    
240
}
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
22 22
 */
23 23
package org.gvsig.fmap.dal.store.csv;
24 24

  
25
import java.io.Closeable;
26 25
import java.io.File;
27 26
import java.io.IOException;
28
import java.io.InputStreamReader;
29
import java.net.URI;
30
import java.net.URL;
31
import java.nio.charset.StandardCharsets;
27
import java.io.Reader;
32 28
import java.util.ArrayList;
33
import java.util.HashMap;
34 29
import java.util.Iterator;
35 30
import java.util.List;
36
import java.util.Objects;
37 31
import org.apache.commons.io.FileUtils;
38

  
39 32
import org.apache.commons.io.FilenameUtils;
40
import org.apache.commons.io.IOUtils;
41
import org.apache.commons.lang3.StringUtils;
42
import org.cresques.cts.IProjection;
43
import org.gvsig.fmap.dal.DALLocator;
44
import org.gvsig.fmap.dal.DataManager;
45
import org.gvsig.fmap.dal.DataServerExplorer;
46 33
import org.gvsig.fmap.dal.DataStore;
47
import org.gvsig.fmap.dal.DataStoreNotification;
48
import org.gvsig.fmap.dal.DataTypes;
49 34
import org.gvsig.fmap.dal.FileHelper;
50
import org.gvsig.fmap.dal.exception.CloseException;
51 35
import org.gvsig.fmap.dal.exception.DataException;
52 36
import org.gvsig.fmap.dal.exception.InitializeException;
53
import org.gvsig.fmap.dal.exception.OpenException;
54
import org.gvsig.fmap.dal.exception.ReadException;
55
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
56
import org.gvsig.fmap.dal.feature.EditableFeatureType;
57
import org.gvsig.fmap.dal.feature.Feature;
58
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
59
import org.gvsig.fmap.dal.feature.FeatureQuery;
60 37
import org.gvsig.fmap.dal.feature.FeatureSet;
61
import org.gvsig.fmap.dal.feature.FeatureStore;
62 38
import org.gvsig.fmap.dal.feature.FeatureType;
63
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
64 39
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
65 40
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
66
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
67
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
68
import org.gvsig.fmap.dal.feature.spi.memory.AbstractMemoryStoreProvider;
69 41
import org.gvsig.fmap.dal.resource.ResourceAction;
70
import org.gvsig.fmap.dal.resource.file.FileResource;
71 42
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
72
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
73
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
74
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
75 43
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
76
import org.gvsig.fmap.dal.store.csv.simplereaders.AbstractSimpleReader;
77 44
import org.gvsig.fmap.dal.store.csv.simplereaders.CSVReaderSuperCSV;
78
import org.gvsig.fmap.dal.store.csv.simplereaders.SimpleReader;
79
import org.gvsig.fmap.geom.Geometry;
80
import org.gvsig.fmap.geom.GeometryLocator;
81
import org.gvsig.fmap.geom.GeometryManager;
82
import org.gvsig.fmap.geom.SpatialIndex;
83
import org.gvsig.fmap.geom.SpatialIndexFactory;
84
import org.gvsig.fmap.geom.primitive.Envelope;
85
import org.gvsig.fmap.geom.primitive.Point;
45
import org.gvsig.fmap.dal.store.csv.simplereaders.FixedLenReader;
46
import org.gvsig.fmap.dal.store.simplereader.SimpleReader;
47
import org.gvsig.fmap.dal.store.simplereader.SimpleReaderFeatureTypeLoader;
48
import org.gvsig.fmap.dal.store.simplereader.SimpleReaderStoreParameters;
49
import org.gvsig.fmap.dal.store.simplereader.SimpleReaderStoreProvider;
86 50
import org.gvsig.tools.ToolsLocator;
87
import org.gvsig.tools.dataTypes.Coercion;
88 51
import org.gvsig.tools.dispose.DisposableIterator;
89
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
90
import org.gvsig.tools.evaluator.AbstractEvaluator;
91
import org.gvsig.tools.evaluator.EvaluatorData;
92
import org.gvsig.tools.evaluator.EvaluatorException;
93
import org.gvsig.tools.exception.BaseException;
94
import org.gvsig.tools.exception.NotYetImplemented;
95
import org.gvsig.tools.persistence.PersistentState;
96
import org.gvsig.tools.persistence.exception.PersistenceException;
97
import org.gvsig.tools.task.SimpleTaskStatus;
98
import org.gvsig.tools.task.TaskStatusManager;
99
import org.gvsig.tools.visitor.VisitCanceledException;
100
import org.gvsig.tools.visitor.Visitor;
52
import org.gvsig.tools.i18n.I18nManager;
101 53
import org.slf4j.Logger;
102 54
import org.slf4j.LoggerFactory;
103 55
import org.supercsv.prefs.CsvPreference;
104
import org.gvsig.tools.dataTypes.CoercionContext;
105
import org.gvsig.tools.dispose.DisposeUtils;
106
import org.gvsig.tools.dynobject.DynObject;
107
import org.gvsig.tools.i18n.I18nManager;
108
import org.gvsig.tools.util.GetItemWithSize64;
109 56

  
110 57
@SuppressWarnings("UseSpecificCatch")
111
public class CSVStoreProvider extends AbstractMemoryStoreProvider implements
58
public class CSVStoreProvider extends SimpleReaderStoreProvider implements
112 59
        ResourceConsumer {
113 60

  
114 61
    private static final Logger LOGGER = LoggerFactory.getLogger(CSVStoreProvider.class);
......
118 65

  
119 66
    public static final String METADATA_DEFINITION_NAME = NAME;
120 67

  
121
    private final ResourceProvider resource;
68
    protected final CSVFeatureWriter writer;
122 69

  
123
    private long counterNewsOIDs = 0;
124
    private Envelope envelope;
125
    private boolean need_calculate_envelope = false;
126
    private final SimpleTaskStatus taskStatus;
127
    private final CSVFeatureWriter writer;
128
    private FeatureType featureType;
129
    private GetItemWithSize64<List<String>> virtualrows;
130
    private RowToFeatureTranslator rowToFeatureTranslator;
131
    private SpatialIndex spatialIndex;
132
    
133 70
    @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
134 71
    public CSVStoreProvider(
135 72
            CSVStoreParameters parameters,
......
141 78
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
142 79
        );
143 80
        this.writer = new CSVFeatureWriter();
144
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
145
        this.taskStatus = manager.createDefaultSimpleTaskStatus("CSV");
146
        this.taskStatus.setAutoremove(true);
147

  
148
        counterNewsOIDs = 0;
149

  
150
        File file = getCSVParameters().getFile();
151
        resource = this.createResource(
152
                FileResource.NAME,
153
                new Object[]{file.getAbsolutePath()}
154
        );
155

  
156
        resource.addConsumer(this);
157

  
158
        initializeFeatureTypes();
159 81
    }
160 82

  
161 83
    private CSVStoreParameters getCSVParameters() {
......
172 94
        return true;
173 95
    }
174 96

  
175
    private String getFullFileName() {
176
        // Usar solo para mostrar mensajes en el logger.
177
        String s;
178
        try {
179
            s = getCSVParameters().getFile().getAbsolutePath();
180
        } catch (Exception e2) {
181
            s = "(unknow)";
182
        }
183
        return s;
184
    }
185

  
186 97
    @Override
187
    public void open() throws OpenException {
188
        if (this.data != null) {
189
            return;
190
        }
191
        this.data = new ArrayList<>();
192
        resource.setData(new HashMap());
193
        counterNewsOIDs = 0;
194
        try {
195
            loadFeatures();
196
        } catch (RuntimeException e) {
197
            LOGGER.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
198
            throw e;
199
        } catch (Exception e) {
200
            LOGGER.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
201
            throw new RuntimeException(e);
202
        }
203
    }
204

  
205
    @Override
206
    public DataServerExplorer getExplorer() throws ReadException {
207
        DataManager manager = DALLocator.getDataManager();
208
        FilesystemServerExplorerParameters params;
209
        try {
210
            params = (FilesystemServerExplorerParameters) manager
211
                    .createServerExplorerParameters(FilesystemServerExplorer.NAME);
212
            params.setRoot(this.getCSVParameters().getFile().getParent());
213
            return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
214
        } catch (Exception e) {
215
            throw new ReadException(this.getProviderName(), e);
216
        }
217

  
218
    }
219

  
220
    @Override
221 98
    @SuppressWarnings("Convert2Lambda")
222 99
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
223 100

  
......
344 221
    }
345 222

  
346 223
    @Override
347
    public boolean closeResourceRequested(ResourceProvider resource) {
348
        return true;
349
    }
350

  
351
    @Override
352
    public int getOIDType() {
353
        return DataTypes.LONG;
354
    }
355

  
356
    @Override
357 224
    public boolean supportsAppendMode() {
358 225
        return true;
359 226
    }
......
418 285
        }
419 286
    }
420 287

  
421
    public void saveToState(PersistentState state) throws PersistenceException {
422
        throw new NotYetImplemented();
423
    }
424

  
425
    public void loadFromState(PersistentState state) throws PersistenceException {
426
        throw new NotYetImplemented();
427
    }
428

  
429
    @Override
430
    public Object createNewOID() {
431
        return counterNewsOIDs++;
432
    }
433

  
434
    protected void initializeFeatureTypes() throws InitializeException {
435
        try {
436
            this.open();
437
        } catch (OpenException e) {
438
            throw new InitializeException(this.getProviderName(), e);
439
        }
440
    }
441

  
442
    @Override
443
    @SuppressWarnings("Convert2Lambda")
444
    public Envelope getEnvelope() throws DataException {
445
        this.open();
446
        if (this.envelope != null) {
447
            return this.envelope;
448
        }
449
        this.envelope = bboxFileLoad();
450
        if (this.envelope != null) {
451
            return this.envelope;
452
        }
453
        if (!this.need_calculate_envelope) {
454
            return null;
455
        }
456
        try {
457
            I18nManager i18n = ToolsLocator.getI18nManager();
458
            this.taskStatus.add();
459
            this.taskStatus.message(i18n.getTranslation("_Calculating_envelope"));
460
            FeatureStore fs = this.getFeatureStore();
461
            FeatureType ft = fs.getDefaultFeatureType();
462
            FeatureAttributeDescriptor fad = ft.getAttributeDescriptor(ft.getDefaultGeometryAttributeIndex());
463
            this.taskStatus.setRangeOfValues(0, fs.getFeatureCount());
464
            this.envelope = GeometryLocator.getGeometryManager().createEnvelope(fad.getGeomType().getSubType());
465
            fs.accept(new Visitor() {
466
                @Override
467
                public void visit(Object obj) throws VisitCanceledException, BaseException {
468
                    taskStatus.incrementCurrentValue();
469
                    if(taskStatus.isCancellationRequested()){
470
                        taskStatus.cancel();
471
                        throw new VisitCanceledException();
472
                    }
473
                    Feature f = (Feature) obj;
474
                    Geometry geom = f.getDefaultGeometry();
475
                    if (geom != null) {
476
                        try {
477
                            Envelope env = geom.getEnvelope();
478
                            envelope.add(env);
479
                        } catch(Exception ex) {
480
                            LOGGER.warn("Can't calculate envelop of geometry in feature '"+Objects.toString(f.getReference())+"'.",ex);
481
                        }
482
                    }
483
                }
484
            });
485
            bboxFileSave(envelope);
486
            taskStatus.terminate();
487
        } catch (VisitCanceledException e) {
488
            return null;
489
        } catch (BaseException e) {
490
            taskStatus.abort();
491
            LOGGER.warn("Can't calculate the envelope of CSV file '" + this.getFullName() + "'.", e);
492
            return null;
493
        }
494

  
495
        this.need_calculate_envelope = false;
496
        return this.envelope;
497
    }
498

  
499
    @Override
500
    public Object getDynValue(String name) throws DynFieldNotFoundException {
501
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
502
            try {
503
                return this.getEnvelope();
504
            } catch (DataException e) {
505
                return null;
506
            }
288
    protected SimpleReader getSimpleReader(SimpleReaderStoreParameters parameters, Reader in) throws IOException {
289
        SimpleReader reader;
290
        if (CSVStoreParameters.getRawFieldsDefinition(parameters) != null) {
291
            reader = new FixedLenReader(in, (CSVStoreParameters) parameters);
507 292
        } else {
508
            if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
509
                IProjection pro = CSVStoreParameters.getCRS(this.getCSVParameters());
510
                if (pro != null) {
511
                    return pro;
512
                }
513
            }
293
            reader = new CSVReaderSuperCSV(in, (CSVStoreParameters) parameters);
514 294
        }
515
        return super.getDynValue(name);
295
        return reader;
516 296
    }
517 297

  
518 298
    @Override
519
    public void resourceChanged(ResourceProvider resource) {
520
        this.getStoreServices().notifyChange(
521
                DataStoreNotification.RESOURCE_CHANGED,
522
                resource);
299
    protected SimpleReaderFeatureTypeLoader getFeatureTypeLoader() {
300
        return new CSVFeatureTypeLoader(getCSVParameters());
523 301
    }
524 302

  
525
    @Override
526
    public Object getSourceId() {
527
        return this.getCSVParameters().getFile();
528
    }
529

  
530
    @Override
531
    public String getName() {
532
        String name = this.getCSVParameters().getFile().getName();
533
        return FilenameUtils.getBaseName(name);
534
    }
535

  
536
    @Override
537
    public String getFullName() {
538
        return this.getCSVParameters().getFile().getAbsolutePath();
539
    }
540

  
541
    @Override
542
    public ResourceProvider getResource() {
543
        return resource;
544
    }
545

  
546
    private boolean isEmpty(String s) {
547
        if (s == null) {
548
            return true;
549
        }
550
        return s.trim().length() == 0;
551
    }
552

  
553
    private void init(CSVStoreParameters parameters, DataStoreProviderServices storeServices) {
554
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
555
    }
556

  
557
    static class ToPointEvaluaror extends AbstractEvaluator {
558

  
559
        private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
560

  
561
        private GeometryManager geommgr = null;
562
        private String xname = null;
563
        private String yname = null;
564
        private String zname = null;
565
        private final Coercion toDouble;
566
        private int errorcount = 0;
567

  
568
        ToPointEvaluaror(String[] pointDimensionNames) {
569
            this.xname = pointDimensionNames[0];
570
            this.yname = pointDimensionNames[1];
571
            if (pointDimensionNames.length > 2) {
572
                this.zname = pointDimensionNames[2];
573
            }
574
            this.geommgr = GeometryLocator.getGeometryManager();
575
            this.toDouble = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.DOUBLE);
576
        }
577

  
578
        @Override
579
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
580
            try {
581
                double x = ((Double) toDouble.coerce(data.getDataValue(xname)));
582
                double y = ((Double) toDouble.coerce(data.getDataValue(yname)));
583
                Point point = geommgr.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
584
                if (zname != null) {
585
                    double z = ((Double) toDouble.coerce(data.getDataValue(zname)));
586
                    point.setCoordinateAt(2, z);
587
                }
588
                return point;
589
            } catch (Exception ex) {
590
                if (++errorcount < 5) {
591
                    logger.warn("[" + errorcount + "] Can't create point in CSV provider. XNAME='"
592
                            + xname + "', YNAME='" + yname + "', ZNAME='" + zname + "', data=" + data.toString());
593
                }
594
                return null;
595
            }
596
        }
597

  
598
        @Override
599
        public String getName() {
600
            return "ToPointEvaluaror";
601
        }
602

  
603
    }
604

  
605
    public static class RowToFeatureTranslator {
606

  
607
        private Coercion coercion[];
608
        private CoercionContext coercionContext[];
609
        private int sizes[];
610
        private String[] names;
611
        private final boolean ignore_errors;
612
        private long count_errors;
613
        private FeatureType csvFeatureType;
614

  
615
        public RowToFeatureTranslator(boolean ignore_errors) {
616
            this.ignore_errors = ignore_errors;
617
            this.count_errors = 0;
618
        }
619

  
620
        public int getColumnSize(int column) {
621
            return this.sizes[column];
622
        }
623

  
624
        public void initialize(FeatureType ftype) {
625
            this.csvFeatureType = ftype;
626
            int columns = this.csvFeatureType.size();
627
            this.names = new String[columns];
628
            this.coercion = new Coercion[columns];
629
            this.coercionContext = new CoercionContext[columns];
630
            this.sizes = new int[columns];
631
            int index = 0;
632
            for (int i = 0; i < this.csvFeatureType.size(); i++) {
633
                FeatureAttributeDescriptor ad = this.csvFeatureType.getAttributeDescriptor(i);
634
                names[i] = null;
635
                if( ad.isComputed() ) {
636
                    continue;
637
                }
638
                names[index] = ad.getName();
639
                coercion[index] = ad.getCoercion();
640
                coercionContext[index] = ad.getCoercionContext();
641
                sizes[index] = ad.getSize();
642
                index++;
643
            }
644
        }
645

  
646
        public void translate(long rowindex, List<String> row, FeatureProvider feature) throws Exception {
647

  
648
            feature.setOID(rowindex);
649
            for (int i = 0; i < names.length; i++) {
650
                String name = names[i];
651
                if( name == null ) {
652
                    break;
653
                }
654
                Object rawvalue = row.get(i);
655
                try {
656
                    Object value = null;
657
                    if (coercion[i] != null) {
658
                        value = coercion[i].coerce(rawvalue, coercionContext[i]);
659
                    }
660
                    int findex = feature.getType().getIndex(name);
661
                    if( findex>=0 ) {
662
                        // Ojo que puede que se este filtrando el featuretype y no 
663
                        // tenga todos los atributos, por ejemplo al pintar la vista.
664
                        feature.set(findex, value);
665
                    }
666
                    if (sizes[i] >= 0
667
                            && (value instanceof String || value instanceof URL
668
                            || value instanceof URI || value instanceof File)) {
669
                        int x = value.toString().length();
670
                        if (sizes[i] < x) {
671
                            sizes[i] = x;
672
                        }
673
                    }
674
                } catch (Exception ex) {
675
                    if (!ignore_errors) {
676
                        throw ex;
677
                    }
678
                    if (count_errors++ < 10) {
679
                        LOGGER.warn("Can't load value of attribute " + name +"/" +i+" in row " + rowindex + ".", ex);
680
                    }
681
                    if (count_errors == 10) {
682
                        LOGGER.info("Too many errors, suppress messages.");
683
                    }
684
                }
685
            }
686
        }
687
    }
688

  
689
    private void loadFeatures() {
690
        InputStreamReader in = null;
691
        SimpleReader reader = null;
692
        try {
693
            taskStatus.setTitle("CSV "+this.getName());
694
            taskStatus.add();
695
//            boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
696

  
697
            // Initialize the feature types
698
            EditableFeatureType edftype = getStoreServices().createFeatureType(this.getName());
699
            CSVUtils.loadFeatureType(getCSVParameters(), edftype, true, taskStatus);
700
            FeatureType ftype = edftype.getNotEditableCopy();
701
            this.setFeatureType(ftype);
702

  
703
            in = CSVUtils.openFile(
704
                    this.getCSVParameters().getFile(),
705
                    CSVStoreParameters.getCharset(this.getCSVParameters())
706
            );
707
            reader = CSVUtils.getSimpleReader(getCSVParameters(), in);
708
            if (CSVStoreParameters.isFirstLineHeader(getCSVParameters())) {
709
                reader.getHeader(); // Skip and ignore the header of file
710
            }
711
            this.rowToFeatureTranslator = new RowToFeatureTranslator(
712
                    CSVStoreParameters.getIgnoreErrors(getCSVParameters())
713
            );
714
            this.rowToFeatureTranslator.initialize(ftype);
715
            if (ftype.getDefaultGeometryAttributeName() != null) {
716
                this.need_calculate_envelope = true;
717
            }
718
            I18nManager i18n = ToolsLocator.getI18nManager();
719
            taskStatus.message(i18n.getTranslation("_Loading"));
720

  
721
            if(this.virtualrows != null && this.virtualrows instanceof Closeable){
722
                IOUtils.closeQuietly((Closeable) this.virtualrows);
723
                this.virtualrows = null;
724
            }
725
            
726
            this.virtualrows = ((AbstractSimpleReader) reader).getVirtualRows(this.taskStatus);
727
            if (this.virtualrows == null) {
728

  
729
                List<String> row = reader.read();
730

  
731
                int skipLines = CSVStoreParameters.getSkipLines(getCSVParameters());
732
                if (skipLines > 0) {
733
                    row = reader.skip(skipLines);
734
                }
735
                int limit = CSVStoreParameters.getLimit(getCSVParameters());
736
                while (row != null) {
737
                    taskStatus.incrementCurrentValue();
738
                    if( taskStatus.isCancellationRequested() ) {
739
                        taskStatus.cancel();
740
                        break;
741
                    }
742
                    FeatureProvider feature = this.createFeatureProvider(ftype);
743
                    this.rowToFeatureTranslator.translate(reader.getLine(), row, feature);
744

  
745
                    this.addFeatureProvider(feature);
746
                    if (limit > 0) {
747
                        if (limit < this.data.size()) {
748
                            break;
749
                        }
750
                    }
751
                    row = reader.read();
752
                }
753
                for (int i = 0; i < ftype.size(); i++) {
754
                    if (this.rowToFeatureTranslator.getColumnSize(i) > 0) {
755
//                    if (sizes[i] > 0) {
756
                        EditableFeatureAttributeDescriptor efad = ((EditableFeatureAttributeDescriptor) edftype.getAttributeDescriptor(i));
757
//                        efad.setSize(sizes[i]);
758
                        efad.setSize(this.rowToFeatureTranslator.getColumnSize(i));
759
                    }
760
                }
761
                // Volvemos a asignar al store el featuretype, ya que puede
762
                // haber cambiado.
763
                ftype = edftype.getNotEditableCopy();
764
                this.setFeatureType(ftype);
765
            } else {
766
                this.loadOrCreateSpatialIndex();
767
            }
768
            if( taskStatus.isRunning() ) {
769
                taskStatus.terminate();
770
            }
771
        } catch (Throwable ex) {
772
            taskStatus.abort();
773
            int lineno = 0;
774
            if (reader != null) {
775
                lineno = reader.getLine();
776
            }
777
            throw new RuntimeException("Problems reading file '" + getFullFileName() + "' near line " + lineno + ".", ex);
778

  
779
        } finally {
780
            if (reader != null) {
781
                try {
782
                    reader.close();
783
                } catch (Exception ex) {
784
                    // Do nothing
785
                }
786
//                reader = null;
787
            }
788
            if (in != null) {
789
                try {
790
                    in.close();
791
                } catch (Exception ex) {
792
                    // Do nothing
793
                }
794
//                in = null;
795
            }
796
            taskStatus.remove();
797
        }
798
    }
799

  
800
    @Override
801
    public void fixFeatureTypeFromParameters() {
802
        if(mustFixFeatureType() && featureType != null){
803
            this.setFeatureType(featureType);
804
        }
805
    }
806
    
807
    private boolean mustFixFeatureType() {
808
        try {
809
            String param_types_def = CSVStoreParameters.getRawFieldTypes(this.getParameters());
810
            String[] pointDimensionNames = CSVStoreParameters.getPointDimensionNames(this.getParameters());
811
            String geometry_column = CSVStoreParameters.getGeometryColumn(this.getParameters());
812
            
813
            
814
            FeatureType dalFeatureType = this.getStoreServices().getDefaultFeatureType();
815
            if (StringUtils.isNotBlank(geometry_column)){
816
                FeatureAttributeDescriptor attr = dalFeatureType.getAttributeDescriptor(geometry_column);
817
                if(attr == null || attr.getType() !=  DataTypes.GEOMETRY){
818
                    return true;
819
                }
820
            }
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff