Revision 44408 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

View differences:

CSVStoreProvider.java
26 26
import java.io.FileInputStream;
27 27
import java.io.FileNotFoundException;
28 28
import java.io.FileReader;
29
import java.io.FileWriter;
30 29
import java.io.IOException;
31 30
import java.io.InputStreamReader;
32 31
import java.net.URI;
......
37 36
import java.util.Iterator;
38 37
import java.util.List;
39 38
import java.util.Locale;
40
import java.util.logging.Level;
39
import java.util.Map;
41 40

  
42 41
import org.apache.commons.io.FilenameUtils;
43 42
import org.apache.commons.io.IOUtils;
......
50 49
import org.gvsig.fmap.dal.DataStoreNotification;
51 50
import org.gvsig.fmap.dal.DataTypes;
52 51
import org.gvsig.fmap.dal.FileHelper;
53
import org.gvsig.fmap.dal.exception.CloseException;
54 52
import org.gvsig.fmap.dal.exception.DataException;
55 53
import org.gvsig.fmap.dal.exception.InitializeException;
56 54
import org.gvsig.fmap.dal.exception.OpenException;
......
82 80
import org.gvsig.fmap.geom.Geometry;
83 81
import org.gvsig.fmap.geom.GeometryLocator;
84 82
import org.gvsig.fmap.geom.GeometryManager;
83
import org.gvsig.fmap.geom.GeometryUtils;
85 84
import org.gvsig.fmap.geom.aggregate.MultiPoint;
86 85
import org.gvsig.fmap.geom.primitive.Envelope;
87 86
import org.gvsig.fmap.geom.primitive.Point;
88 87
import org.gvsig.fmap.geom.type.GeometryType;
89 88
import org.gvsig.tools.ToolsLocator;
90
import org.gvsig.tools.dataTypes.CoercionException;
91 89
import org.gvsig.tools.dataTypes.DataType;
92 90
import org.gvsig.tools.dataTypes.DataTypesManager;
93 91
import org.gvsig.tools.dataTypes.DataTypesManager.Coercion;
94 92
import org.gvsig.tools.dataTypes.DataTypesManager.CoercionWithLocale;
95 93
import org.gvsig.tools.dispose.DisposableIterator;
94
import org.gvsig.tools.dynobject.Tags;
96 95
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
97 96
import org.gvsig.tools.evaluator.AbstractEvaluator;
98 97
import org.gvsig.tools.evaluator.EvaluatorData;
......
107 106
import org.gvsig.tools.visitor.Visitor;
108 107
import org.slf4j.Logger;
109 108
import org.slf4j.LoggerFactory;
110
import org.supercsv.io.CsvListWriter;
111 109
import org.supercsv.prefs.CsvPreference;
112 110

  
113 111
@SuppressWarnings("UseSpecificCatch")
114 112
public class CSVStoreProvider extends AbstractMemoryStoreProvider implements
115 113
        ResourceConsumer {
116 114

  
117
    private static final Logger logger = LoggerFactory.getLogger(CSVStoreProvider.class);
115
    private static final Logger LOGGER = LoggerFactory.getLogger(CSVStoreProvider.class);
118 116

  
119 117
    public static final String NAME = "CSV";
120 118
    public static final String DESCRIPTION = "CSV file";
......
189 187
        try {
190 188
            loadFeatures();
191 189
        } catch (RuntimeException e) {
192
            logger.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
190
            LOGGER.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
193 191
            throw e;
194 192
        } catch (Exception e) {
195
            logger.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
193
            LOGGER.debug("Can't load features from CSV '" + getFullFileName() + "'.", e);
196 194
            throw new RuntimeException(e);
197 195
        }
198 196
    }
......
245 243
                                    (org.gvsig.fmap.dal.feature.Feature) it.next());
246 244
                            writer.add(feature);
247 245
                            if (feature.getOID() == null) {
248
                                logger.warn("feature without OID");
246
                                LOGGER.warn("feature without OID");
249 247
                                feature.setOID(createNewOID());
250 248
                            }
251 249
                            newdata.add(feature);
......
341 339
            });
342 340
            writer.end();
343 341
        } catch (PerformEditingException ex) {
344
            logger.warn("Not been able to end append '" + this.getFullName() + "'.", ex);
342
            LOGGER.warn("Not been able to end append '" + this.getFullName() + "'.", ex);
345 343
        }
