/[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 2443 - (show annotations) (download)
Fri Mar 13 13:06:17 2015 UTC (9 years, 2 months ago) by torben
File size: 19497 byte(s)
Ret potentiel NPE fejl
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 if (targetAddress.rute == null) { //hvis targetAdress.rute er null så er adressen ikke dækket alligevel
414 return null;
415 }
416
417 // ///////////////////////////////////////////////////////////////////
418 switch( eb.transport) {
419 case "cykel":
420 if (eb.afstand < 0.151) {
421 return "." + targetAddress.rute;
422 } else if (eb.afstand < 0.501) {
423 return ".." + targetAddress.rute;
424 } else if (eb.afstand < 0.701) {
425 return "..." + targetAddress.rute;
426 } else if (eb.afstand < 0.501) {
427 return "...." + targetAddress.rute;
428 }
429 break;
430 case "scooter":
431 if (eb.afstand < 0.151) {
432 return "." + targetAddress.rute;
433 } else if (eb.afstand < 0.801) {
434 return ".." + targetAddress.rute;
435 } else if (eb.afstand < 1.201) {
436 return "..." + targetAddress.rute;
437 } else if (eb.afstand < 2.101) {
438 return "...." + targetAddress.rute;
439 }
440 break;
441 case "bil":
442 if (eb.afstand < 0.151) {
443 return "." + targetAddress.rute;
444 } else if (eb.afstand < 1.001) {
445 return ".." + targetAddress.rute;
446 } else if (eb.afstand < 1.601) {
447 return "..." + targetAddress.rute;
448 } else if (eb.afstand < 2.601) {
449 return "...." + targetAddress.rute;
450 }
451 break;
452 }
453 return null;
454 }
455
456 public List<Address> getNonCoveredAddresses() {
457 List<Address> result = new ArrayList<Address>(60000);
458 for (Address a : alleAdresser) {
459 if ( a.daekningsType == DaekningsType.DAEKNING_IKKEDAEKKET) {
460 result.add(a);
461 }
462 }
463 Collections.sort(result );
464 return result;
465 }
466
467 ///////////////////////////////////////////////////////////
468 private String calculateExtendedBkKoreliste(ExtendedBean eb, Address orgAddress, Address targetAddress) {
469 String inject;
470 if (eb.afstand <= 0.500) {
471 inject = ".";
472 } else {
473 inject = "..";
474 }
475 return AddressUtils.injectIntoBk(targetAddress.koreliste, inject);
476 }
477
478 private Set<String> findVejAliaser(String vejnavn) {
479 vejnavn = vejnavn.toLowerCase();
480 HashSet<String> aliasSet = new HashSet<String>();
481 aliasSet.add(vejnavn);
482
483 aliasSet.add(vejnavn.replace("u", "ü") );
484 aliasSet.add(vejnavn.replace("ü", "u") );
485
486 aliasSet.add(vejnavn.replace("alle", "allé") );
487 aliasSet.add(vejnavn.replace("allé", "alle") );
488
489 aliasSet.add(vejnavn.replace("dronningens", "dr") );
490 aliasSet.add(vejnavn.replace("dr.", "dronningens") );
491 aliasSet.add(vejnavn.replace("dr ", "dronningens") );
492
493 aliasSet.add(vejnavn.replace("dronning", "dr") );
494 aliasSet.add(vejnavn.replace("dr.", "dronning") );
495 aliasSet.add(vejnavn.replace("dr ", "dronning") );
496
497 aliasSet.add(vejnavn.replace("kng", "kongen") );
498 aliasSet.add(vejnavn.replace("kongen", "kng") );
499
500 aliasSet.add(vejnavn.replace("kvt", "kvarter") );
501 aliasSet.add(vejnavn.replace("kvarter", "kvt") );
502
503 aliasSet.add(vejnavn.replace("gl", "gammel") );
504 aliasSet.add(vejnavn.replace("gammel", "gl") );
505
506 aliasSet.add(vejnavn.replace("lille", "ll") );
507 aliasSet.add(vejnavn.replace("ll ", "lille") );
508 aliasSet.add(vejnavn.replace("ll.", "lille") );
509
510 aliasSet.add(vejnavn.replace("store", "st") );
511 aliasSet.add(vejnavn.replace("st ", "store") );
512 aliasSet.add(vejnavn.replace("st.", "store") );
513
514 aliasSet.add(vejnavn.replace("søndre", "sdr") );
515 aliasSet.add(vejnavn.replace("sdr", "søndre") );
516
517
518 aliasSet.add(vejnavn.replace("nørre", "nr") );
519 aliasSet.add(vejnavn.replace("nr", "nørre") );
520
521 aliasSet.add(vejnavn.replace("nordre", "ndr") );
522 aliasSet.add(vejnavn.replace("ndr", "nordre") );
523
524 aliasSet.add(vejnavn.replace("sankt", "skt") );
525 aliasSet.add(vejnavn.replace("sankt", "sct") );
526 aliasSet.add(vejnavn.replace("skt", "sankt") );
527
528 aliasSet.add(vejnavn.replace("skt", "sct") );
529 aliasSet.add(vejnavn.replace("sct", "skt") );
530
531
532 // fornavn forkortelser
533 aliasSet.add(vejnavn.replace("john", "j") );
534 aliasSet.add(vejnavn.replace("thomas", "th") );
535 aliasSet.add(vejnavn.replace("thorvald", "th") );
536
537
538 // Romertal
539 aliasSet.add(vejnavn.replace("1", "i") );
540 aliasSet.add(vejnavn.replace("i", "1") );
541
542 aliasSet.add(vejnavn.replace("2", "ii") );
543 aliasSet.add(vejnavn.replace("ii", "2") );
544
545 aliasSet.add(vejnavn.replace("3", "iii") );
546 aliasSet.add(vejnavn.replace("iii", "3") );
547
548 aliasSet.add(vejnavn.replace("4", "iv") );
549 aliasSet.add(vejnavn.replace("iv", "4") );
550
551 aliasSet.add(vejnavn.replace("5", "v") );
552 aliasSet.add(vejnavn.replace("v", "5") );
553
554 aliasSet.add(vejnavn.replace("6", "vi") );
555 aliasSet.add(vejnavn.replace("vi", "6") );
556
557 aliasSet.add(vejnavn.replace("7", "vii") );
558 aliasSet.add(vejnavn.replace("vii", "7") );
559
560 aliasSet.add(vejnavn.replace("8", "viii") );
561 aliasSet.add(vejnavn.replace("viii", "8") );
562
563 aliasSet.add(vejnavn.replace("9", "ix") );
564 aliasSet.add(vejnavn.replace("ix", "9") );
565
566 aliasSet.add(vejnavn.replace("10", "x") );
567 aliasSet.add(vejnavn.replace("x", "10") );
568
569
570 //alternative måder at stave vej/gade/alle
571 aliasSet.add(vejnavn.replace("vej", "ve") );
572 aliasSet.add(vejnavn.replace("vej", "vj") );
573 aliasSet.add(vejnavn.replace("vej", "v") );
574 aliasSet.add(vejnavn.replace("vej", "vejen") );
575 aliasSet.add(vejnavn.replace("vejen", "vej") );
576
577 aliasSet.add(vejnavn.replace("alle", "all") );
578 aliasSet.add(vejnavn.replace("allé", "all") );
579 aliasSet.add(vejnavn.replace("alle", "allú") ); //Fundet i logs.hentruteinfo
580 aliasSet.add(vejnavn.replace("allé", "allú") );
581
582 aliasSet.add(vejnavn.replace("gade", "gaed") ); //Fundet i logs.hentruteinfo
583 aliasSet.add(vejnavn.replace("gade", "gde") );
584
585 aliasSet.add(vejnavn.replace("plads", "pl") );
586 aliasSet.add(vejnavn.replace("vænget", "vænge") );
587
588
589 // Opbyg æøå varianter over alle fundne aliaser
590
591 @SuppressWarnings("unchecked")
592 HashSet<String> variants = (HashSet<String>) aliasSet.clone();
593
594 for (String vVejnavn : variants) {
595 // danske tegn 1
596 aliasSet.add( vVejnavn.replace("æ", "ae") );
597 aliasSet.add( vVejnavn.replace("ø", "oe") );
598 aliasSet.add( vVejnavn.replace("å", "aa") );
599 aliasSet.add( vVejnavn.replace("ae", "æ") );
600 aliasSet.add( vVejnavn.replace("oe", "ø") );
601 aliasSet.add( vVejnavn.replace("aa", "å") );
602
603 //danske tegn 2
604 aliasSet.add( vVejnavn.replace("æ", "ae").replace("ø", "oe") );
605 aliasSet.add( vVejnavn.replace("æ", "ae").replace("å", "aa") );
606 aliasSet.add( vVejnavn.replace("ø", "ae").replace("å", "aa") );
607 aliasSet.add( vVejnavn.replace("ae", "æ").replace("oe","ø") );
608 aliasSet.add( vVejnavn.replace("ae", "æ").replace("aa","å") );
609 aliasSet.add( vVejnavn.replace("oe", "ø").replace("aa", "å") );
610
611 //danske tegn 3
612 aliasSet.add( vejnavn.replace("æ", "ae").replace("ø", "oe").replace("å", "aa") );
613 aliasSet.add( vejnavn.replace("ae", "æ").replace("oe", "ø").replace("aa", "å") );
614 }
615
616 return aliasSet;
617 }
618
619
620 }

  ViewVC Help
Powered by ViewVC 1.1.20