Project

General

Profile

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

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

    
20
import org.apache.commons.lang.ArrayUtils;
21
import org.apache.log4j.Level;
22
import org.apache.log4j.Logger;
23

    
24
import au.com.bytecode.opencsv.CSVReader;
25
import eu.etaxonomy.cdm.model.common.TermVocabulary;
26
import eu.etaxonomy.cdm.model.location.NamedArea;
27

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

    
48
    public static final Logger logger = Logger.getLogger(ShpAttributesToNamedAreaMapper.class);
49

    
50
    private static final char COMMA = ',';
51

    
52
    private final Set<NamedArea> areas;
53

    
54
    private final IGeoServiceAreaMapping areaMapping;
55

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

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

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

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

    
86
        logger.setLevel(Level.DEBUG);
87

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

    
90
        CSVReader csvReader = new CSVReader(reader, COMMA);
91

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

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

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

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

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

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

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

    
140
            } // END loop columns
141

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

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

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

    
166

    
167
        } // END of areas loop
168

    
169
        return resultMap;
170
    }
171

    
172
}
(12-12/12)