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

History | View | Annotate | Download (31.3 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
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.io.File;
27
import java.io.FileReader;
28
import java.io.FileWriter;
29
import java.io.IOException;
30
import java.net.URL;
31
import java.text.SimpleDateFormat;
32
import java.util.ArrayList;
33
import java.util.HashMap;
34
import java.util.Iterator;
35
import java.util.List;
36

    
37
import org.apache.commons.io.FilenameUtils;
38
import org.cresques.cts.IProjection;
39
import org.gvsig.fmap.dal.DALLocator;
40
import org.gvsig.fmap.dal.DataManager;
41
import org.gvsig.fmap.dal.DataServerExplorer;
42
import org.gvsig.fmap.dal.DataStore;
43
import org.gvsig.fmap.dal.DataStoreNotification;
44
import org.gvsig.fmap.dal.DataTypes;
45
import org.gvsig.fmap.dal.FileHelper;
46
import org.gvsig.fmap.dal.exception.DataException;
47
import org.gvsig.fmap.dal.exception.InitializeException;
48
import org.gvsig.fmap.dal.exception.OpenException;
49
import org.gvsig.fmap.dal.exception.ReadException;
50
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
51
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
52
import org.gvsig.fmap.dal.feature.EditableFeatureType;
53
import org.gvsig.fmap.dal.feature.Feature;
54
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
55
import org.gvsig.fmap.dal.feature.FeatureSet;
56
import org.gvsig.fmap.dal.feature.FeatureStore;
57
import org.gvsig.fmap.dal.feature.FeatureType;
58
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
59
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
60
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
61
import org.gvsig.fmap.dal.feature.spi.memory.AbstractMemoryStoreProvider;
62
import org.gvsig.fmap.dal.resource.ResourceAction;
63
import org.gvsig.fmap.dal.resource.file.FileResource;
64
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
65
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
66
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
67
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
68
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
69
import org.gvsig.fmap.geom.Geometry;
70
import org.gvsig.fmap.geom.GeometryLocator;
71
import org.gvsig.fmap.geom.GeometryManager;
72
import org.gvsig.fmap.geom.primitive.Envelope;
73
import org.gvsig.fmap.geom.primitive.Point;
74
import org.gvsig.fmap.geom.type.GeometryType;
75
import org.gvsig.tools.ToolsLocator;
76
import org.gvsig.tools.dataTypes.CoercionException;
77
import org.gvsig.tools.dataTypes.DataTypesManager;
78
import org.gvsig.tools.dataTypes.DataTypesManager.Coercion;
79
import org.gvsig.tools.dispose.DisposableIterator;
80
import org.gvsig.tools.dynobject.DynObject;
81
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
82
import org.gvsig.tools.evaluator.AbstractEvaluator;
83
import org.gvsig.tools.evaluator.EvaluatorData;
84
import org.gvsig.tools.evaluator.EvaluatorException;
85
import org.gvsig.tools.exception.BaseException;
86
import org.gvsig.tools.exception.NotYetImplemented;
87
import org.gvsig.tools.persistence.PersistentState;
88
import org.gvsig.tools.persistence.exception.PersistenceException;
89
import org.gvsig.tools.task.SimpleTaskStatus;
90
import org.gvsig.tools.task.TaskStatusManager;
91
import org.gvsig.tools.visitor.VisitCanceledException;
92
import org.gvsig.tools.visitor.Visitor;
93
import org.slf4j.Logger;
94
import org.slf4j.LoggerFactory;
95
import org.supercsv.comment.CommentStartsWith;
96
import org.supercsv.io.CsvListReader;
97
import org.supercsv.io.CsvListWriter;
98
import org.supercsv.prefs.CsvPreference;
99
import org.supercsv.quote.QuoteMode;
100

    
101
public class CSVStoreProvider extends AbstractMemoryStoreProvider implements
102
ResourceConsumer {
103
    private static final Logger logger = LoggerFactory.getLogger(CSVStoreProvider.class);
104

    
105
    public static final String NAME = "CSV";
106
    public static final String DESCRIPTION = "CSV file";
107

    
108
    public static final String METADATA_DEFINITION_NAME = NAME;
109

    
110
    private ResourceProvider resource;
111

    
112
    private long counterNewsOIDs = 0;
113
    private Envelope envelope;
114
    private boolean need_calculate_envelope = false;
115
    private SimpleTaskStatus taskStatus;
116

    
117

    
118
    public CSVStoreProvider(CSVStoreParameters parameters,
119
        DataStoreProviderServices storeServices) throws InitializeException {
120
        super(
121
            parameters, 
122
            storeServices,
123
            FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
124
        );
125

    
126
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
127
        this.taskStatus = manager.createDefaultSimpleTaskStatus("CSV");
128

    
129
        counterNewsOIDs = 0;
130

    
131
        File file = getCSVParameters().getFile();
132
        resource = this.createResource(
133
            FileResource.NAME,
134
            new Object[] { file.getAbsolutePath() }
135
        );
136

    
137
        resource.addConsumer(this);
138
        initializeFeatureTypes();
139
    }
140

    
141
    private CSVStoreParameters getCSVParameters() {
142
        return (CSVStoreParameters) this.getParameters();
143
    }
144

    
145
    public String getProviderName() {
146
        return NAME;
147
    }
148

    
149
    public boolean allowWrite() {
150
        return true;
151
    }
152

    
153
    private String getFullFileName() {
154
            // Usar solo para mostrar mensajes en el logger.
155
                String s = "(unknow)";
156
                try { 
157
                        s = getCSVParameters().getFile().getAbsolutePath();
158
                } catch(Exception e2) {
159
                        s = "(unknow)";
160
                }
161
                return s;
162
    }
163
    
164
    public void open() throws OpenException {
165
        if (this.data != null) {
166
            return;
167
        }
168
        this.data = new ArrayList<FeatureProvider>();
169
        resource.setData(new HashMap());
170
        counterNewsOIDs = 0;
171
                try {
172
                        loadFeatures();
173
                } catch (RuntimeException e) {
174
                        logger.warn("Can't load features from CSV '"+getFullFileName()+"'.", e);
175
                        throw e;
176
                } catch (Exception e) {
177
                        logger.warn("Can't load features from CSV '"+getFullFileName()+"'.", e);
178
                        throw new RuntimeException(e);
179
                }
180
    }
181

    
182
    public DataServerExplorer getExplorer() throws ReadException {
183
        DataManager manager = DALLocator.getDataManager();
184
        FilesystemServerExplorerParameters params;
185
        try {
186
            params = (FilesystemServerExplorerParameters) manager
187
            .createServerExplorerParameters(FilesystemServerExplorer.NAME);
188
            params.setRoot(this.getCSVParameters().getFile().getParent());
189
            return manager.openServerExplorer(FilesystemServerExplorer.NAME,params);
190
        } catch (DataException e) {
191
            throw new ReadException(this.getProviderName(), e);
192
        } catch (ValidateDataParametersException e) {
193
            throw new ReadException(this.getProviderName(), e);
194
        }
195

    
196
    }
197

    
198
    class Writer {
199
            private Envelope envelope = null;
200
                private boolean calculate_envelope = false;
201
                private CsvListWriter listWriter = null;
202
                private CsvPreference csvpreferences = null;
203
                private FileWriter fwriter = null;
204
                private FeatureType ftype;
205
                private File file;
206
                private String[] values;
207
                private FeatureAttributeDescriptor[] descriptors;
208
                private Coercion convert = null;
209
                private int errorcounts =0;
210
                private Throwable lasterror = null;
211
            
212
            public void initialize(File file, FeatureType ftype, CsvPreference csvpreferences) {
213
                    this.file = file;
214
                    this.ftype = ftype;
215
                        this.csvpreferences = csvpreferences;
216
                    if( csvpreferences == null ) {
217
                            this.csvpreferences = CsvPreference.STANDARD_PREFERENCE;
218
                    }
219
                    if( ftype.getDefaultGeometryAttributeName() != null ) {
220
                            this.calculate_envelope = true;
221
                    }
222
                    this.descriptors = this.ftype.getAttributeDescriptors();
223
                    this.convert = ToolsLocator.getDataTypesManager().getCoercion(org.gvsig.tools.dataTypes.DataTypes.STRING);
224
                    this.errorcounts = 0;
225
            }
226
            
227
            public void begin() {
228
                    try {
229
                                this.fwriter = new FileWriter(file);
230
                        } catch (IOException e) {
231
                                logger.warn("Can't open file for write ("+file.getAbsolutePath()+").",e);
232
                                throw new RuntimeException(e);
233
                        }
234
                    this.listWriter = new CsvListWriter(this.fwriter,this.csvpreferences);
235
                    int n = 0;
236
                    for(int i=0; i<descriptors.length; i++ ) {
237
                            FeatureAttributeDescriptor descriptor = descriptors[i];
238
                            if( descriptor.getEvaluator()== null ) {
239
                                    n++;
240
                            }
241
                    }
242
                            
243
                    String[] header = new String[n];
244
                    this.values = new String[n];
245
                    n = 0;
246
                    for(int i=0; i<descriptors.length; i++ ) {
247
                            FeatureAttributeDescriptor descriptor = descriptors[i];
248
                            if( descriptor.getEvaluator()== null ) {
249
                                    String name = descriptor.getName();
250
                                    String type = descriptor.getDataTypeName();
251
                                    header[n++] = name + "__" + type;
252
                            }
253
                    }
254
            try {
255
                                listWriter.writeHeader(header);
256
                        } catch (Exception e) {
257
                                logger.warn("Can't write header '"+header.toString()+"' file for write ("+file.getAbsolutePath()+").",e);
258
                                throw new RuntimeException(e);
259
                        }
260
            }
261
            
262
            public void add(FeatureProvider feature) {
263
                        if (this.calculate_envelope) {
264
                                Geometry geom = feature.getDefaultGeometry();
265
                                if (geom != null) {
266
                                        if (envelope == null) {
267
                                                try {
268
                                                        envelope = (Envelope) geom.getEnvelope().clone();
269
                                                } catch (CloneNotSupportedException e) {
270
                                                        logger.warn("Este error no deberia pasar, siempre se puede hacer un clone de un envelope.",e);
271
                                                }
272
                                        } else {
273
                                                envelope.add(geom.getEnvelope());
274
                                        }
275
                                }
276
                        }
277
                    int n = 0;
278
                    for(int i=0; i<descriptors.length; i++ ) {
279
                            FeatureAttributeDescriptor descriptor = descriptors[i];
280
                            if( descriptor.getEvaluator()== null ) {
281
                                        Object value = feature.get(i);
282
                                    try {
283
                                            n++;
284
                                                values[n] = (String) this.convert.coerce(value);
285
                                        } catch (CoercionException e) {
286
                                                try {
287
                                                        values[n] = value.toString();
288
                                                } catch(Exception ex) {
289
                                                        values[n] = "";
290
                                                }
291
                                                if( errorcounts++ <= 10 ) {
292
                                                        this.lasterror = e;
293
                                                        logger.warn("Can't convert value of field "+i+" to string in CVS file '"+getFullFileName()+"'.",e);
294
                                                        if( errorcounts == 10 ) {
295
                                                                logger.warn("Too many error writing CVS file '"+getFullFileName()+"', don't output more.");
296
                                                        }
297
                                                } 
298
                                        } 
299
                            }
300
                    }
301
                    try {
302
                                this.listWriter.writeHeader(values);
303
                        } catch (IOException e) {
304
                                if( errorcounts++ <= 10 ) {
305
                                        this.lasterror = e;
306
                                        logger.warn("Can't write values to CVS file '"+getFullFileName()+"'.",e);
307
                                        if( errorcounts == 10 ) {
308
                                                logger.warn("Too many error writing CVS file '"+getFullFileName()+"', don't output more.");
309
                                        }
310
                                } 
311
                        }
312
                        
313
            }
314
            
315
            public void end() throws PerformEditingException {
316
                    if( this.errorcounts>0 ) {
317
                            throw new PerformEditingException(this.file.getAbsolutePath(), lasterror);
318
                    }
319
                        if( listWriter!=null ) {
320
                            try {
321
                                    listWriter.close();
322
                            } catch(Exception ex) {
323
                                    // Ignore error
324
                            }
325
                                listWriter=null ;
326
                        }
327
                        if( fwriter!=null ) {
328
                            try {
329
                                    fwriter.close();
330
                            } catch(Exception ex) {
331
                                    // Ignore error
332
                            }
333
                                fwriter=null ;
334
                        }
335
            }
336
            
337
            public Envelope getEnvelope() {
338
                    return this.envelope;
339
            }
340
    }
341

    
342
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
343

    
344
        try {
345
            this.taskStatus.add();
346
            taskStatus.message("_preparing");
347
            getResource().execute(new ResourceAction() {
348
                public Object run() throws Exception {
349
                    FeatureSet features = null;
350
                    DisposableIterator it = null;
351
                    try {
352
                        File file = (File) resource.get();
353
                        
354
                        Writer writer = new Writer();
355
                        writer.initialize(file,getStoreServices().getDefaultFeatureType(),null);
356
                        features =
357
                            getStoreServices().getFeatureStore()
358
                            .getFeatureSet();
359
                        List<FeatureProvider> newdata = new ArrayList<FeatureProvider>();
360
                        writer.begin();
361
                        it = features.fastIterator();
362
                        taskStatus.setRangeOfValues(0,0);
363
                        long counter=0;
364
                        while (it.hasNext()) {
365
                            taskStatus.setCurValue(counter++);
366
                            FeatureProvider feature = getStoreServices().getFeatureProviderFromFeature(
367
                                (org.gvsig.fmap.dal.feature.Feature) it.next());
368
                            writer.add(feature);
369
                            if (feature.getOID() == null){
370
                                logger.warn("feature without OID");
371
                                feature.setOID(createNewOID());
372
                            }
373
                            newdata.add(feature);
374
                        }
375
                        data = newdata;
376
                        if (writer.getEnvelope() != null){
377
                            envelope = writer.getEnvelope().getGeometry().getEnvelope();
378
                        }
379
                        resource.notifyChanges();
380
                        writer.end();
381
                    } finally {
382
                        if (it != null) {
383
                            it.dispose();
384
                        }
385
                        if (features != null) {
386
                            features.dispose();
387
                        }
388
                    }
389
                    return null;
390
                }
391
            });
392
            this.taskStatus.terminate();
393
        } catch (Exception e) {
394
            this.taskStatus.abort();
395
            throw new PerformEditingException(getResource().toString(), e);
396
        } finally {
397
            this.taskStatus.remove();
398
        }
399
    }
400

    
401
    public boolean closeResourceRequested(ResourceProvider resource) {
402
        return true;
403
    }
404

    
405
    public int getOIDType() {
406
        return DataTypes.LONG;
407
    }
408

    
409
    public boolean supportsAppendMode() {
410
        return false;
411
    }
412

    
413
    public void append(FeatureProvider featureProvider) {
414
            throw new UnsupportedOperationException();
415
    }
416

    
417
    public void beginAppend() {
418
            throw new UnsupportedOperationException();
419
    }
420

    
421
    public void endAppend() {
422
            throw new UnsupportedOperationException();
423
    }
424

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

    
429
    public void loadFromState(PersistentState state) throws PersistenceException {
430
        throw new NotYetImplemented();
431
    }
432

    
433
    public Object createNewOID() {
434
        return new Long(counterNewsOIDs++);
435
    }
436

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

    
445
    public Envelope getEnvelope() throws DataException {
446
        this.open();
447
        if( this.envelope!= null )  {
448
                return this.envelope;
449
        }
450
        if( !this.need_calculate_envelope ) {
451
                return null;
452
        }
453
        FeatureStore fs = this.getFeatureStore();
454
        FeatureType ft = fs.getDefaultFeatureType();
455
        FeatureAttributeDescriptor fad = ft.getAttributeDescriptor(ft.getDefaultGeometryAttributeIndex());
456

    
457
        try {
458
            this.envelope = GeometryLocator.getGeometryManager().createEnvelope(fad.getGeomType().getSubType());
459
                        fs.accept(new Visitor() {
460
                                public void visit(Object obj) throws VisitCanceledException, BaseException {
461
                                        Feature f = (Feature) obj;
462
                                        Geometry geom = f.getDefaultGeometry();
463
                                        envelope.add(geom.getEnvelope());
464
                                }
465
                        });
466
                } catch (BaseException e) {
467
                        logger.warn("Can't calculate the envelope of CSV file '"+this.getFullName()+"'.",e);
468
                        this.envelope = null;
469
                }
470
        
471
        this.need_calculate_envelope = false;
472
        return this.envelope;
473
    }
474

    
475
    public Object getDynValue(String name) throws DynFieldNotFoundException {
476
        if( DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name) ) {
477
            try {
478
                return this.getEnvelope();
479
            } catch (DataException e) {
480
                return null;
481
            }
482
        } else {
483
            if( DataStore.METADATA_CRS.equalsIgnoreCase(name) ) {
484
                IProjection pro = CSVStoreParameters.getCRS(this.getCSVParameters());
485
                if (pro != null){
486
                    return pro;
487
                }
488
            }
489
        }
490
        return super.getDynValue(name);
491
    }
