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

  ViewVC Help
Powered by ViewVC 1.1.20