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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20