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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20