/[projects]/dao/DaoAdresseService/src/dk/daoas/daoadresseservice/AdressSearch.java
ViewVC logotype

Contents of /dao/DaoAdresseService/src/dk/daoas/daoadresseservice/AdressSearch.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2391 - (show annotations) (download)
Thu Feb 26 16:09:39 2015 UTC (9 years, 2 months ago) by torben
File size: 16194 byte(s)
Flere alias varianter
1 package dk.daoas.daoadresseservice;
2
3 import java.sql.SQLException;
4 import java.text.SimpleDateFormat;
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.Date;
8 import java.util.HashMap;
9 import java.util.HashSet;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13 import java.util.concurrent.ConcurrentHashMap;
14
15 import org.apache.commons.lang3.StringUtils;
16
17 import dk.daoas.daoadresseservice.admin.ServiceConfig;
18 import dk.daoas.daoadresseservice.beans.Address;
19 import dk.daoas.daoadresseservice.beans.DataStatisticsBean;
20 import dk.daoas.daoadresseservice.beans.ExtendedBean;
21 import dk.daoas.daoadresseservice.beans.HundredePctBean;
22 import dk.daoas.daoadresseservice.beans.SearchResult;
23 import dk.daoas.daoadresseservice.beans.SearchResult.Status;
24 import dk.daoas.daoadresseservice.db.DatabaseLayer;
25
26 public class AdressSearch {
27
28 private Map<Integer, Map<String,Long>> searchPostnrVejnavnGadeid;
29 private Map<Long, Map<String,Address>> searchGadeidentAdresser;
30
31 private List<Address> alleAdresser;
32
33 private Map<String,Long> helperCache;
34
35 private DataStatisticsBean stats = new DataStatisticsBean();
36
37 ServiceConfig config;
38
39 public AdressSearch(ServiceConfig config) {
40 this.config = config;
41 }
42
43
44 public SearchResult search(String postnrStr, String adresse) {
45
46 SearchResult result = new SearchResult();
47
48 int postnr=0;
49
50 String helperSearchKey = "";
51
52 try {
53 postnr = Integer.parseInt(postnrStr);
54 } catch (Exception E) {
55 result.status = Status.ERROR_UNKNOWN_POSTAL;
56 return result;
57 }
58
59 Map<String,Long> postnrVeje = searchPostnrVejnavnGadeid.get(postnr);
60
61 if (postnrVeje == null) {
62 result.status = Status.ERROR_UNKNOWN_POSTAL;
63 return result;
64 }
65
66
67 result.splitResult = AddressUtils.splitAdresse(adresse);
68
69
70 if (result.splitResult.husnr.length() == 0) {
71 result.status = Status.ERROR_MISSING_HOUSENUMBER;
72 return result;
73 }
74
75 String vasketVejnavn = AddressUtils.vaskVejnavn( result.splitResult.vej );
76
77 Long gadeident = postnrVeje.get(vasketVejnavn);
78
79
80 if ( gadeident == null) {
81 helperSearchKey = "" + postnr + "/" + vasketVejnavn;
82 gadeident = helperCache.get(helperSearchKey);
83 }
84
85 if (gadeident == null) {
86 String best = getbestLevenshteinDistance(vasketVejnavn, postnrVeje);
87 if (best != null) {
88 result.levenshtein = true;
89 gadeident = postnrVeje.get(best);
90 }
91 }
92
93
94 // Brug OpenStreetMap før vi prøver google
95 // For google har en request limit, det har OSM ikke!
96 if ( gadeident == null) {
97 if (config.useOpenStreetMaps) {
98 result.osmVej = GeocodeHelper.openstreetmapHelper(config, postnr, result.splitResult.vej );
99 result.osm = true;
100
101 if (result.osmVej != null) {
102 String osmVasket = AddressUtils.vaskVejnavn( result.osmVej );
103 gadeident = postnrVeje.get(osmVasket);
104
105 if (gadeident != null) {
106 helperCache.put(helperSearchKey, gadeident);
107 }
108 }
109 }
110 }
111
112 if ( gadeident == null) {
113 if (config.useGoogle) {
114 result.googleVej = GeocodeHelper.googleHelper(config, postnr, result.splitResult.vej );
115 result.google = true;
116
117 if (result.googleVej != null) {
118 String googleVasket = AddressUtils.vaskVejnavn( result.googleVej );
119 gadeident = postnrVeje.get(googleVasket);
120
121 if (gadeident != null) {
122 helperCache.put(helperSearchKey, gadeident);
123 }
124 }
125 }
126 }
127
128
129
130 if (gadeident == null) {
131 result.status = Status.ERROR_UNKNOWN_STREETNAME;
132 return result;
133 }
134
135 Map<String, Address> gade = searchGadeidentAdresser.get(gadeident);
136 if (gade == null) { //Denne søgning må ikke fejle
137 result.status = Status.ERROR_INTERNAL;
138 return result;
139 }
140
141
142 String husnrSearch = "" + result.splitResult.husnr + result.splitResult.litra;
143 Address addr = gade.get(husnrSearch);
144
145 if (addr == null) {
146 result.status = Status.ERROR_UNKNOWN_ADDRESSPOINT;
147 return result;
148 }
149
150 result.address = addr;
151
152
153 if ( StringUtils.equals(addr.distributor, "LUKKET") ) {
154 result.status = Status.STATUS_NOT_COVERED; //Skal vi have en special status til Lukkede adresser ?
155 return result;
156 }
157
158 if (addr.daekningsType == DaekningsType.DAEKNING_IKKEDAEKKET) {
159 result.status = Status.STATUS_NOT_COVERED;
160 return result;
161 }
162
163
164 result.status = Status.STATUS_OK;
165
166 return result;
167 }
168
169
170 public void buildSearchStructures() throws SQLException{
171 searchPostnrVejnavnGadeid = new HashMap<Integer, Map<String,Long>>();
172 searchGadeidentAdresser = new HashMap<Long, Map<String,Address>>();
173 helperCache = new ConcurrentHashMap<String,Long>();
174
175 long start1 = System.currentTimeMillis();
176 System.out.println("Build -- stage 1");
177
178 alleAdresser = DatabaseLayer.getAllAdresses();
179
180
181 /* Mapper mellem db Row ID og adresse noden */
182 Map<Integer,Address> idAddressMap = new HashMap<Integer,Address>( alleAdresser.size() );
183
184 for (Address a : alleAdresser) {
185 idAddressMap.put(a.id, a);
186
187 Map<String,Long> postnrVeje = searchPostnrVejnavnGadeid.get(a.postnr);
188
189 if (postnrVeje == null) {
190 postnrVeje = new ConcurrentHashMap<String,Long>();
191 searchPostnrVejnavnGadeid.put(a.postnr, postnrVeje);
192 }
193
194 String vasketVejnavn = AddressUtils.vaskVejnavn(a.vejnavn);
195 Long gadeident = postnrVeje.get(vasketVejnavn);
196 if (gadeident == null) {
197 //postnrVeje.put(vasketVejnavn, a.gadeid);
198
199 Set<String> aliaser = findVejAliaser(a.vejnavn);
200 for(String alias : aliaser) {
201 String vasketAlias = AddressUtils.vaskVejnavn(alias);
202 postnrVeje.put(vasketAlias, a.gadeid);
203 }
204
205 }
206
207 Map<String, Address> gade = searchGadeidentAdresser.get(a.gadeid);
208 if (gade == null) {
209 gade = new HashMap<String, Address>();
210 searchGadeidentAdresser.put(a.gadeid, gade);
211 }
212 String husnrSearch = "" + a.husnr + a.husnrbogstav;
213 gade.put(husnrSearch, a);
214 }
215
216
217 ////////////////////////////////////////////////////////////////////////////////////////
218 long start2 = System.currentTimeMillis();
219 System.out.println("Build, stage1 elapsed: " + (start2-start1) );
220 System.out.println("Build -- stage 2 udvidet dækning");
221
222 List<ExtendedBean> extDao = DatabaseLayer.getExtendedAdresslist();
223 for (ExtendedBean eb : extDao) {
224
225 Address orgAddress = idAddressMap.get(eb.orgId);
226 if (orgAddress == null)
227 continue;
228
229 Address targetAddress = idAddressMap.get(eb.targetId);
230 if (targetAddress == null)
231 continue;
232
233 if (orgAddress.distributor != null && orgAddress.distributor.equals("LUKKET")) {
234 continue;
235 }
236
237 if (targetAddress.distributor.equals("LUKKET")) {
238 continue;
239 }
240
241 orgAddress.extTarget = targetAddress;
242 orgAddress.extAfstand = eb.afstand;
243
244 boolean covered = false;
245 if (targetAddress.distributor.equals("DAO")) {
246 orgAddress.rute = calculateExtendedDaoRoute(eb,orgAddress,targetAddress);
247 if (orgAddress.rute != null) {
248 orgAddress.koreliste = targetAddress.koreliste;
249 covered = true;
250 }
251 }
252
253 if (targetAddress.distributor.equals("BK")) {
254 orgAddress.koreliste = calculateExtendedBkKoreliste(eb,orgAddress,targetAddress);
255 if (orgAddress.koreliste != null) {
256 orgAddress.rute = targetAddress.rute;
257 covered = true;
258 }
259 }
260
261 if (covered) { //Kopier resten af felterne
262 orgAddress.daekningsType = DaekningsType.DAEKNING_UDVIDET;
263 orgAddress.dbkBane = targetAddress.dbkBane;
264
265 /* Sådan gør den gamle service */
266 orgAddress.kommunekode = targetAddress.kommunekode;
267 orgAddress.vejkode = targetAddress.vejkode;
268
269 orgAddress.distributor = targetAddress.distributor;
270 }
271 }
272
273 // nu skal vi ikke bruge idAddressMap længere
274 idAddressMap = null;
275
276 //////////////////////////////////////////////////////////////////////////////////////
277 long start3 = System.currentTimeMillis();
278 System.out.println("Build, stage2 elapsed: " + (start3-start2) );
279 System.out.println("Build -- stage 3 - 100pct");
280
281 Map<Integer,HundredePctBean> hundredePct = DatabaseLayer.get100PctList();
282 for (Address addr : alleAdresser) {
283 if (addr.daekningsType != DaekningsType.DAEKNING_IKKEDAEKKET) {
284 continue;
285 }
286
287 if (addr.distributor != null && addr.distributor.equals("LUKKET")) {
288 continue;
289 }
290
291
292 HundredePctBean bean = hundredePct.get(addr.postnr);
293 if (bean == null) {
294 continue;
295 }
296
297 addr.daekningsType = DaekningsType.DAEKNING_100PCT;
298 addr.rute = bean.rute;
299 addr.koreliste = bean.koreliste;
300 addr.dbkBane = bean.dbkBane;
301 addr.distributor = bean.distributor;
302 }
303
304 ////////////////////////////////////////////////////////////////////////////////////
305 long stop = System.currentTimeMillis();
306 System.out.println("Build, stage3 elapsed: " + (stop-start3) );
307 System.out.println("Build -- Gathering statistics");
308
309 for (Address addr : alleAdresser) {
310 switch (addr.daekningsType) {
311 case DAEKNING_DIREKTE:
312 stats.direkteCount++;
313 break;
314 case DAEKNING_UDVIDET:
315 stats.extendedCount++;
316 break;
317 case DAEKNING_100PCT:
318 stats.hundredePctCount++;
319 break;
320 default:
321 stats.ikkeDaekketCount++;
322 }
323 }
324
325
326 stats.elapsed = stop-start1;
327 stats.buildTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( new Date() );
328
329 System.out.println("Build: direkteCount: " + stats.direkteCount);
330 System.out.println("Build: extendedCount: " + stats.extendedCount);
331 System.out.println("Build: hundredePctCount: " + stats.hundredePctCount);
332 System.out.println("Build: ikkeDaekketCount: " + stats.ikkeDaekketCount);
333
334 System.out.println("Build: Total Elapsed: " + (stop-start1) );
335 System.out.println("Build Completed");
336
337 }
338
339 public DataStatisticsBean getStatistics() {
340 return stats;
341 }
342
343 public void clear() {
344 searchPostnrVejnavnGadeid.clear();
345 searchGadeidentAdresser.clear();
346 alleAdresser.clear();
347 helperCache.clear();
348 }
349
350
351 private String getbestLevenshteinDistance(String vasketVejnavn, Map<String,Long> postnrVeje) {
352 for(String vej : postnrVeje.keySet()) {
353 if ( StringUtils.getLevenshteinDistance(vasketVejnavn, vej) == 1) {
354 System.out.println("Levenstein: " + vasketVejnavn + "->" + vej);
355 return vej;
356 }
357 }
358
359 return null;
360 }
361
362 private String calculateExtendedDaoRoute(ExtendedBean eb, Address orgAddress, Address targetAddress) {
363
364 // ///////////////////////////////////////////////////////////////////
365 switch( eb.transport) {
366 case "cykel":
367 if (eb.afstand < 0.151) {
368 return "." + targetAddress.rute;
369 } else if (eb.afstand < 0.501) {
370 return ".." + targetAddress.rute;
371 } else if (eb.afstand < 0.701) {
372 return "..." + targetAddress.rute;
373 } else if (eb.afstand < 0.501) {
374 return "...." + targetAddress.rute;
375 }
376 break;
377 case "scooter":
378 if (eb.afstand < 0.151) {
379 return "." + targetAddress.rute;
380 } else if (eb.afstand < 0.801) {
381 return ".." + targetAddress.rute;
382 } else if (eb.afstand < 1.201) {
383 return "..." + targetAddress.rute;
384 } else if (eb.afstand < 2.101) {
385 return "...." + targetAddress.rute;
386 }
387 break;
388 case "bil":
389 if (eb.afstand < 0.151) {
390 return "." + targetAddress.rute;
391 } else if (eb.afstand < 1.001) {
392 return ".." + targetAddress.rute;
393 } else if (eb.afstand < 1.601) {
394 return "..." + targetAddress.rute;
395 } else if (eb.afstand < 2.601) {
396 return "...." + targetAddress.rute;
397 }
398 break;
399 }
400 return null;
401 }
402
403 public List<Address> getNonCoveredAddresses() {
404 List<Address> result = new ArrayList<Address>(60000);
405 for (Address a : alleAdresser) {
406 if ( a.daekningsType == DaekningsType.DAEKNING_IKKEDAEKKET) {
407 result.add(a);
408 }
409 }
410 Collections.sort(result );
411 return result;
412 }
413
414 ///////////////////////////////////////////////////////////
415 private String calculateExtendedBkKoreliste(ExtendedBean eb, Address orgAddress, Address targetAddress) {
416 String inject;
417 if (eb.afstand <= 0.500) {
418 inject = ".";
419 } else {
420 inject = "..";
421 }
422 return AddressUtils.injectIntoBk(targetAddress.koreliste, inject);
423 }
424
425 private Set<String> findVejAliaser(String vejnavn) {
426 vejnavn = vejnavn.toLowerCase();
427 HashSet<String> aliasSet = new HashSet<String>();
428 aliasSet.add(vejnavn);
429
430 aliasSet.add(vejnavn.replace("u", "ü") );
431 aliasSet.add(vejnavn.replace("ü", "u") );
432
433 aliasSet.add(vejnavn.replace("alle", "allé") );
434 aliasSet.add(vejnavn.replace("allé", "alle") );
435
436 aliasSet.add(vejnavn.replace("dronningens", "dr") );
437 aliasSet.add(vejnavn.replace("dr.", "dronningens") );
438 aliasSet.add(vejnavn.replace("dr ", "dronningens") );
439
440 aliasSet.add(vejnavn.replace("dronning", "dr") );
441 aliasSet.add(vejnavn.replace("dr.", "dronning") );
442 aliasSet.add(vejnavn.replace("dr ", "dronning") );
443
444 aliasSet.add(vejnavn.replace("kng", "kongen") );
445 aliasSet.add(vejnavn.replace("kongen", "kng") );
446
447 aliasSet.add(vejnavn.replace("kvt", "kvarter") );
448 aliasSet.add(vejnavn.replace("kvarter", "kvt") );
449
450 aliasSet.add(vejnavn.replace("gl", "gammel") );
451 aliasSet.add(vejnavn.replace("gammel", "gl") );
452
453 aliasSet.add(vejnavn.replace("lille", "ll") );
454 aliasSet.add(vejnavn.replace("ll ", "lille") );
455 aliasSet.add(vejnavn.replace("ll.", "lille") );
456
457 aliasSet.add(vejnavn.replace("store", "st") );
458 aliasSet.add(vejnavn.replace("st ", "store") );
459 aliasSet.add(vejnavn.replace("st.", "store") );
460
461 aliasSet.add(vejnavn.replace("søndre", "sdr") );
462 aliasSet.add(vejnavn.replace("sdr", "søndre") );
463
464
465 aliasSet.add(vejnavn.replace("nørre", "nr") );
466 aliasSet.add(vejnavn.replace("nr", "nørre") );
467
468 aliasSet.add(vejnavn.replace("nordre", "ndr") );
469 aliasSet.add(vejnavn.replace("ndr", "nordre") );
470
471 aliasSet.add(vejnavn.replace("sankt", "skt") );
472 aliasSet.add(vejnavn.replace("sankt", "sct") );
473 aliasSet.add(vejnavn.replace("skt", "sankt") );
474
475 aliasSet.add(vejnavn.replace("skt", "sct") );
476 aliasSet.add(vejnavn.replace("sct", "skt") );
477
478
479 //alternative måder at stave vej/gade/alle
480 aliasSet.add(vejnavn.replace("vej", "ve") );
481 aliasSet.add(vejnavn.replace("vej", "vj") );
482 aliasSet.add(vejnavn.replace("vej", "v") );
483
484 aliasSet.add(vejnavn.replace("alle", "all") );
485 aliasSet.add(vejnavn.replace("allé", "all") );
486 aliasSet.add(vejnavn.replace("alle", "allú") ); //Fundet i logs.hentruteinfo
487 aliasSet.add(vejnavn.replace("allé", "allú") );
488
489 aliasSet.add(vejnavn.replace("gade", "gaed") ); //Fundet i logs.hentruteinfo
490
491
492 // Opbyg æøå varianter over alle fundne aliaser
493
494 @SuppressWarnings("unchecked")
495 HashSet<String> variants = (HashSet<String>) aliasSet.clone();
496
497 for (String vVejnavn : variants) {
498 // danske tegn 1
499 aliasSet.add( vVejnavn.replace("æ", "ae") );
500 aliasSet.add( vVejnavn.replace("ø", "oe") );
501 aliasSet.add( vVejnavn.replace("å", "aa") );
502 aliasSet.add( vVejnavn.replace("ae", "æ") );
503 aliasSet.add( vVejnavn.replace("oe", "ø") );
504 aliasSet.add( vVejnavn.replace("aa", "å") );
505
506 //danske tegn 2
507 aliasSet.add( vVejnavn.replace("æ", "ae").replace("ø", "oe") );
508 aliasSet.add( vVejnavn.replace("æ", "ae").replace("å", "aa") );
509 aliasSet.add( vVejnavn.replace("ø", "ae").replace("å", "aa") );
510 aliasSet.add( vVejnavn.replace("ae", "æ").replace("oe","ø") );
511 aliasSet.add( vVejnavn.replace("ae", "æ").replace("aa","å") );
512 aliasSet.add( vVejnavn.replace("oe", "ø").replace("aa", "å") );
513
514 //danske tegn 3
515 aliasSet.add( vejnavn.replace("æ", "ae").replace("ø", "oe").replace("å", "aa") );
516 aliasSet.add( vejnavn.replace("ae", "æ").replace("oe", "ø").replace("aa", "å") );
517 }
518
519 return aliasSet;
520 }
521
522
523 }

  ViewVC Help
Powered by ViewVC 1.1.20