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

  ViewVC Help
Powered by ViewVC 1.1.20