492

    
493

    
494
    public void resourceChanged(ResourceProvider resource) {
495
        this.getStoreServices().notifyChange(
496
            DataStoreNotification.RESOURCE_CHANGED,
497
            resource);
498
    }
499

    
500

    
501
    public Object getSourceId() {
502
        return this.getCSVParameters().getFile();
503
    }
504

    
505
    public String getName() {
506
        String name = this.getCSVParameters().getFile().getName();
507
        return FilenameUtils.getBaseName(name);
508
    }
509

    
510
    public String getFullName() {
511
        return this.getCSVParameters().getFile().getAbsolutePath();
512
    }
513

    
514
    public ResourceProvider getResource() {
515
        return resource;
516
    }
517

    
518
    private boolean isEmpty(String s) {
519
            if( s==null ) {
520
                    return true;
521
            }
522
            return s.trim().length()==0;
523
    }
524
    
525
        private CsvPreference getCSVPreferences() {
526
                try {
527
                        String s = null;
528
                        char quoteChar;
529
                        int delimiterChar;
530
                        String endOfLineSymbols;
531

    
532
                        DynObject params = this.getParameters();
533

    
534
                        CsvPreference.Builder builder = null;
535

    
536
                        CsvPreference defaultPreference = CSVStoreParameters
537
                                        .getPredefinedCSVPreferences(params);
538
                        if (defaultPreference == null) {
539
                                defaultPreference = CsvPreference.STANDARD_PREFERENCE;
540
                        }
541

    
542
                        endOfLineSymbols = CSVStoreParameters.getRecordSeparator(params);
543
                        if (isEmpty(endOfLineSymbols)) {
544
                                endOfLineSymbols = defaultPreference.getEndOfLineSymbols();
545
                        }
546
                        s = CSVStoreParameters.getQuoteCharacter(params);
547
                        if (isEmpty(s)) {
548
                                quoteChar = (char) defaultPreference.getQuoteChar();
549
                        } else {
550
                                quoteChar = s.charAt(0);
551
                        }
552
                        s = CSVStoreParameters.getDelimiter(params);
553
                        if (isEmpty(s)) {
554
                                delimiterChar = defaultPreference.getDelimiterChar();
555
                        } else {
556
                                delimiterChar = s.charAt(0);
557
                        }
558

    
559
                        builder = new CsvPreference.Builder(quoteChar, delimiterChar,
560
                                        endOfLineSymbols);
561

    
562
                        s = CSVStoreParameters.getCommentStartMarker(params);
563
                        if (!isEmpty(s)) {
564
                                CommentStartsWith cs = new CommentStartsWith(s);
565
                                builder.skipComments(cs);
566
                        }
567

    
568
                        builder.surroundingSpacesNeedQuotes(CSVStoreParameters
569
                                        .getSurroundingSpacesNeedQuotes(params));
570
                        QuoteMode quoteMode = CSVStoreParameters.getQuoteMode(params);
571
                        if( quoteMode != null ) {
572
                                builder.useQuoteMode(quoteMode);
573
                        }
574
                        return builder.build();
575
                } catch (Exception e) {
576
                        logger.warn("Can't make preferences for CSV '" + getFullFileName()
577
                                        + "'.", e);
578
                        return null;
579
                }
580
        }
