Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libGeocoding / src / org / gvsig / geocoding / impl / DataGeocoderImpl.java @ 32195

History | View | Annotate | Download (10.1 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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 2
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
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 PRODEVELOP                Main development
26
 */
27

    
28
package org.gvsig.geocoding.impl;
29

    
30
import java.util.ArrayList;
31
import java.util.Iterator;
32
import java.util.List;
33
import java.util.Set;
34
import java.util.TreeSet;
35

    
36
import org.gvsig.fmap.dal.DALLocator;
37
import org.gvsig.fmap.dal.DataManager;
38
import org.gvsig.fmap.dal.DataStore;
39
import org.gvsig.fmap.dal.exception.DataException;
40
import org.gvsig.fmap.dal.feature.Feature;
41
import org.gvsig.fmap.dal.feature.FeatureQuery;
42
import org.gvsig.fmap.dal.feature.FeatureSelection;
43
import org.gvsig.fmap.dal.feature.FeatureSet;
44
import org.gvsig.fmap.dal.feature.FeatureStore;
45
import org.gvsig.geocoding.DataGeocoder;
46
import org.gvsig.geocoding.address.Address;
47
import org.gvsig.geocoding.address.ComposedAddress;
48
import org.gvsig.geocoding.address.Literal;
49
import org.gvsig.geocoding.address.NumberAddress;
50
import org.gvsig.geocoding.distance.StringsDistance;
51
import org.gvsig.geocoding.distance.impl.LevenshteinDistance;
52
import org.gvsig.geocoding.pattern.GeocodingPattern;
53
import org.gvsig.geocoding.result.GeocodingResult;
54
import org.gvsig.geocoding.result.ScoredFeature;
55
import org.gvsig.geocoding.result.impl.DefaultScoredFeature;
56
import org.gvsig.geocoding.styles.AbstractGeocodingStyle;
57
import org.gvsig.geocoding.styles.impl.Composed;
58
import org.gvsig.geocoding.styles.impl.DoubleRange;
59
import org.gvsig.geocoding.styles.impl.SimpleCentroid;
60
import org.gvsig.geocoding.styles.impl.SimpleRange;
61
import org.gvsig.tools.evaluator.Evaluator;
62
import org.gvsig.tools.locator.LocatorException;
63
import org.slf4j.Logger;
64
import org.slf4j.LoggerFactory;
65

    
66
/**
67
 * Data geocoder implementation
68
 * 
69
 * @author <a href="mailto:jsanz@prodevelop.es"> Jorge Gaspar Sanz Salinas</a>
70
 * @author <a href="mailto:vsanjaime@prodevelop.es"> Vicent Sanjaime Calvet</a>
71
 */
72

    
73
public class DataGeocoderImpl implements DataGeocoder {
74

    
75
        private Logger log = LoggerFactory.getLogger(DataGeocoderImpl.class);
76
        private GeocodingPattern pattern = null;
77
        private DataStore store = null;
78
        private DataManager manager = null;
79

    
80
        /**
81
         * Constructor with one pattern
82
         * 
83
         * @param pattern
84
         */
85
        public DataGeocoderImpl() {
86
                manager = DALLocator.getDataManager();
87
        }
88

    
89
        /**
90
         * Constructor with one pattern
91
         * 
92
         * @param pattern
93
         */
94
        public DataGeocoderImpl(GeocodingPattern pattern) {
95
                this.pattern = pattern;
96
                manager = DALLocator.getDataManager();
97
        }
98

    
99
        /**
100
         * set the pattern
101
         * 
102
         * @param pattern
103
         */
104
        public void setPattern(GeocodingPattern pattern) {
105
                this.pattern = pattern;
106

    
107
        }
108

    
109
        /**
110
         * Get the pattern
111
         * 
112
         * @return pattern
113
         */
114
        public GeocodingPattern getPattern() {
115
                return this.pattern;
116

    
117
        }
118

    
119
        /**
120
         * Set the store
121
         */
122
        public void setStore(DataStore store) {
123
                this.store = store;
124

    
125
        }
126

    
127
        /**
128
         * Get the store
129
         * 
130
         * @return
131
         */
132
        public DataStore getStore() {
133
                return this.store;
134

    
135
        }
136

    
137
        /**
138
         * Geocoding process
139
         * 
140
         * @param address
141
         * @return results
142
         */
143
        public Set<GeocodingResult> geocode(Address address)
144
                        throws LocatorException, DataException {
145

    
146
                Set<GeocodingResult> results = new TreeSet<GeocodingResult>();
147
                // get the style
148
                AbstractGeocodingStyle astyle = getPattern().getDataSource().getStyle();
149
                // get literal with relations with the store
150
                Literal relationsLiteral = astyle.getRelationsLiteral();
151
                // list of list with one or more literal results
152
                List<List<ScoredFeature>> lists = new ArrayList<List<ScoredFeature>>();
153
                // get layer store
154

    
155
                // SIMPLE CENTROID
156
                if (astyle instanceof SimpleCentroid) {
157
                        SimpleCentroid style = (SimpleCentroid) astyle;
158
                        Literal addressLiteral = address.getMainLiteral();
159
                        // literal search
160
                        List<ScoredFeature> literalResults = literalSearch(
161
                                        relationsLiteral, addressLiteral, store);
162
                        lists.add(literalResults);
163
                        // Geom search
164
                        results = style.match(lists, address);
165
                }
166

    
167
                // SIMPLE RANGE
168
                else if (astyle instanceof SimpleRange) {
169
                        SimpleRange style = (SimpleRange) astyle;
170
                        Literal addressLiteral = ((NumberAddress) address).getMainLiteral();
171
                        // literal search
172
                        List<ScoredFeature> literalResults = literalSearch(
173
                                        relationsLiteral, addressLiteral, store);
174
                        lists.add(literalResults);
175
                        // geom search
176
                        results = style.match(lists, address);
177
                }
178

    
179
                // DOUBLE RANGE
180
                else if (astyle instanceof DoubleRange) {
181
                        DoubleRange style = (DoubleRange) astyle;
182
                        Literal addressLiteral = ((NumberAddress) address).getMainLiteral();
183
                        // literal search
184
                        List<ScoredFeature> literalResults = literalSearch(
185
                                        relationsLiteral, addressLiteral, store);
186
                        lists.add(literalResults);
187
                        // number search
188
                        results = style.match(lists, address);
189
                }
190

    
191
                // STYLE COMPOSED
192
                else if (astyle instanceof Composed) {
193
                        Composed style = (Composed) astyle;
194
                        ComposedAddress cAddress = (ComposedAddress) address;
195

    
196
                        // main literal search
197
                        Literal mainAddressLiteral = cAddress.getMainLiteral();
198
                        List<ScoredFeature> literalResults = literalSearch(
199
                                        relationsLiteral, mainAddressLiteral, store);
200
                        lists.add(literalResults);
201
                        // search in others literals
202
                        List<Literal> intersectslist = cAddress.getIntersectionLiterals();
203
                        for (Literal addrLiteral : intersectslist) {
204
                                // literal search
205
                                List<ScoredFeature> secList = literalSearch(relationsLiteral,
206
                                                addrLiteral, store);
207
                                lists.add(secList);
208
                        }
209
                        // Match
210
                        results = style.match(lists, address);
211
                }
212
                return results;
213
        }
214

    
215
        /**
216
         * First scouting process, search literal elements in data store and return
217
         * a list with ok scored features
218
         * 
219
         * @param relationsLiteral
220
         * @param addressLiteral
221
         * @param store
222
         * @return
223
         * @throws DataException
224
         */
225
        private List<ScoredFeature> literalSearch(Literal relationsLiteral,
226
                        Literal addressLiteral, DataStore store) throws DataException {
227

    
228
                List<FeatureSelection> sels = new ArrayList<FeatureSelection>();
229
                FeatureSet features = null;
230

    
231
                //int maxres = getPattern().getSettings().getResultsNumber();
232

    
233
                int cont = relationsLiteral.size();
234
                int cont2 = relationsLiteral.size();
235

    
236
                for (int j = 0; j < cont; j++) {
237

    
238
                        String expresion = null;
239
                        String value;
240
                        int num = 0;
241

    
242
                        FeatureSelection selection = ((FeatureStore) store)
243
                                        .createFeatureSelection();
244
                        FeatureQuery query = ((FeatureStore) store).createFeatureQuery();
245

    
246
                        for (String key : relationsLiteral.keySet()) {
247
                                if (num < cont2) {
248
                                        key = key.trim();
249
                                        value = relationsLiteral.get(key);
250

    
251
                                        String chain = addressLiteral.get(key);
252
                                        if (num == 0) {
253
                                                expresion = value + " = '" + chain + "'";
254
                                        } else {
255
                                                expresion = expresion + " and " + value + " = '"
256
                                                                + chain + "'";
257
                                        }
258
                                        num++;
259
                                } else {
260
                                        break;
261
                                }
262
                        }
263

    
264
                        log.debug("EXPRESION: " + expresion);
265
                        Evaluator eval = manager.createExpresion(expresion);
266

    
267
                        query.setFilter(eval);
268
                        features = ((FeatureStore) store).getFeatureSet(query);
269
                        log.debug("FEatures selected: " + features.getSize());
270
                        selection.select(features);
271
                        sels.add(selection);
272
                        
273
                        if (selection.getSize() > 0) {
274
                                break;
275
                        }
276

    
277
                        cont2--;
278
                }
279
                // Put scores
280
                List<ScoredFeature> scores = createLiteralScores(store, sels, relationsLiteral, addressLiteral );
281

    
282
                return scores;
283
        }
284

    
285
        /**
286
         * Create score of the feature to first literal search
287
         * 
288
         * @param store
289
         * @param sels
290
         * @return
291
         * @throws DataException
292
         */
293
        @SuppressWarnings("unchecked")
294
        private List<ScoredFeature> createLiteralScores(DataStore store,
295
                        List<FeatureSelection> sels, Literal relationsLiteral,
296
                        Literal addressLiteral ) throws DataException {
297

    
298
                List<ScoredFeature> scores = new ArrayList<ScoredFeature>();
299

    
300
                FeatureSet features = ((FeatureStore) store).getFeatureSet();
301

    
302
                for (Iterator<Feature> it = features.iterator(); it.hasNext();) {
303
                        Feature feature = it.next();
304
                        double num = 0;
305
                        for (int i = 0; i < sels.size(); i++) {
306
                                FeatureSelection sel = sels.get(i);
307
                                if (sel.isSelected(feature)) {
308
                                        double sco = scorePonderated(i, sels.size()) - stringsDistance(feature, relationsLiteral, addressLiteral);
309
                                        if(sco < 0){
310
                                                sco = 0;
311
                                        }
312
                                        num = num + sco;
313
                                }
314
                        }
315
                        if (num > 0.0) {
316
                                ScoredFeature scoFeat = new DefaultScoredFeature();
317
                                scoFeat.setReference(feature.getReference());
318
                                scoFeat.setScore(num);
319
                                scores.add(scoFeat);
320
                        }
321
                }
322
                return scores;
323
        }
324

    
325
        /**
326
         * Get the score value ponderated
327
         * 
328
         * @param i
329
         *            position
330
         * @param total
331
         * @return score
332
         */
333
        private double scorePonderated(int i, int total) {
334
                if (total == 1) {
335
                        return 100.0;
336
                }
337
                double score = 100.0 / (2.0 * (i + 1));
338
                return score;
339
        }
340
        
341
        /**
342
         * 
343
         * @param feat
344
         * @param relations
345
         * @param address
346
         * @return
347
         */
348
        private double stringsDistance(Feature feat, Literal relations, Literal address){
349
                
350
                double pes = 0;
351
                
352
                StringsDistance strDist = new LevenshteinDistance();
353
                for (String key : relations.keySet()) {
354
                        String field = relations.get(key);
355
                        String value = address.get(key);
356
                        Object obj = feat.get(field);
357
                        String value2 = obj.toString();
358
                        int dist = strDist.getStringsDistance(value.toUpperCase(), value2.toUpperCase());
359
                        pes = pes + dist;                
360
                }
361
                        
362
                return pes;
363
        }
364

    
365
}