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

  ViewVC Help
Powered by ViewVC 1.1.20