581
    
582
    private EditableFeatureType getFeatureType(String headers[], int automaticTypes[]) {
583
                EditableFeatureType fType =        getStoreServices().createFeatureType(this.getName());
584
                fType.setHasOID(true);
585
                DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
586
                
587
            int[] types = new int[headers.length];
588
            //
589
            // Calculamos cuales pueden ser los tipos de datos
590
            //
591
            
592
            // Por defecto todos string
593
            for( int i=0; i<types.length ; i++) {
594
                    types[i] = DataTypes.STRING;
595
            }
596
            
597
            // Luego asuminos los tipos pasados por parametro, que se supone
598
            // son los detectados automaticamente.
599
                if (automaticTypes != null) {
600
                        for (int i = 0; i < types.length && i < automaticTypes.length; i++) {
601
                                types[i] = automaticTypes[i];
602
                        }
603
                }
604
            
605
            // Luego probamos con lo que diga las cabezeras del CVS, sobreescribiendo
606
            // los tipos anteriores en caso de definirse en la cabezara.
607
            for( int i=0; i<types.length; i++) {
608
                    String s = headers[i];
609
                    String typename = null;
610
                    if( s.contains(":") ) {
611
                            String[] ss = s.split(":");
612
                            headers[i] = ss[0];
613
                            typename = ss[1];
614
                            types[i] = dataTypesManager.getType(typename); 
615
                    } else if( s.contains("__") ) {
616
                                String[] ss = s.split("__");
617
                                headers[i] = ss[0];
618
                                typename = ss[1];
619
                                types[i] = dataTypesManager.getType(typename); 
620
                    }
621
                        if( types[i]==DataTypes.INVALID ) {
622
                                types[i] = DataTypes.STRING;
623
                                logger.info("Type '"+typename+"' not valid for attribute '"+headers[i]+"' in CSV file '"+this.getFullFileName()+"'.");
624
                        }
625
            }
626
            
627
            // Y por ultimo hacemos caso a lo que se haya especificado en los parametros
628
            // de apertura del CSV, teniendo esto prioridad sobre todo.
629
            int[] param_types = CSVStoreParameters.getFieldTypes(this.getParameters());
630
            if( param_types != null ) {
631
                for( int i=0; i<types.length && i<param_types.length; i++) {
632
                        types[i] = param_types[i];
633
                }
634
            }
635
            
636
            //
637
            // Una vez ya sabemos los tipos de datos rellenamos el feature-type
638
            //
639
            int[] param_sizes = CSVStoreParameters.getFieldSizes(this.getParameters());
640
            for(int i=0; i<types.length; i++) {
641
                        int fieldType = types[i];
642
                        String fieldName = headers[i];
643
                        EditableFeatureAttributeDescriptor fad = fType.add(fieldName, fieldType);
644
                        if( param_sizes!=null && param_sizes[i]>0 ) {
645
                                fad.setSize(param_sizes[i]);
646
                        }
647
                        if( fieldType == DataTypes.GEOMETRY && fType.getDefaultGeometryAttributeName() == null) {
648
                                fType.setDefaultGeometryAttributeName(fieldName);
649
                        }
650
                }
651
            String[] pointDimensionNames = CSVStoreParameters.getPointDimensionNames(this.getParameters());
652
            if( pointDimensionNames!= null ) {
653
                    EditableFeatureAttributeDescriptor attr = fType.add("GEOM", DataTypes.GEOMETRY, new ToPointEvaluaror(pointDimensionNames));
654
                    GeometryManager geommgr = GeometryLocator.getGeometryManager();
655
                    GeometryType gt;
656
                        try {
657
                                gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM3D);
658
                            attr.setGeometryType(gt);
659
                        } catch (Exception e) {
660
                                logger.warn("Can't set geometry type for the calculated field in CSV file '"+getFullFileName()+"'.",e);
661
                        }
662
            }
