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