From 8bb5373a38f43d83c041ec0739459e38eb7cc3e2 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Fri, 1 Jul 2022 14:48:10 +0200 Subject: feat(matching): optimize order of address search results --- .../eidas/v2/controller/AdresssucheController.java | 78 ++++++++++++++-------- .../v2/test/utils/AddressSearchResultTest.java | 55 +++++++++++++++ 2 files changed, 105 insertions(+), 28 deletions(-) create mode 100644 modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/AddressSearchResultTest.java diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java index 6f49c700..1c47f02c 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java @@ -25,6 +25,7 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.controller; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -67,17 +68,17 @@ public class AdresssucheController { public static final String PARAM_VILLAGE = "village"; public static final String PARAM_STREET = "street"; public static final String PARAM_NUMBER = "number"; - + @Autowired private ZmrAddressSoapClient client; @Autowired private IPendingRequestIdGenerationStrategy pendingReqGeneration; - + /** * Performs search for addresses in ZMR. */ - @RequestMapping(value = {MsEidasNodeConstants.ENDPOINT_RESIDENCY_SEARCH}, method = {RequestMethod.POST}) + @RequestMapping(value = { MsEidasNodeConstants.ENDPOINT_RESIDENCY_SEARCH }, method = { RequestMethod.POST }) public ResponseEntity search( @RequestParam(PARAM_POSTLEITZAHL) String postleitzahl, @RequestParam(PARAM_MUNIPICALITY) String municipality, @@ -90,26 +91,26 @@ public class AdresssucheController { municipality.replaceAll("[\r\n]", ""), village.replaceAll("[\r\n]", ""), street.replaceAll("[\r\n]", ""), - number.replaceAll("[\r\n]", "")); + number.replaceAll("[\r\n]", "")); try { pendingReqGeneration.validateAndGetPendingRequestId(pendingId); - - } catch (PendingReqIdValidationException e) { + + } catch (final PendingReqIdValidationException e) { log.warn("Search with pendingId '{}' is not valid", pendingId.replaceAll("[\r\n]", "")); return ResponseEntity.badRequest().build(); - + } - + try { - Adressdaten searchInput = buildSearchInput(postleitzahl, municipality, village, street, number); - ZmrAddressSoapClient.AddressInfo searchOutput = client.searchAddress(searchInput); - AdresssucheResult output = buildResponse(searchOutput); + final Adressdaten searchInput = buildSearchInput(postleitzahl, municipality, village, street, number); + final ZmrAddressSoapClient.AddressInfo searchOutput = client.searchAddress(searchInput); + final AdresssucheResult output = buildResponse(searchOutput); return ResponseEntity.ok(output); - - } catch (EidasSAuthenticationException e) { + + } catch (final EidasSAuthenticationException e) { log.warn("Search failed", e); return ResponseEntity.badRequest().build(); - + } } @@ -117,27 +118,27 @@ public class AdresssucheController { if (searchOutput.getPersonResult().isEmpty()) { log.warn("No result from ZMR"); return new AdresssucheResult(Collections.emptyList(), 0); - + } - + log.info("Result level is {}", searchOutput.getLevel()); - Set result = searchOutput.getPersonResult().stream() + final Set result = searchOutput.getPersonResult().stream() .map(Adressdaten::getPostAdresse) .map(it -> new AdresssucheOutput(it.getPostleitzahl(), it.getGemeinde(), it.getOrtschaft(), it.getZustelladresse().getStrassenname(), it.getZustelladresse().getOrientierungsnummer())) .collect(Collectors.toSet()); // TODO Add configuration option for the limit of 30 - List sorted = result.stream().sorted().limit(30).collect(Collectors.toList()); + final List sorted = result.stream().sorted().limit(30).collect(Collectors.toList()); return new AdresssucheResult(sorted, result.size()); - + } private Adressdaten buildSearchInput(String postleitzahl, - String municipality, - String village, - String street, - String number) { - PostAdresseTyp postAdresse = new PostAdresseTyp(); + String municipality, + String village, + String street, + String number) { + final PostAdresseTyp postAdresse = new PostAdresseTyp(); if (StringUtils.isNotBlank(postleitzahl)) { postAdresse.setPostleitzahl(postleitzahl); } @@ -148,7 +149,7 @@ public class AdresssucheController { postAdresse.setOrtschaft(village); } if (StringUtils.isNotBlank(street) || StringUtils.isNotBlank(number)) { - ZustelladresseTyp zustelladresse = new ZustelladresseTyp(); + final ZustelladresseTyp zustelladresse = new ZustelladresseTyp(); if (StringUtils.isNotBlank(street)) { zustelladresse.setStrassenname(street); } @@ -157,10 +158,10 @@ public class AdresssucheController { } postAdresse.setZustelladresse(zustelladresse); } - Adressdaten searchInput = new Adressdaten(); + final Adressdaten searchInput = new Adressdaten(); searchInput.setPostAdresse(postAdresse); return searchInput; - + } @Data @@ -187,9 +188,30 @@ public class AdresssucheController { .append(this.municipality, o.municipality) .append(this.village, o.village) .append(this.street, o.street) - .append(this.number, o.number) + + /* + * TODO: implement better sort method, because current version results to 1, 10, + * 11, .... 2, 20, 21 + */ + .appendSuper(getCustomIntegerComperatpr().compare(this.number, o.number)) + .toComparison(); } + + private Comparator getCustomIntegerComperatpr() { + return new Comparator() { + @Override + public int compare(String o1, String o2) { + return extractInt(o1) - extractInt(o2); + } + + int extractInt(String s) { + final String num = s.replaceAll("\\D", ""); + // return 0 if no digits found + return num.isEmpty() ? 0 : Integer.parseInt(num); + } + }; + } } } diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/AddressSearchResultTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/AddressSearchResultTest.java new file mode 100644 index 00000000..89692ab7 --- /dev/null +++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/AddressSearchResultTest.java @@ -0,0 +1,55 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.utils; + +import static org.junit.Assert.assertArrayEquals; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.mockito.internal.util.collections.Sets; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput; + +@RunWith(BlockJUnit4ClassRunner.class) +public class AddressSearchResultTest { + + @Test + public void checkNumbers() { + + Set result = Sets.newSet( + buildRandom("2"), + buildRandom("3"), + buildRandom("1"), + buildRandom("10"), + buildRandom("10-12"), + buildRandom("15") + ); + + final List sorted = result.stream().sorted().limit(30) + .map(el -> el.getNumber()) + .collect(Collectors.toList()); + + + assertArrayEquals("wrong order", + new Object[]{"1", "2", "3", "10", "15", "10-12"}, + sorted.toArray()); + + + + + } + + private AdresssucheOutput buildRandom(String number) { + return AdresssucheOutput.builder() + .municipality("aaaaaaaa") + .postleitzahl("8080") + .street("bbbbb") + .number(number) + .village("cccccc") + .build(); + } + +} -- cgit v1.2.3