663
                return fType;
664
    }
665
    
666
    static class ToPointEvaluaror extends AbstractEvaluator {
667

    
668
            private static final Logger logger = LoggerFactory.getLogger(ToPointEvaluaror.class);
669
            
670
            private GeometryManager geommgr = null;
671
            private String xname = null;
672
            private String yname = null;
673
            private String zname = null;
674
                private Coercion toDouble;
675
                private int errorcount = 0;
676
            ToPointEvaluaror(String[] pointDimensionNames) {
677
                    this.xname = pointDimensionNames[0];
678
                    this.yname = pointDimensionNames[1];
679
                    if( pointDimensionNames.length >2 ) {
680
                            this.yname = pointDimensionNames[2];
681
                    }
682
                    this.geommgr = GeometryLocator.getGeometryManager();
683
                    this.toDouble = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.DOUBLE);
684
            }
685
            
686
                public Object evaluate(EvaluatorData data) throws EvaluatorException {
687
                        try {
688
                                double x = ((Double) toDouble.coerce(data.getDataValue(xname))).doubleValue();
689
                                double y = ((Double) toDouble.coerce(data.getDataValue(yname))).doubleValue();
690
                                Point point = geommgr.createPoint(x, y,Geometry.SUBTYPES.GEOM3D);
691
                                if (zname != null) {
692
                                        double z = ((Double) toDouble.coerce(data.getDataValue(zname))).doubleValue();
693
                                        point.setCoordinateAt(2, z);
694
                                }
695
                                return point;
696
                        } catch (Exception ex) {
697
                                if( ++errorcount <5 ) {
698
                                        logger.warn("["+errorcount+"] Can't create point in CSV provider. XNAME='"+
699
                                                        xname + "', YNAME='"+yname+"', ZNAME='"+zname+"', data="+data.toString());
700
                                }
701
                                return null;
702
                        }
703
                }
