Project

General

Profile

Download (5.75 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2013 EDIT
3
 * European Distributed Institute of Taxonomy
4
 * http://www.e-taxonomy.eu
5
 *
6
 * The contents of this file are subject to the Mozilla Public License Version 1.1
7
 * See LICENSE.TXT at the top of this package for the full license terms.
8
 */
9
package eu.etaxonomy.cdm.ext.geo;
10

    
11
import java.io.IOException;
12
import java.io.Reader;
13
import java.util.HashMap;
14
import java.util.List;
15
import java.util.Map;
16
import java.util.Set;
17

    
18
import org.apache.commons.lang.ArrayUtils;
19
import org.apache.logging.log4j.LogManager;
20
import org.apache.logging.log4j.Logger;
21

    
22
import au.com.bytecode.opencsv.CSVReader;
23
import eu.etaxonomy.cdm.model.location.NamedArea;
24
import eu.etaxonomy.cdm.model.term.TermVocabulary;
25

    
26
/**
27
 * Reads csv data containing the attributes from a shape file and adds the
28
 * shapefile data to each area in the given set of {@link NamedAreas}. The way
29
 * this data it attached to the areas is specific to the
30
 * {@link IGeoServiceAreaMapping} implementation. It is recommended to create
31
 * csv file directly from the original shape file by making use of the
32
 * {@code org2ogr} command which is contained in the <a
33
 * href="http://www.gdal.org/ogr2ogr.html">gdal</a> tools:
34
 *
35
 * <pre>
36
 * ogr2ogr -f csv out.csv input_shape_file.shp
37
 * </pre>
38
 *
39
 *
40
 * @author a.kohlbecker
41
 * @since Oct 18, 2013
42
 *
43
 */
44
public class ShpAttributesToNamedAreaMapper {
45

    
46
    public static final Logger logger = LogManager.getLogger(ShpAttributesToNamedAreaMapper.class);
47

    
48
    private static final char COMMA = ',';
49

    
50
    private final Set<NamedArea> areas;
51

    
52
    private final IGeoServiceAreaMapping areaMapping;
53

    
54
    /**
55
     * maps the idSearchFields supplied to the {@link #readCsv(File, List)} method to the
56
     * column index
57
     */
58
    private Map<String,Integer> searchColumnMap = null;
59

    
60
    public ShpAttributesToNamedAreaMapper(Set<NamedArea> areas, IGeoServiceAreaMapping areaMapping) {
61
        this.areas = areas;
62
        this.areaMapping = areaMapping;
63
    }
64

    
65
    public ShpAttributesToNamedAreaMapper(TermVocabulary<NamedArea> areaVocabulary, IGeoServiceAreaMapping areaMapping) {
66
        this.areas = areaVocabulary.getTerms();
67
        this.areaMapping = areaMapping;
68
    }
69

    
70
    /**
71
     * @param reader A reader of the csv data
72
     * @param idSearchFields
73
     *            An ordered list column names in the the csv file to be
74
     *            imported. These columns will be used to search for the
75
     *            {@link NamedArea#getIdInVocabulary() IdInVocabulary} of each
76
     *            area
77
     * @param wmsLayerName
78
     * @return the resulting table of the import, also together with diagnostic
79
     *         messages per NamedArea (id not found)
80
     * @throws IOException
81
     */
82
    public Map<NamedArea, String> readCsv(Reader reader, List<String> idSearchFields, String wmsLayerName) throws IOException {
83

    
84
        //logger.setLevel(Level.DEBUG);
85

    
86
        Map<NamedArea, String> resultMap = new HashMap<>(areas.size());
87

    
88
        CSVReader csvReader = new CSVReader(reader, COMMA);
89

    
90
        // read header row and prepare the searchColumnMap
91
        String[] headerRow = csvReader.readNext();
92
        searchColumnMap = new HashMap<>();
93
        for(String colName : idSearchFields){
94
            int idx = ArrayUtils.indexOf(headerRow, colName);
95
            if(idx > -1){
96
                searchColumnMap.put(colName, idx);
97
            } else {
98
                logger.debug("no header row found for " + colName);
99
            }
100
        }
101

    
102
        // read the rest of the file
103
        List<String[]> data = csvReader.readAll();
104
        csvReader.close();
105
        csvReader = null; // release memory
106

    
107
        String matchIdCode;
108
        String matchColName;
109
        for(NamedArea a : areas){
110

    
111
            if(a.getIdInVocabulary() == null){
112
                String message = "has no IdInVocabulary";
113
                resultMap.put(a, message);
114
                logger.warn(a.getTitleCache() + " " + message);
115
                continue;
116
            }
117
            matchIdCode = null;
118
            matchColName = null;
119
            // search in each of the columns until found
120
            for(String colName : searchColumnMap.keySet()){
121

    
122
                int idx = searchColumnMap.get(colName);
123

    
124
                for(String[] row : data){
125
                    String fieldData = row[idx].trim();
126
                    if(a.getIdInVocabulary().equals(fieldData)){
127
                        // FOUND!
128
                        matchIdCode = fieldData;
129
                        break;
130
                    }
131
                }
132

    
133
                if(matchIdCode != null){
134
                    // no need to search in next column
135
                    matchColName = colName;
136
                    break;
137
                }
138

    
139
            } // END loop columns
140

    
141
            if(matchIdCode != null){
142
                //TODO need to clear the area mapping since the mapping impl can not distinguish multiple layers
143
                //     see https://dev.e-taxonomy.eu/redmine/issues/4263
144
                areaMapping.clear(a);
145

    
146
                GeoServiceArea geoServiceArea;
147
                geoServiceArea = areaMapping.valueOf(a);
148
                if(geoServiceArea == null){
149
                    geoServiceArea = new GeoServiceArea();
150
                }
151
                geoServiceArea.add(wmsLayerName, matchColName, matchIdCode);
152
                areaMapping.set(a, geoServiceArea );
153

    
154
                String message = matchColName + ": " + matchIdCode;
155
                resultMap.put(a, message);
156
                if(logger.isDebugEnabled()){
157
                    logger.debug(a.getIdInVocabulary() + ": " + message);
158
                }
159
            } else {
160
                String message = "no match for " + a.getIdInVocabulary();
161
                resultMap.put(a, message);
162
                logger.warn(message);
163
            }
164

    
165

    
166
        } // END of areas loop
167
        return resultMap;
168
    }
169

    
170
}
(11-11/11)