/[projects]/dao/DaoAdresseVedligehold/src/main/java/dk/daoas/adressevedligehold/AddressManager.java
ViewVC logotype

Contents of /dao/DaoAdresseVedligehold/src/main/java/dk/daoas/adressevedligehold/AddressManager.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2911 - (show annotations) (download)
Thu Feb 4 08:32:08 2016 UTC (8 years, 3 months ago) by torben
File size: 18455 byte(s)
add rule regarding that house number must be less than 1000
1 package dk.daoas.adressevedligehold;
2
3 import java.sql.SQLException;
4 import java.util.ArrayList;
5 import java.util.Arrays;
6 import java.util.Collections;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Map.Entry;
10 import java.util.TreeMap;
11
12 import org.apache.commons.lang3.StringUtils;
13
14 import dk.daoas.adressevedligehold.AddressSourceEntry.EntryType;
15 import dk.daoas.adressevedligehold.beans.Address;
16 import dk.daoas.adressevedligehold.beans.Address.AddressState;
17 import dk.daoas.adressevedligehold.db.DatabaseLayerImplementation;
18 import dk.daoas.adressevedligehold.tasks.TaskLogger;
19 import dk.daoas.adressevedligehold.util.DeduplicateHelper;
20 import dk.daoas.adressevedligehold.util.MiscUtils;
21 import dk.daoas.adressevedligehold.util.TimingHelper;
22
23 /*
24 * TODO: håndtering af entry dupletter ! (+ rapportering af dem)
25
26
27
28 */
29
30 public class AddressManager {
31
32 private TaskLogger logger = TaskLogger.getInstance();
33
34
35 List<Address> addressList;
36
37 Map<Integer, TreeMap<Short, ArrayList<Address>> > searchStructure;
38
39 ArrayList<AddressSourceEntry> rejectedEntries = new ArrayList<AddressSourceEntry>();
40
41 Map<Integer,String> unknownStreets = new TreeMap<Integer, String>();
42
43 Map<Short,Short> dbkBaneMap = new TreeMap<Short,Short>();
44
45 public AddressManager() throws SQLException {
46 DatabaseLayerImplementation db = new DatabaseLayerImplementation();
47
48 searchStructure = new TreeMap<Integer, TreeMap<Short, ArrayList<Address>> >();
49
50 addressList = db.getAllAdresses();
51
52 DeduplicateHelper<Integer> intHelper = new DeduplicateHelper<Integer>();
53 DeduplicateHelper<Short> shortHelper = new DeduplicateHelper<Short>();
54
55 List<ArrayList<Address>> arraylistCache = new ArrayList<ArrayList<Address>>();
56
57 TimingHelper timer = new TimingHelper();
58
59 for (Address a : addressList) {
60 Integer gadeid = intHelper.getInstance( a.gadeid );
61 Short husnr = shortHelper.getInstance( a.husnr );
62 TreeMap<Short, ArrayList<Address>> gade = searchStructure.get( gadeid );
63
64 if (a.dbkBane > 0 && a.postnr<=4999) {
65 Short bane = dbkBaneMap.get(a.postnr);
66 if (bane == null) {
67 dbkBaneMap.put(a.postnr, a.dbkBane);
68 }
69 }
70
71 if (gade == null) {
72 gade = new TreeMap<Short,ArrayList<Address>>();
73 searchStructure.put(gadeid, gade);
74 }
75
76 ArrayList<Address> litraList = gade.get(husnr);
77 if (litraList == null) {
78 litraList = new ArrayList<Address>();
79 gade.put(husnr, litraList);
80 arraylistCache.add(litraList);
81 }
82
83 litraList.add(a);
84 }
85
86 for (ArrayList<Address> list : arraylistCache) {
87 list.trimToSize();
88 }
89
90 logger.info("AddressManager ready, elapsed " + timer.getElapsed() + "ms");
91
92
93 }
94
95 public void closeUnvisitedAddresses(String distributor, EntryUgedage ugedage) {
96 for (Address addr : addressList) {
97 if (addr.distributor == null)
98 continue;
99
100 if (addr.distributor.equals(distributor) == false)//irrelevant for denne indlæsning
101 continue;
102
103 int closedCount = 0;
104
105 if (addr.visitedMan == false && ugedage.mandag) {
106 if (addr.ruteMandag != null) {
107 addr.ruteMandag = null;
108 addr.korelisteMandag = null;
109 addr.stateMan = AddressState.CLOSED;
110 closedCount++;
111 }
112 }
113 if (addr.visitedTir == false && ugedage.tirsdag) {
114 if (addr.ruteTirsdag != null) {
115 addr.ruteTirsdag = null;
116 addr.korelisteTirsdag = null;
117 addr.stateTir = AddressState.CLOSED;
118 closedCount++;
119 }
120 }
121
122 if (addr.visitedOns == false && ugedage.onsdag) {
123 if (addr.ruteOnsdag != null) {
124 addr.ruteOnsdag = null;
125 addr.korelisteOnsdag = null;
126 addr.stateOns = AddressState.CLOSED;
127 closedCount++;
128 }
129 }
130
131 if (addr.visitedTor == false && ugedage.torsdag) {
132 if (addr.ruteTorsdag != null) {
133 addr.ruteTorsdag = null;
134 addr.korelisteTorsdag = null;
135 addr.stateTor = AddressState.CLOSED;
136 closedCount++;
137 }
138 }
139
140 if (addr.visitedFre == false && ugedage.fredag) {
141 if (addr.ruteFredag != null) {
142 addr.ruteFredag = null;
143 addr.korelisteFredag = null;
144 addr.stateFre = AddressState.CLOSED;
145 closedCount++;
146 }
147 }
148
149 if (addr.visitedLor == false && ugedage.lordag) {
150 if (addr.ruteLordag != null) {
151 addr.ruteLordag = null;
152 addr.korelisteLordag = null;
153 addr.stateLor = AddressState.CLOSED;
154 closedCount++;
155 }
156 }
157
158 if (addr.visitedSon == false && ugedage.sondag) {
159 if (addr.ruteSondag != null) {
160 addr.ruteSondag = null;
161 addr.korelisteSondag = null;
162 addr.stateSon = AddressState.CLOSED;
163 closedCount++;
164 }
165 }
166
167 if (addr.state == AddressState.NOT_CHANGED && closedCount>0) {
168 addr.state = AddressState.CLOSED;
169 }
170
171 }
172 }
173 public void dumpChanged() {
174 int count = 0;
175 for (Address addr : addressList) {
176 if (addr.state == AddressState.NOT_CHANGED) {
177 continue;
178 }
179 /*if (addr.stateMan == AddressState.NOT_CHANGED || addr.stateMan == AddressState.CREATED) {
180 continue;
181 }*/
182
183 if (addr.stateMan != AddressState.MODIFIED ) {
184 continue;
185 }
186
187 logger.info(addr.state + ": " + addr.toStringExtended() );
188 logger.info(addr.getRuteString() );
189
190 if (count++ > 50)
191 return;
192 }
193 }
194
195 public void writeBackChanges() {
196 logger.info("Writing back changes");
197 TimingHelper timer = new TimingHelper();
198
199 List<Address> updates = new ArrayList<Address>(1024*1024);
200 List<Address> inserts = new ArrayList<Address>(16*1024);
201
202 for (Address addr : addressList) {
203 if (addr.state == AddressState.CREATED) {
204 inserts.add(addr);
205 }
206 if (addr.state == AddressState.MODIFIED || addr.state == AddressState.OPENED || addr.state == AddressState.CLOSED) {
207 updates.add(addr);
208 }
209 }
210
211 DatabaseLayerImplementation db = new DatabaseLayerImplementation();
212
213 db.updateAddresses(updates);
214 db.saveNewAddresses(inserts);
215
216
217
218 logger.info("Writeback done: elapsed " + timer.getElapsed() + "ms.");
219 }
220
221
222 public void visit(AddressSourceEntry entry) {
223 if (entry.type == EntryType.TypeSingleAddress) {
224 visitSingle(entry);
225 } else {
226 visitRange(entry);
227 }
228 }
229
230 private void visitSingle(AddressSourceEntry entry) {
231 TreeMap<Short, ArrayList<Address>> gade = searchStructure.get( entry.gadeid );
232 if (gade == null) {
233 if (! unknownStreets.containsKey(entry.gadeid)) {
234 unknownStreets.put(entry.gadeid, entry.vejnavn);
235 }
236
237 createFromEntry(entry); // if we get here there was no match - so we need to create it
238 return;
239 }
240
241 ArrayList<Address> litraList = gade.get(entry.husnr);
242 if (litraList == null) {
243 createFromEntry(entry); // if we get here there was no match - so we need to create it
244 return;
245 }
246 boolean found = false;
247 for (Address addr : litraList) {
248 if (addr.husnrbogstav.equals(entry.litra) ) {
249 updateAddress(addr, entry);
250 found = true; // 1 visit should be enough but as long as there's duplicates on gadeid+husnr+litra we will visit them all
251 //when the issue with duplicates is resolved this should be reverted to a return or break
252 }
253 }
254 if (found == false) {
255 createFromEntry(entry); // if we get here there was no match - so we need to create it
256 }
257 }
258
259 private void visitRange(AddressSourceEntry entry) {
260
261 TreeMap<Short, ArrayList<Address>> gade = searchStructure.get( entry.gadeid );
262 if (gade == null) {
263 if (! unknownStreets.containsKey(entry.gadeid)) {
264 unknownStreets.put(entry.gadeid, entry.vejnavn);
265 }
266
267 logger.info("[Range] Ukendt gadeID " + entry);
268 return;
269 }
270
271 for (Entry<Short, ArrayList<Address>> husnrEntry: gade.entrySet()) {
272
273 short husnummer = husnrEntry.getKey();
274
275 if ( (entry.husnr % 2) != (husnummer%2) ){ //lige/ulige skal passe sammen
276 continue;
277 }
278
279 if ( husnummer < entry.husnr || husnummer > entry.tilHusnr) {
280 continue;
281 }
282
283 ArrayList<Address> litraList = husnrEntry.getValue();
284
285 /* a=adressetabel u=input
286 * and (a.husnr>u.FraHusNr OR (a.husnr=u.FraHusNr AND a.HusnrBogstav >= u.FraBog))
287 * AND (a.husnr<u.TilHusNr OR (a.husnr=u.TilHusNr AND a.HusnrBogstav <= u.TilBog))
288 */
289
290
291 for (Address addr: litraList) {
292 if (addr.husnr > entry.husnr || (addr.husnr == entry.husnr && addr.husnrbogstav.compareTo(entry.litra) >= 0 )) {
293 //Using nested IF instead of &&
294 if (addr.husnr < entry.tilHusnr || (addr.husnr == entry.tilHusnr && addr.husnrbogstav.compareTo(entry.tilLitra) <= 0 )) {
295 updateAddress(addr, entry);
296 }
297 }
298 }
299 }
300 }
301
302
303
304 private void updateAddress(Address addr, AddressSourceEntry entry) {
305 if ( addr.distributor != null && addr.distributor.equals(entry.distributor) == false) {
306 rejectedEntries.add(entry);
307 logger.info("Afviser " + entry);
308 return;
309 }
310
311
312
313 if (entry.ugedage.mandag) {
314 if (addr.visitedMan == false) {
315 addr.visitedMan = true;
316 if (addr.ruteMandag == null) {
317 addr.stateMan = AddressState.OPENED;
318 addr.ruteMandag = entry.rute;
319 addr.korelisteMandag = entry.koreliste;
320 } else {
321
322 if (StringUtils.equals(addr.ruteMandag, entry.rute) == false || StringUtils.equals(addr.korelisteMandag, entry.koreliste) == false) {
323 addr.stateMan = AddressState.MODIFIED;
324 addr.ruteMandag = entry.rute;
325 addr.korelisteMandag = entry.koreliste;
326 }
327 }
328 } else {
329 logger.info( "Double visit monday " + addr);
330 }
331
332 }
333
334
335 if (entry.ugedage.tirsdag) {
336 if (addr.visitedTir == false) {
337 addr.visitedTir = true;
338 if (addr.ruteTirsdag == null) {
339 addr.stateTir = AddressState.OPENED;
340 addr.ruteTirsdag = entry.rute;
341 addr.korelisteTirsdag = entry.koreliste;
342 } else {
343
344 if (StringUtils.equals(addr.ruteTirsdag, entry.rute) == false || StringUtils.equals(addr.korelisteTirsdag, entry.koreliste) == false) {
345 addr.stateTir = AddressState.MODIFIED;
346 addr.ruteTirsdag = entry.rute;
347 addr.korelisteTirsdag = entry.koreliste;
348 }
349 }
350 } else {
351 logger.info( "Double visit tuesday " + addr);
352 }
353 }
354
355 if (entry.ugedage.onsdag) {
356 if (addr.visitedOns == false) {
357 addr.visitedOns = true;
358 if (addr.ruteOnsdag == null) {
359 addr.stateOns = AddressState.OPENED;
360 addr.ruteOnsdag = entry.rute;
361 addr.korelisteOnsdag = entry.koreliste;
362 } else {
363
364 if (StringUtils.equals(addr.ruteOnsdag, entry.rute) == false || StringUtils.equals(addr.korelisteOnsdag, entry.koreliste) == false) {
365 addr.stateOns = AddressState.MODIFIED;
366 addr.ruteOnsdag = entry.rute;
367 addr.korelisteOnsdag = entry.koreliste;
368 }
369 }
370 } else {
371 logger.info( "Double visit wednesday " + addr);
372 }
373 }
374
375
376 if (entry.ugedage.torsdag) {
377 if (addr.visitedTor == false) {
378 addr.visitedTor = true;
379 if (addr.ruteTorsdag == null) {
380 addr.stateTor = AddressState.OPENED;
381 addr.ruteTorsdag = entry.rute;
382 addr.korelisteTorsdag = entry.koreliste;
383 } else {
384
385
386 if (StringUtils.equals(addr.ruteTorsdag, entry.rute) == false || StringUtils.equals(addr.korelisteTorsdag, entry.koreliste) == false) {
387 addr.stateTor = AddressState.MODIFIED;
388 addr.ruteTorsdag = entry.rute;
389 addr.korelisteTorsdag = entry.koreliste;
390 }
391 }
392 } else {
393 logger.info( "Double visit thursday " + addr);
394 }
395 }
396
397
398 if (entry.ugedage.fredag) {
399 if (addr.visitedFre == false) {
400 addr.visitedFre = true;
401 if (addr.ruteFredag == null) {
402 addr.stateFre = AddressState.OPENED;
403 addr.ruteFredag = entry.rute;
404 addr.korelisteFredag = entry.koreliste;
405 } else {
406
407 if (StringUtils.equals(addr.ruteFredag, entry.rute) == false || StringUtils.equals(addr.korelisteFredag, entry.koreliste) == false) {
408 addr.stateFre = AddressState.MODIFIED;
409 addr.ruteFredag = entry.rute;
410 addr.korelisteFredag = entry.koreliste;
411 }
412 }
413 } else {
414 logger.info( "Double visit friday " + addr);
415 }
416 }
417
418
419 if (entry.ugedage.lordag) {
420 if (addr.visitedLor == false) {
421 addr.visitedLor = true;
422 if (addr.ruteLordag == null) {
423 addr.stateLor = AddressState.OPENED;
424 addr.ruteLordag = entry.rute;
425 addr.korelisteLordag = entry.koreliste;
426 } else {
427
428
429 if (StringUtils.equals(addr.ruteLordag, entry.rute) == false || StringUtils.equals(addr.korelisteLordag, entry.koreliste) == false) {
430 addr.stateLor = AddressState.MODIFIED;
431 addr.ruteLordag = entry.rute;
432 addr.korelisteLordag = entry.koreliste;
433 }
434 }
435 } else {
436 logger.info( "Double visit saturday " + addr);
437 }
438 }
439
440
441 if (entry.ugedage.sondag) {
442 if (addr.visitedSon == false) {
443 addr.visitedSon = true;
444 if (addr.ruteSondag == null) {
445 addr.stateSon = AddressState.OPENED;
446 addr.ruteSondag = entry.rute;
447 addr.korelisteSondag = entry.koreliste;
448 } else {
449
450 if (StringUtils.equals(addr.ruteSondag, entry.rute) == false || StringUtils.equals(addr.korelisteSondag, entry.koreliste) == false) {
451 addr.stateSon = AddressState.MODIFIED;
452 addr.ruteSondag = entry.rute;
453 addr.korelisteSondag = entry.koreliste;
454 }
455 }
456 } else {
457 logger.info( "Double visit sunday " + addr);
458 }
459 }
460
461
462
463 //addr.visited = true;
464 if (addr.state == AddressState.NOT_CHANGED) {
465 if (addr.distributor == null) {
466 addr.state = AddressState.OPENED;
467 addr.distributor = entry.distributor;
468 } else {
469 if (addr.stateMan != AddressState.NOT_CHANGED || addr.stateTir != AddressState.NOT_CHANGED
470 || addr.stateOns != AddressState.NOT_CHANGED || addr.stateTor != AddressState.NOT_CHANGED
471 || addr.stateFre != AddressState.NOT_CHANGED || addr.stateLor != AddressState.NOT_CHANGED || addr.stateSon != AddressState.NOT_CHANGED ){
472
473 addr.state = AddressState.MODIFIED;
474 }
475 }
476 }
477
478 updateDbkBane(addr);
479
480 }
481
482
483
484 private void createFromEntry(AddressSourceEntry entry) {
485 if (entry.husnr >= 1000) { //husnumre i DK må kun være på 3 cifre
486 return;
487 }
488
489 if (entry.husnr == 999) {
490 return;
491 }
492 if (entry.kommunekode == 0 || entry.vejkode == 0) {
493 return;
494 }
495 if (entry.kommunekode < 100) {
496 return;
497 }
498
499 if (entry.gadeid == 0) {
500 return;
501 }
502
503 String gadeidStr = Integer.toString(entry.gadeid);
504 if (gadeidStr.length() != 9) {
505 return;
506 }
507 if (Short.parseShort(gadeidStr.substring(0, 4)) != entry.postnr) {
508 return; //gadeid / postnr mismatch
509 }
510
511
512
513 logger.info("Opretter adresse ud fra " + entry);
514
515 Address a = new Address();
516 a.state = AddressState.CREATED;
517
518 a.distributor = entry.distributor;
519 a.gadeid = entry.gadeid;
520 a.kommunekode = entry.kommunekode;
521 a.vejkode = entry.vejkode;
522 a.vejnavn = entry.vejnavn;
523 a.husnr = entry.husnr;
524 a.husnrbogstav = entry.litra;
525 a.postnr = entry.postnr;
526 //a.visited = true;
527
528 if (entry.ugedage.mandag) {
529 a.ruteMandag = entry.rute;
530 a.korelisteMandag = entry.koreliste;
531 }
532 if (entry.ugedage.tirsdag) {
533 a.ruteTirsdag = entry.rute;
534 a.korelisteTirsdag = entry.koreliste;
535 }
536 if (entry.ugedage.onsdag) {
537 a.ruteOnsdag = entry.rute;
538 a.korelisteOnsdag = entry.koreliste;
539 }
540 if (entry.ugedage.torsdag) {
541 a.ruteTorsdag = entry.rute;
542 a.korelisteTorsdag = entry.koreliste;
543 }
544 if (entry.ugedage.fredag) {
545 a.ruteFredag = entry.rute;
546 a.korelisteFredag = entry.koreliste;
547 }
548 if (entry.ugedage.lordag) {
549 a.ruteLordag = entry.rute;
550 a.korelisteLordag = entry.koreliste;
551 }
552 if (entry.ugedage.sondag) {
553 a.ruteSondag = entry.rute;
554 a.korelisteLordag = entry.koreliste;
555 }
556
557 updateDbkBane(a);
558
559 // Nu er det nye adresse object oprettet - nu skal det gemmes i søge strukturen og totallisten
560
561
562 TreeMap<Short, ArrayList<Address>> gade = searchStructure.get( a.gadeid );
563
564 if (gade == null) {
565 gade = new TreeMap<Short,ArrayList<Address>>();
566 searchStructure.put(a.gadeid, gade);
567 }
568
569 ArrayList<Address> litraList = gade.get(a.husnr);
570 if (litraList == null) {
571 litraList = new ArrayList<Address>();
572 gade.put(a.husnr, litraList);
573 }
574
575 litraList.add(a);
576 addressList.add(a);
577
578 }
579
580
581
582 /*
583 DAO:
584 UPDATE fulddaekning.adressetabel
585 SET dbkbane = case
586 when substr(korelisteMa,1,2) IN ('07','10','11','12','14','15','16','18','19','20') then 205 #DAO-BRA
587 when substr(korelisteMa,1,2) BETWEEN 24 and 30 then 201 #DAO-Ovrige
588 else 202 #dao syd (52-99=
589 END
590 WHERE distributor='DAO'
591 AND ruteMa is not null;
592
593 FD: Altid 200
594 NS: Altid 204
595 BK: 195,196,197,198
596 */
597
598 private void updateDbkBane(Address a) {
599 List<Short> daoBane205 = Arrays.asList( new Short[] {7,10,11,12,12,14,15,16,18,19,20} );
600
601
602 Short bane = null;
603
604 switch (a.distributor) {
605 case "BK":
606 bane = dbkBaneMap.get(a.postnr);
607 break;
608 case "DAO":
609 String koreliste = MiscUtils.firstNonNull(a.korelisteMandag,a.korelisteLordag, a.korelisteSondag); //DAO har kun 3 dækningstyper
610 short first2 = Short.parseShort( koreliste.substring(0,2) );
611 if ( daoBane205.contains(first2) ) {
612 bane = 205;
613 } else if (first2 >= 24 && first2<=30) {
614 bane = 201;
615 } else {
616 bane = 202;
617 }
618
619 break;
620 case "FD":
621 bane = 200;
622 break;
623 case "NS":
624 bane = 204;
625 break;
626 default:
627 throw new RuntimeException("Ukendt distributor: " + a.distributor); //Silence findBugs
628 }
629
630 if (bane == null) {
631 throw new RuntimeException("Ukendt bane for postnr: " + a.postnr);
632 }
633
634 if (a.dbkBane != bane) {
635 a.dbkBane = bane;
636 if (a.state ==AddressState.NOT_CHANGED) {
637 a.state = AddressState.MODIFIED;
638 }
639 }
640 }
641
642 public List<Address> getAddressList() {
643 return Collections.unmodifiableList(addressList);
644 }
645
646 public Map<Integer,String> getUnknownStreets() {
647 return Collections.unmodifiableMap( unknownStreets );
648 }
649
650
651
652 public int getRejectedCount() {
653 return rejectedEntries.size();
654 }
655
656 }

  ViewVC Help
Powered by ViewVC 1.1.20