704

    
705
                public String getName() {
706
                        return "ToPointEvaluaror";
707
                }
708
            
709
    }
710
    
711
        private void loadFeatures() throws IOException, DataException,
712
                        CoercionException, CloneNotSupportedException {
713
                //
714
                // http://supercsv.sourceforge.net/examples_reading.html
715
                // http://supercsv.sourceforge.net/apidocs/index.html
716
                //
717
                FileReader in = null;
718
                CsvListReader reader = null;
719
                try {
720
                        String headers[] = null;
721
                        FeatureStoreProviderServices store = this.getStoreServices();
722

    
723
                        boolean ignore_errors = CSVStoreParameters.getIgnoreErrors(getCSVParameters());
724
                        
725
                        // Initiaize the CSV parser
726
                        CsvPreference preferences = getCSVPreferences();
727
                        in = new FileReader(this.getCSVParameters().getFile());
728

    
729
                        reader = new CsvListReader(in, preferences);
730
                        headers = CSVStoreParameters.getHeaders(getCSVParameters());
731
                        if (headers == null) {
732
                                headers = reader.getHeader(true);
733
                                if (headers == null) {
734
                                        String msg = "Can't retrieve header from csv file '"
735
                                                        + this.getCSVParameters().getFile()
736
                                                                        .getAbsolutePath()
737
                                                        + "' and not specified in the parameters.";
738
                                        logger.warn(msg);
739
                                        throw new RuntimeException(msg);
740
                                }
741
                        }
742

    
743
                        // Initialize the feature types
744
                        EditableFeatureType edftype = this.getFeatureType(headers, automaticDetectionOfTypes());
745
                        FeatureType ftype = edftype.getNotEditableCopy();
746
                        List<FeatureType> ftypes = new ArrayList<FeatureType>();
747
                        ftypes.add(ftype);
748
                        store.setFeatureTypes(ftypes, ftype);
749

    
750
                        Coercion coercion[] = new Coercion[ftype.size()];
751
                        int sizes[] = new int[ftype.size()];
752
                        for (int i = 0; i < ftype.size(); i++) {
753
                                sizes[i] = -1;
754
                                FeatureAttributeDescriptor ad = ftype.getAttributeDescriptor(i);
755
                                coercion[i] = ad.getDataType().getCoercion();
756
                                if( ad.getDataType().getType() == DataTypes.STRING ) {
757
                                        if( ad.getSize() == 0 ) {
758
                                                // Es un string y no tiene un size asignado.
759
                                                // Lo ponemos a cero para calcularlo.
760
                                                sizes[i] = 0;
761
                                        }
762
                                }
763
                        }
764
                        if( ftype.getDefaultGeometryAttributeName() != null) {
765
                                this.need_calculate_envelope = true;
766
                        }
767
                        taskStatus.message("_loading");
768
                        int count = 0;
769

    
770
                        int count_errors = 0;
771
                        List<String> row = reader.read();
772
                        
773
                        while (row != null) {
774
                                taskStatus.setCurValue(++count);
775
                                FeatureProvider feature = this.createFeatureProvider(ftype);
776
                                for (int i = 0; i < row.size(); i++) {
777
                                        Object rawvalue = row.get(i);
778
                                        try {
779
                                                Object value = coercion[i].coerce(rawvalue);
780
                                                feature.set(i, value);
781
                                                if (sizes[i] >= 0 && value != null) {
782
                                                        int x = ((String) value).length();
783
                                                        if (sizes[i] < x) {
784
                                                                sizes[i] = x;
785
                                                        }
786
                                                }
787
                                        } catch (RuntimeException ex) {
788
                                                if (!ignore_errors) {
789
                                                        throw ex;
790
                                                }
791
                                                if( count_errors++ <10 ) {
792
                                                        logger.warn("Can't load value of attribute "+i+" in row "+count+".",ex);
793
                                                }
794
                                                if( count_errors==10 ) {
795
                                                        logger.info("Too many errors, suppress messages.");
796
                                                }
797
                                        }
798
                                }
799
                                this.addFeatureProvider(feature);
800
                                row = reader.read();
801
                        }
802
                        for (int i = 0; i < ftype.size(); i++) {
803
                                if( sizes[i]>0 ) {
804
                                        EditableFeatureAttributeDescriptor efad = ((EditableFeatureAttributeDescriptor)edftype.getAttributeDescriptor(i));
805
                                        efad.setSize(sizes[i]);
806
                                }
807
                        }
808
                        // Volvemos a asignar al store el featuretype, ya que puede
809
                        // haber cambiado.
810
                        ftype = edftype.getNotEditableCopy();
811
                        ftypes = new ArrayList<FeatureType>();
812
                        ftypes.add(ftype);
813
                        store.setFeatureTypes(ftypes, ftype);
814

    
815
                        taskStatus.terminate();
816
                } finally {
817
                        if( reader != null ) {
818
                                try { 
819
                                        reader.close();
820
                                } catch(Exception ex) {
821
                                        // Do nothing
822
                                }
823
                                reader = null;
824
                        }
825
                        if( in != null ) {
826
                                try { 
827
                                        in.close();
828
                                } catch(Exception ex) {
829
                                        // Do nothing
830
                                }
831
                                in = null;
832
                        }
833
                }
834
        }