346 344
    }
347 345

  
......
392 390
                }
393 391
            });
394 392
        } catch (BaseException e) {
395
            logger.warn("Can't calculate the envelope of CSV file '" + this.getFullName() + "'.", e);
393
            LOGGER.warn("Can't calculate the envelope of CSV file '" + this.getFullName() + "'.", e);
396 394
            this.envelope = null;
397 395
        }
398 396

  
......
457 455
    private void init(CSVStoreParameters parameters, DataStoreProviderServices storeServices) {
458 456
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
459 457
    }
460

  
461 458
    private class FieldTypeParser {
462 459

  
463 460
        public String name = null;
464 461
        public int type = DataTypes.STRING;
465 462
        public int size = 0;
466
        public boolean allowNulls = true;
467
        public int geometryType = Geometry.TYPES.GEOMETRY;
463
        public int geomType = Geometry.TYPES.GEOMETRY;
464
        public int geomSubtype = Geometry.SUBTYPES.GEOM2D;
465
        public Map<String,String> tags = new HashMap<>();
466
        public Map<String,String> assignments = new HashMap<>();
468 467

  
469 468
        private String typename = "string";
470 469

  
471 470
        FieldTypeParser() {
472 471
        }
473 472

  
473
        public void clear() {
474
            this.name = null;
475
            this.type = DataTypes.STRING;
476
            this.size = 0;
477
            this.tags = new HashMap<>();
478
            this.assignments = new HashMap<>();
479
        }
480

  
481
        public void copyFrom(FieldTypeParser other) {
482
            this.name = other.name;
483
            this.type = other.type;
484
            this.size = other.size;
485
            this.tags = new HashMap<>();
486
            this.tags.putAll(other.tags);
487
            this.assignments = new HashMap<>();
488
            this.assignments.putAll(other.assignments);
489
        }
490

  
474 491
        private int getType(String value) {
475 492
            DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
476 493
            return dataTypesManager.getType(typename);
477 494
        }
478 495

  
479
        public void clear() {
480
            name = null;
481
            type = DataTypes.STRING;
482
            size = 0;
483
            allowNulls = true;
484
            geometryType = Geometry.TYPES.GEOMETRY;
496
        private String[] split(String value, String separators) {
497
            int firstSeparatorPosition = 1000000;
498
            Character sep = null;
499
            for (char ch : separators.toCharArray()) {
500
                int pos = value.indexOf(ch);
501
                if( pos>0 && pos<firstSeparatorPosition ) {
502
                    sep = ch;
503
                    firstSeparatorPosition = pos;
504
                }
505
            }
506
            if( sep == null ) {
507
                return new String[] { value };
508
            }
509
            return value.split("["+sep+"]");
485 510
        }
486 511

  
487
        public void copyFrom(FieldTypeParser other) {
488
            name = other.name;
489
            type = other.type;
490
            size = other.size;
491
            allowNulls = other.allowNulls;
492
            geometryType = other.geometryType;
493
        }
494

  
495
        // El formato seria:
496
        //   name[:typename[:size[:notnull|null]]]
497
        //   name[:GEOMETRY[:geometry_type[:notnull|null]]]
498
        //   name[__typename[__size[__notnull|null]]]
499
        //
512
        @SuppressWarnings("UseSpecificCatch")
500 513
        public boolean parse(String value) {
501
            String theTypename = null;
502
            String[] ss = null;
503
            if (value.contains(":")) {
504
                ss = value.split(":");
505
            } else if (value.contains("__")) {
506
                ss = value.split("__");
507
            }
508
            if (ss == null) {
509
                this.name = value;
514
            String[] args;
515
            if ( value.contains("__") ) {
516
                args = value.split("__");
517
            } else {
518
                args = split(value, ":/#@!;-");
519
                if( args.length == 1 ) {
520
                    this.name = value;
521
                    return true;
522
                }
523
            }                        
524
            int n = 0;
525
            this.name = args[n++];
526
            if( n >= args.length ) {
510 527
                return true;
511 528
            }
512
            switch (ss.length) {
513
                case 4:
514
                    if (!StringUtils.isBlank(ss[3])) {
515
                        if ("notnull".equalsIgnoreCase(ss[3].trim())) {
516
                            this.allowNulls = false;
517
                        } else {
518
                            this.allowNulls = true;
529
            this.typename = args[n++];
530
            this.type = this.getType(this.typename);
531
            if ( this.type == DataTypes.INVALID ) {
532
                this.geomType = GeometryUtils.getGeometryType(this.typename);
533
                if( this.geomType==Geometry.TYPES.UNKNOWN )  {
534
                    this.type = DataTypes.STRING;
535
                    LOGGER.info("Type '" + this.typename + "' not valid for attribute '" + value + "' in '"+getProviderName()+"' file '" + getFullFileName() + "'.");
536
                } else {
537
                    this.typename = "GEOMETRY";
538
                    this.type = DataTypes.GEOMETRY;
539
                }
540
            }
541
            switch(this.type) {
542
                case DataTypes.STRING:
543
                    this.size = 50;
544
                    break;
545
                case DataTypes.INT:
546
                    this.size = 10;
547
                    break;
548
                case DataTypes.LONG:
549
                    this.size = 20;
550
                    break;
551
                case DataTypes.FLOAT:
552
                    this.size = 10;
553
                    break;
554
                case DataTypes.DOUBLE:
555
                    this.size = 20;
556
                    break;
557
                default:
558
                    this.size = 0;
559
            }
560
            while (n < args.length) {
561
                String option = args[n++].toLowerCase();
562
                switch (option) {
563
                    case "size":
564
                        try {
565
                            this.size = Integer.parseInt(args[n++]);
566
                        } catch (Exception ex) {
567
                            LOGGER.warn("Ignore incorrect field size for field " + value + " in '"+getProviderName()+"' file '" + getFullFileName() + "'.", ex);
519 568
                        }
520
                    }
521
                case 3:
522
                    if (!StringUtils.isBlank(ss[1])) {
523
                        this.typename = ss[1].trim();
524
                        this.type = this.getType(this.typename);
525
                        if (this.type == DataTypes.INVALID) {
526
                            this.type = DataTypes.STRING;
527
                            logger.info("Type '" + theTypename + "' not valid for attribute '" + value + "' in CSV file '" + getFullFileName() + "'.");
569
                        break;
570
                    case "tag": {
571
                            String x = args[n++];
572
                            int pos = x.indexOf("=");
573
                            if( pos < 0 ) {
574
                                this.tags.put(x, null);
575
                            } else {
576
                                this.tags.put( 
577
                                        StringUtils.substring(x, 0, pos),
578
                                        StringUtils.substring(x, pos+1)
579
                                );
580
                            }
581
                            break;
528 582
                        }
529
                    }
530
                    if (!StringUtils.isBlank(ss[2])) {
531
                        if (this.type == DataTypes.GEOMETRY) {
532
                            String s = ss[2].trim();
533
                            if (s.equalsIgnoreCase("line") || s.equalsIgnoreCase("linestring") || s.equalsIgnoreCase("curve")) {
534
                                this.geometryType = Geometry.TYPES.LINE;
535
                            } else if (s.equalsIgnoreCase("multiline") || s.equalsIgnoreCase("multilinestring") || s.equalsIgnoreCase("multicurve")) {
536
                                this.geometryType = Geometry.TYPES.MULTILINE;
537
                            } else if (s.equalsIgnoreCase("point")) {
538
                                this.geometryType = Geometry.TYPES.POINT;
539
                            } else if (s.equalsIgnoreCase("multipoint")) {
540
                                this.geometryType = Geometry.TYPES.MULTIPOINT;
541
                            } else if (s.equalsIgnoreCase("polygon") || s.equalsIgnoreCase("surface")) {
542
                                this.geometryType = Geometry.TYPES.POLYGON;
543
                            } else if (s.equalsIgnoreCase("multipolygon") || s.equalsIgnoreCase("multisurface")) {
544
                                this.geometryType = Geometry.TYPES.MULTIPOLYGON;
583
                    case "set": {
584
                            String x = args[n++];
585
                            int pos = x.indexOf("=");
586
                            if( pos < 0 ) {
587
                                this.assignments.put(x, null);
588
                            } else {
589
                                this.assignments.put( 
590
                                        StringUtils.substring(x, 0, pos),
591
                                        StringUtils.substring(x, pos+1)
592
                                );
545 593
                            }
546
                            this.size = 1;
547
                        } else {
548
                            try {
549
                                this.size = Integer.parseInt(ss[2]);
550
                            } catch (Exception ex) {
551
                                logger.warn("Ignore incorrect field size for field " + value + " in CSV header of '" + getFullFileName() + "'.", ex);
552
                            }
594
                            break;
553 595
                        }
554
                    }
555
                    this.name = ss[0].trim();
556
                    break;
557
                case 2:
558
                    if (!StringUtils.isBlank(ss[1])) {
559
                        this.typename = ss[1].trim();
560
                        this.type = this.getType(this.typename);
561
                        if (this.type == DataTypes.INVALID) {
562
                            this.type = DataTypes.STRING;
563
                            logger.info("Type '" + theTypename + "' not valid for attribute '" + value + "' in CSV file '" + getFullFileName() + "'.");
564
                        }
565
                    }
566
                case 1:
567
                    this.name = ss[0].trim();
568
                    break;
596
                    default:
597
                        LOGGER.warn("Illegal argumente '"+option+"' for field '"+this.name+"' in '"+getProviderName()+"' file '" + getFullFileName() + "' ("+value+").");
598
                }
569 599
            }
570

  
571
            if (this.type != DataTypes.STRING) {
572
                this.size = 0;
573
            }
574 600
            return true;
575 601
        }
576 602

  
......
627 653
        //
628 654
        // Una vez ya sabemos los tipos de datos rellenamos el feature-type
629 655
        //
630
        for (int i = 0; i < fieldTypes.length; i++) {
631
            EditableFeatureAttributeDescriptor fad = fType.add(
632
                    fieldTypes[i].name,
633
                    fieldTypes[i].type
634
            );
635
            fad.setSize(fieldTypes[i].size);
636
            fad.setAllowNull(fieldTypes[i].allowNulls);
637
            if (fieldTypes[i].type == DataTypes.GEOMETRY) {
638
                if (fType.getDefaultGeometryAttributeName() == null) {
639
                    fType.setDefaultGeometryAttributeName(fieldTypes[i].name);
656
        for (FieldTypeParser fieldType : fieldTypes) {
657
            EditableFeatureAttributeDescriptor fad = fType.add(fieldType.name, fieldType.type);
658
            fad.setSize(fieldType.size);
659
            if (fieldType.type == DataTypes.GEOMETRY ) {
660
                fad.setGeometryType(fieldType.geomType, fieldType.geomSubtype);
661
                if( fType.getDefaultGeometryAttributeName() == null ) {
662
                    fType.setDefaultGeometryAttributeName(fieldType.name);
640 663
                }
641
                fad.setGeometryType(fieldTypes[i].geometryType);
642 664
            }
665
            for (Map.Entry<String, String> entry : fieldType.assignments.entrySet()) {
666
                try {
667
                    switch(entry.getKey().toLowerCase()) {
668
                        case "expression":
669
                            // Los campos calculados los procesamos en una segunda
670
                            // pasada, cuando ya estan definidos el resto de los campos
671
                            // ya que pueden requerir campos que aun no se han definido.
672
                            break;
673
                        default:
674
                            fad.set(entry.getKey(), entry.getValue());
675
                    }
676
                } catch (Exception ex) {
677
                    LOGGER.warn("Can't set property '"+entry.getKey()+"' of '"+fad.getName()+"'.", ex);
678
                }
679
            }
680
            Tags tags = fad.getTags();
681
            for (Map.Entry<String, String> entry : fieldType.tags.entrySet()) {
682
                tags.set(entry.getKey(), entry.getValue());
683
            }
643 684
        }
685
        // Processamos ahora los campos calculados
686
        for (FieldTypeParser fieldType : fieldTypes) {
687
            EditableFeatureAttributeDescriptor fad = fType.getEditableAttributeDescriptor(fieldType.name);
688
            for (Map.Entry<String, String> entry : fieldType.assignments.entrySet()) {
689
                try {
690
                    switch(entry.getKey().toLowerCase()) {
691
                        case "expression":
692
                            fad.set(entry.getKey(), entry.getValue());
693
                            break;
694
                    }
695
                } catch (Exception ex) {
696
                    LOGGER.warn("Can't set property '"+entry.getKey()+"' in '"+fad.getName()+"' of '"+getFullFileName()+"'.", ex);
697
                }
698
            }
699
        }
644 700
        String[] pointDimensionNames = CSVStoreParameters.getPointDimensionNames(this.getParameters());
645
        if (pointDimensionNames != null) {
701
        if ( pointDimensionNames != null ) {
646 702
            PointAttributeEmulator emulator = new PointAttributeEmulator(pointDimensionNames);
647
            EditableFeatureAttributeDescriptor attr = fType.add(
648
                    CSVStoreParameters.getPointColumnName(this.getParameters()),
649
                    DataTypes.GEOMETRY, emulator
650
            );
703
            EditableFeatureAttributeDescriptor attr = fType.add("the_geom", DataTypes.GEOMETRY, emulator);
651 704
            GeometryManager geommgr = GeometryLocator.getGeometryManager();
652 705
            GeometryType gt;
653 706
            try {
654
                gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM3D);
707
                if ( emulator.fieldNames != null && emulator.fieldNames.length <= 2 ) {
708
                	gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D);
709
                } else {
710
                	gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM3D);
711
                }
655 712
                attr.setGeometryType(gt);
656
                attr.setGeometryType(Geometry.TYPES.POINT);
657
                attr.setGeometrySubType(Geometry.SUBTYPES.GEOM3D);
658 713
            } catch (Exception e) {
659
                logger.warn("Can't set geometry type for the calculated field in CSV file '" + getFullFileName() + "'.", e);
714
                LOGGER.warn("Can't set geometry type for the calculated field in '"+getProviderName()+"' file '" + getFullFileName() + "'.", e);
660 715
            }
661
        }
662

  
716
        }        
717
        
663 718
        String geometry_column = CSVStoreParameters.getGeometryColumn(this.getParameters());
664 719
        if (!StringUtils.isEmpty(geometry_column)) {
665 720
            EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor) fType.get(geometry_column);
......
671 726
                    gt = geommgr.getGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.UNKNOWN);
672 727
                    attr.setGeometryType(gt);
673 728
                } catch (Exception e) {
674
                    logger.warn("Can't set geometry type for the calculated field in CSV file '" + getFullFileName() + "'.", e);
729
                    LOGGER.warn("Can't set geometry type for the calculated field in CSV file '" + getFullFileName() + "'.", e);
675 730
                }
676 731
                fType.setDefaultGeometryAttributeName(geometry_column);
677 732
            }
......
860 915
                try {
861 916
                    charset = Charset.forName(charsetName);
862 917
                } catch (Throwable th) {
863
                    logger.warn("Can't use charset '" + charsetName + "' for read csv '" + this.getFullFileName() + "'.", th);
918
                    LOGGER.warn("Can't use charset '" + charsetName + "' for read csv '" + this.getFullFileName() + "'.", th);
864 919
                }
865 920
            } else {
866
                logger.warn("charset '" + charsetName + "' not supported for read csv '" + this.getFullFileName() + "'.");
921
                LOGGER.warn("charset '" + charsetName + "' not supported for read csv '" + this.getFullFileName() + "'.");
867 922
            }
868 923
        }
869 924
        InputStreamReader isr = new InputStreamReader(fis, charset);
......
898 953
                                    + this.getCSVParameters().getFile()
899 954
                                            .getAbsolutePath()
900 955
                                    + "' and not specified in the parameters.";
901
                            logger.warn(msg);
956
                            LOGGER.warn(msg);
902 957
                            throw new RuntimeException(msg);
903 958
                        }
904 959
                    }
......
1006 1061
                            throw ex;
1007 1062
                        }
1008 1063
                        if (count_errors++ < 10) {
1009
                            logger.warn("Can't load value of attribute " + i + " in row " + count + ".", ex);
1064
                            LOGGER.warn("Can't load value of attribute " + i + " in row " + count + ".", ex);
1010 1065
                        }
1011 1066
                        if (count_errors == 10) {
1012
                            logger.info("Too many errors, suppress messages.");
1067
                            LOGGER.info("Too many errors, suppress messages.");
1013 1068
                        }
1014 1069
                    }
1015 1070
                }

Also available in: Unified diff