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

  ViewVC Help
Powered by ViewVC 1.1.20