835
        
836
        private int[] automaticDetectionOfTypes() throws IOException {
837
                boolean automatic_types_detection = CSVStoreParameters.getAutomaticTypesDetection(getCSVParameters());
838
                if( !automatic_types_detection ) {
839
                        return  null;
840
                }
841
                
842
                final int T_INT = 0;
843
                final int T_FLOAT = 1;
844
                final int T_DOUBLE = 2;
845
                final int T_LONG = 3;
846
                final int T_URL = 4;
847
                final int T_DATE = 5;
848
                boolean possibleDataTypes[][] = null;
849
                int[] types = null;
850

    
851
                FileReader in = null;
852
                CsvListReader reader = null;
853
                String headers[] = null;
854
                SimpleDateFormat dateFormat = new SimpleDateFormat();
855

    
856
                try {
857
                        CsvPreference preferences = getCSVPreferences();
858
                        in = new FileReader(this.getCSVParameters().getFile());
859

    
860
                        reader = new CsvListReader(in, preferences);
861
                        headers = reader.getHeader(true);
862
                        if (headers == null) {
863
                                headers = CSVStoreParameters.getHeaders(getCSVParameters());
864
                        }
865
                        types = new int[headers.length]; 
866

    
867
                        possibleDataTypes = new boolean[headers.length][6]; 
868
                        for (int i = 0; i < possibleDataTypes.length; i++) {
869
                                for( int j=0; j<4; j++ ) {
870
                                        possibleDataTypes[i][j] = true;  
871
                                }
872
                        }
873
                        List<String> row = reader.read();
874

    
875
                        while (row != null) {
876
                                for (int i = 0; i < row.size(); i++) {
877
                                        Object rawvalue = row.get(i);
878
                                        Object value = null;
879
                                        if( possibleDataTypes[i][T_DOUBLE] ) {
880
                                                try {
881
                                                        value = Double.parseDouble((String) rawvalue);
882
                                                        possibleDataTypes[i][T_DOUBLE] = true;
883
                                                } catch (Exception ex) {
884
                                                        possibleDataTypes[i][T_DOUBLE] = false;
885
                                                }
886
                                        }
887
                                        if( possibleDataTypes[i][T_FLOAT] ) {
888
                                                try {
889
                                                        value = Float.parseFloat((String) rawvalue);
890
                                                        possibleDataTypes[i][T_FLOAT] = true;
891
                                                } catch (Exception ex) {
892
                                                        possibleDataTypes[i][T_FLOAT] = false;
893
                                                }
894
                                        }
895
                                        if (possibleDataTypes[i][T_LONG]) {
896
                                                try {
897
                                                        value = Long.parseLong((String) rawvalue);
898
                                                        possibleDataTypes[i][T_LONG] = true;
899
                                                } catch (Exception ex) {
900
                                                        possibleDataTypes[i][T_LONG] = false;
901
                                                }
902
                                        }
903
                                        if (possibleDataTypes[i][T_INT]) {
904
                                                try {
905
                                                        value = Integer.parseInt((String) rawvalue);
906
                                                        possibleDataTypes[i][T_INT] = true;
907
                                                } catch (Exception ex) {
908
                                                        possibleDataTypes[i][T_INT] = false;
909
                                                }
910
                                        }                                        
911
                                        if (possibleDataTypes[i][T_DATE]) {
912
                                                try {
913
                                                        value = dateFormat.parse((String) rawvalue);
914
                                                        possibleDataTypes[i][T_DATE] = true;
915
                                                } catch (Exception ex) {
916
                                                        possibleDataTypes[i][T_DATE] = false;
917
                                                }
918
                                        }                                        
919
                                        if (possibleDataTypes[i][T_URL]) {
920
                                                try {
921
                                                        value = new URL((String) rawvalue);
922
                                                        possibleDataTypes[i][T_URL] = true;
923
                                                } catch (Exception ex) {
924
                                                        possibleDataTypes[i][T_URL] = false;
925
                                                }
926
                                        }                                        
927
                                }
928
                                row = reader.read();
929
                        }
930
                } finally {
931
                        if (reader != null) {
932
                                try {
933
                                        reader.close();
934
                                } catch (Exception ex) {
935
                                        // Do nothing
936
                                }
937
                                reader = null;
938
                        }
939
                        if (in != null) {
940
                                try {
941
                                        in.close();
942
                                } catch (Exception ex) {
943
                                        // Do nothing
944
                                }
945
                                in = null;
946
                        }
947

    
948
                }
949
                for (int i = 0; i < possibleDataTypes.length ; i++) {
950
                        if( possibleDataTypes[i][T_DOUBLE] ) {
951
                                types[i] = DataTypes.DOUBLE;
952
                                continue;
953
                        }
954
                        if( possibleDataTypes[i][T_FLOAT] ) {
955
                                types[i] = DataTypes.FLOAT;
956
                                continue;
957
                        }
958
                        if( possibleDataTypes[i][T_LONG] ) {
959
                                types[i] = DataTypes.LONG;
960
                                continue;
961
                        }
962
                        if( possibleDataTypes[i][T_INT] ) {
963
                                types[i] = DataTypes.INT;
964
                                continue;
965
                        }
966
                        if( possibleDataTypes[i][T_URL] ) {
967
                                types[i] = DataTypes.URL;
968
                                continue;
969
                        }
970
                        if( possibleDataTypes[i][T_DATE] ) {
971
                                types[i] = DataTypes.DATE;
972
                                continue;
973
                        }
974
                        types[i] = DataTypes.STRING;
975
                }
976
                return types;
977
        }
978

    
979
}