/[projects]/dao/DaoAdresseService/src/main/java/dk/daoas/daoadresseservice/AddressSearch.java
ViewVC logotype

Contents of /dao/DaoAdresseService/src/main/java/dk/daoas/daoadresseservice/AddressSearch.java

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20