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

  ViewVC Help
Powered by ViewVC 1.1.20