From 47565187c7f273c49e0347fb5ad34ae4a3d1f616 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 29 Nov 2021 08:56:51 +0100 Subject: add SOAP client to search addresses and add first simple test to request address information from real TEST ZMR --- .../eidas/v2/clients/zmr/ZmrAddressSoapClient.java | 283 +++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java new file mode 100644 index 00000000..d869ca37 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java @@ -0,0 +1,283 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr; + +import java.math.BigInteger; +import java.net.URL; +import java.text.MessageFormat; +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.PostConstruct; +import javax.xml.ws.BindingProvider; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.Nullable; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.AbstractSoapClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ZmrCommunicationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.VersionHolder; +import at.gv.bmi.namespace.zmr_su.base._20040201_.address.ClientInfoType; +import at.gv.bmi.namespace.zmr_su.base._20040201_.address.Organisation; +import at.gv.bmi.namespace.zmr_su.base._20040201_.address.RequestType; +import at.gv.bmi.namespace.zmr_su.base._20040201_.address.ResponseType; +import at.gv.bmi.namespace.zmr_su.base._20040201_.address.Service; +import at.gv.bmi.namespace.zmr_su.base._20040201_.address.ServiceFault_Exception; +import at.gv.bmi.namespace.zmr_su.base._20040201_.address.ServicePort; +import at.gv.bmi.namespace.zmr_su.base._20040201_.address.WorkflowInfoClient; +import at.gv.bmi.namespace.zmr_su.base._20040201_.address.WorkflowInfoServer; +import at.gv.bmi.namespace.zmr_su.zrm._20040201_.address.Adressdaten; +import at.gv.bmi.namespace.zmr_su.zrm._20040201_.address.AdresssucheInfoType; +import at.gv.bmi.namespace.zmr_su.zrm._20040201_.address.AdresssucheRequest; +import at.gv.bmi.namespace.zmr_su.zrm._20040201_.address.AdresssuchergebnisType; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; + +/** + * ZMR SOAP client for search-address operations. + * + * @author tlenz + * + */ +@Slf4j +public class ZmrAddressSoapClient extends AbstractSoapClient { + + private static final String CLIENT_DEFAULT = "ZMR-AddressSearch Client"; + private static final String CLIENT_INFO = "eIDAS MS-Connector v{0}"; + + private static final String LOGMSG_ZMR_SOAP_ERROR = + "ZMR anwser for transaction: {0} with code: {1} and message: {2}"; + private static final String LOGMSG_ZMR_ERROR = + "Receive an error from ZMR during '{}' operation with msg: {}"; + private static final String LOGMSG_ZMR_RESP_PROCESS = + "Proces ZMR response during '{}' operation failes with msg: {}"; + + private static final String ERROR_MATCHING_07 = "module.eidasauth.matching.07"; + private static final String ERROR_MATCHING_99 = "module.eidasauth.matching.99"; + + private static final String PROCESS_GENERAL = "GP_Abfragen"; + private static final String PROCESS_TASK_ADDRESS_WIZZARD = "ZMR_VO_Adresssuche_im_GWR__6"; + + private static final String PROCESS_TASK_RESPONSE_LEVEL_CITY = "Ortschaft"; + private static final String PROCESS_TASK_RESPONSE_LEVEL_STREET = "Strassenname"; + private static final String PROCESS_TASK_RESPONSE_LEVEL_NUMBER = "Orientierungsnummer"; + + + private static final String PROCESS_ADDRESS_WIZZARD = "PROCESS_SEARCH_WITH_ADDRESS_WIZZARD"; + + private static final String SEARCH_TYPE = "ADRESSSUCHE"; + + + @Autowired VersionHolder versionHolder; + private ServicePort zmrClient; + + @Getter + @AllArgsConstructor + public static class AddressInfo { + private final BigInteger processId; + private final List personResult; + private final DetailLevel level; + + } + + public enum DetailLevel { CITY, STREET, NUMBER, UNKNOWN } + + /** + * Get address information based on ZMR data. + * + * @param addressInfo Search parameters + * @return Address data + * @throws EidasSAuthenticationException In case of an error + */ + public AddressInfo searchAddress(@NonNull Adressdaten addressInfo) + throws EidasSAuthenticationException { + return searchAddress(addressInfo, null); + + } + + /** + * Get address information based on ZMR data. + * + * @param addressInfo Search parameters + * @param prozessInstanzId processId in case of associated requests + * @return Address data + * @throws EidasSAuthenticationException In case of an error + */ + public AddressInfo searchAddress(@NonNull Adressdaten addressInfo, @Nullable BigInteger prozessInstanzId) + throws EidasSAuthenticationException { + try { + RequestType req = new RequestType(); + + // set generic informations + req.setClientInfo(generateClientInfos()); + req.setWorkflowInfoClient(generateWorkFlowInfos(PROCESS_TASK_ADDRESS_WIZZARD, null)); + + AdresssucheRequest search = new AdresssucheRequest(); + req.setAdresssucheRequest(search); + + // set static search type + AdresssucheInfoType searchType = new AdresssucheInfoType(); + searchType.setSuchart(SEARCH_TYPE); + search.setAdresssucheInfo(searchType); + + // set search parameters + search.setAdressdaten(addressInfo); + + // request ZMR address services + log.debug("Requesting ZMR for adddress search ...."); + ResponseType resp = zmrClient.service(req, null); + log.debug("Receice response for address search with #{} elements", + resp.getAdresssucheResponse().getAdresssuchergebnis().getGefundeneSaetze()); + + return new AddressInfo( + extractZmrProcessId(resp.getWorkflowInfoServer()), + resp.getAdresssucheResponse().getAdresssuchergebnis().getAdressdaten(), + extractAddressDetailLevel(resp.getAdresssucheResponse().getAdresssuchergebnis())); + + } catch (final ServiceFault_Exception e) { + final String errorMsg = extractReasonFromError(e); + log.warn(LOGMSG_ZMR_ERROR, PROCESS_ADDRESS_WIZZARD, errorMsg); + throw new ZmrCommunicationException(ERROR_MATCHING_07, new Object[] { errorMsg }, e); + + } catch (final Exception e) { + log.warn(LOGMSG_ZMR_RESP_PROCESS, PROCESS_ADDRESS_WIZZARD, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); + + } + } + + @PostConstruct + private void initialize() throws EaafConfigurationException { + // set-up the ZMR client + initializeTechnicalZmrClient(); + + } + + private void initializeTechnicalZmrClient() throws EaafConfigurationException { + log.info("Starting ZMR-AddressSearch Client initialization .... "); + final URL url = ZmrAddressSoapClient.class.getResource("/wsdl/addresssearching_client/wsdl/Service.wsdl"); + final Service zmrService = new Service(url); + zmrClient = zmrService.getService(); + + final String zmrServiceUrl = basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_ENDPOINT); + if (StringUtils.isEmpty(zmrServiceUrl)) { + log.error("No ZMR-AddressSearch service-URL found. ZMR-AddressSearch-Client initalisiation failed."); + throw new RuntimeException( + "No ZMR-AddressSearch service URL found. ZMR-AddressSearch-Client initalisiation failed."); + + } + + // inject handler + log.info("Use ZMR-AddressSearch service-URL: " + zmrServiceUrl); + injectBindingProvider((BindingProvider) zmrClient, CLIENT_DEFAULT, zmrServiceUrl, + basicConfig.getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_DEBUG_TRACEMESSAGES, + false)); + + // inject http parameters and SSL context + log.debug("Inject HTTP client settings ... "); + injectHttpClient(zmrClient, HttpClientConfig.builder() + .clientName(CLIENT_DEFAULT) + .clientType(CLIENT_DEFAULT) + .clientUrl(zmrServiceUrl) + .connectionTimeout(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_TIMEOUT_CONNECTION, + Constants.HTTP_CLIENT_DEFAULT_TIMEOUT_CONNECTION)) + .responseTimeout(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_TIMEOUT_RESPONSE, + Constants.HTTP_CLIENT_DEFAULT_TIMEOUT_RESPONSE)) + .keyStoreConfig(buildKeyStoreConfiguration( + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_KEYSTORE_TYPE, + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_KEYSTORE_PATH, + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_KEYSTORE_PASSWORD, + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_KEYSTORE_NAME, + "ZMR-AddressSearch SSL Client-Authentication KeyStore")) + .keyAlias(basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_KEYS_ALIAS)) + .keyPassword(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_KEY_PASSWORD)) + .trustAll(false) + .trustStoreConfig(buildKeyStoreConfiguration( + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_TRUSTSTORE_TYPE, + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_TRUSTSTORE_PATH, + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_TRUSTSTORE_PASSWORD, + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_TRUSTSTORE_NAME, + "ZMR-AddressSearch SSL Client-Authentication TrustStore")) + .build()); + + } + + @Nonnull + private ClientInfoType generateClientInfos() { + final ClientInfoType clientInfo = new ClientInfoType(); + final Organisation clientOrganisation = new Organisation(); + clientInfo.setOrganisation(clientOrganisation); + + // set client information + clientInfo.setClient(MessageFormat.format(CLIENT_INFO, versionHolder.getVersion())); + + // set Behoerdennummer as organization identifier + clientOrganisation.setBehoerdenNr(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_ORGANIZATION_NR)); + + return clientInfo; + } + + @Nonnull + private static String extractReasonFromError(ServiceFault_Exception e) { + if (e.getFaultInfo() != null) { + return MessageFormat.format(LOGMSG_ZMR_SOAP_ERROR, + e.getFaultInfo().getServerTransaktionNr().toString(), + e.getFaultInfo().getErrorCode(), + e.getFaultInfo().getErrorMessage()); + + } else { + log.error("ZMR response without error code", e); + return e.getMessage(); + + } + } + + @Nonnull + private static WorkflowInfoClient generateWorkFlowInfos(@Nonnull String subStepName, + @Nullable BigInteger prozessInstanzId) { + final WorkflowInfoClient infos = new WorkflowInfoClient(); + infos.setProzessName(PROCESS_GENERAL); + infos.setVorgangName(subStepName); + + //set processId that we received from ZMR before, if already available + if (prozessInstanzId != null) { + infos.setProzessInstanzID(prozessInstanzId); + + } + + return infos; + + } + + private static BigInteger extractZmrProcessId(WorkflowInfoServer workflowInfoServer) { + return workflowInfoServer != null ? workflowInfoServer.getProzessInstanzID() : null; + + } + + private static DetailLevel extractAddressDetailLevel(AdresssuchergebnisType value) { + switch (value.getDetailgrad()) { + case PROCESS_TASK_RESPONSE_LEVEL_CITY: + return DetailLevel.CITY; + + case PROCESS_TASK_RESPONSE_LEVEL_STREET: + return DetailLevel.STREET; + + case PROCESS_TASK_RESPONSE_LEVEL_NUMBER: + return DetailLevel.NUMBER; + + default: + return DetailLevel.UNKNOWN; + + } + } + +} -- cgit v1.2.3 From e5934d538aabcfc1f3b92472753de729d6ce1cce Mon Sep 17 00:00:00 2001 From: Christian Kollmann Date: Thu, 2 Dec 2021 09:06:55 +0100 Subject: Search with user provided input in ZMR for addresses --- .../eidas/v2/clients/zmr/ZmrAddressSoapClient.java | 110 +++++++++++---------- 1 file changed, 56 insertions(+), 54 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java index d869ca37..5fb839af 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java @@ -39,18 +39,18 @@ import lombok.extern.slf4j.Slf4j; /** * ZMR SOAP client for search-address operations. - * + * * @author tlenz * */ @Slf4j public class ZmrAddressSoapClient extends AbstractSoapClient { - + private static final String CLIENT_DEFAULT = "ZMR-AddressSearch Client"; private static final String CLIENT_INFO = "eIDAS MS-Connector v{0}"; - + private static final String LOGMSG_ZMR_SOAP_ERROR = - "ZMR anwser for transaction: {0} with code: {1} and message: {2}"; + "ZMR anwser for transaction: {0} with code: {1} and message: {2}"; private static final String LOGMSG_ZMR_ERROR = "Receive an error from ZMR during '{}' operation with msg: {}"; private static final String LOGMSG_ZMR_RESP_PROCESS = @@ -58,37 +58,37 @@ public class ZmrAddressSoapClient extends AbstractSoapClient { private static final String ERROR_MATCHING_07 = "module.eidasauth.matching.07"; private static final String ERROR_MATCHING_99 = "module.eidasauth.matching.99"; - + private static final String PROCESS_GENERAL = "GP_Abfragen"; private static final String PROCESS_TASK_ADDRESS_WIZZARD = "ZMR_VO_Adresssuche_im_GWR__6"; - + private static final String PROCESS_TASK_RESPONSE_LEVEL_CITY = "Ortschaft"; private static final String PROCESS_TASK_RESPONSE_LEVEL_STREET = "Strassenname"; private static final String PROCESS_TASK_RESPONSE_LEVEL_NUMBER = "Orientierungsnummer"; - - + + private static final String PROCESS_ADDRESS_WIZZARD = "PROCESS_SEARCH_WITH_ADDRESS_WIZZARD"; - + private static final String SEARCH_TYPE = "ADRESSSUCHE"; - - - @Autowired VersionHolder versionHolder; + + + @Autowired VersionHolder versionHolder; private ServicePort zmrClient; - + @Getter @AllArgsConstructor - public static class AddressInfo { + public static class AddressInfo { private final BigInteger processId; private final List personResult; private final DetailLevel level; - + } - + public enum DetailLevel { CITY, STREET, NUMBER, UNKNOWN } - + /** - * Get address information based on ZMR data. - * + * Get address information based on ZMR data. + * * @param addressInfo Search parameters * @return Address data * @throws EidasSAuthenticationException In case of an error @@ -96,12 +96,12 @@ public class ZmrAddressSoapClient extends AbstractSoapClient { public AddressInfo searchAddress(@NonNull Adressdaten addressInfo) throws EidasSAuthenticationException { return searchAddress(addressInfo, null); - + } - + /** - * Get address information based on ZMR data. - * + * Get address information based on ZMR data. + * * @param addressInfo Search parameters * @param prozessInstanzId processId in case of associated requests * @return Address data @@ -111,33 +111,33 @@ public class ZmrAddressSoapClient extends AbstractSoapClient { throws EidasSAuthenticationException { try { RequestType req = new RequestType(); - + // set generic informations req.setClientInfo(generateClientInfos()); req.setWorkflowInfoClient(generateWorkFlowInfos(PROCESS_TASK_ADDRESS_WIZZARD, null)); - + AdresssucheRequest search = new AdresssucheRequest(); req.setAdresssucheRequest(search); - + // set static search type AdresssucheInfoType searchType = new AdresssucheInfoType(); searchType.setSuchart(SEARCH_TYPE); search.setAdresssucheInfo(searchType); - + // set search parameters - search.setAdressdaten(addressInfo); + search.setAdressdaten(addressInfo); // request ZMR address services log.debug("Requesting ZMR for adddress search ...."); ResponseType resp = zmrClient.service(req, null); - log.debug("Receice response for address search with #{} elements", - resp.getAdresssucheResponse().getAdresssuchergebnis().getGefundeneSaetze()); - + log.debug("Receice response for address search with #{} elements", + resp.getAdresssucheResponse().getAdresssuchergebnis().getGefundeneSaetze()); + return new AddressInfo( - extractZmrProcessId(resp.getWorkflowInfoServer()), - resp.getAdresssucheResponse().getAdresssuchergebnis().getAdressdaten(), + extractZmrProcessId(resp.getWorkflowInfoServer()), + resp.getAdresssucheResponse().getAdresssuchergebnis().getAdressdaten(), extractAddressDetailLevel(resp.getAdresssucheResponse().getAdresssuchergebnis())); - + } catch (final ServiceFault_Exception e) { final String errorMsg = extractReasonFromError(e); log.warn(LOGMSG_ZMR_ERROR, PROCESS_ADDRESS_WIZZARD, errorMsg); @@ -154,7 +154,7 @@ public class ZmrAddressSoapClient extends AbstractSoapClient { private void initialize() throws EaafConfigurationException { // set-up the ZMR client initializeTechnicalZmrClient(); - + } private void initializeTechnicalZmrClient() throws EaafConfigurationException { @@ -206,10 +206,10 @@ public class ZmrAddressSoapClient extends AbstractSoapClient { Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_TRUSTSTORE_PASSWORD, Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_TRUSTSTORE_NAME, "ZMR-AddressSearch SSL Client-Authentication TrustStore")) - .build()); - + .build()); + } - + @Nonnull private ClientInfoType generateClientInfos() { final ClientInfoType clientInfo = new ClientInfoType(); @@ -218,14 +218,14 @@ public class ZmrAddressSoapClient extends AbstractSoapClient { // set client information clientInfo.setClient(MessageFormat.format(CLIENT_INFO, versionHolder.getVersion())); - + // set Behoerdennummer as organization identifier clientOrganisation.setBehoerdenNr(basicConfig.getBasicConfiguration( Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_ORGANIZATION_NR)); - + return clientInfo; } - + @Nonnull private static String extractReasonFromError(ServiceFault_Exception e) { if (e.getFaultInfo() != null) { @@ -239,10 +239,10 @@ public class ZmrAddressSoapClient extends AbstractSoapClient { return e.getMessage(); } - } - + } + @Nonnull - private static WorkflowInfoClient generateWorkFlowInfos(@Nonnull String subStepName, + private static WorkflowInfoClient generateWorkFlowInfos(@Nonnull String subStepName, @Nullable BigInteger prozessInstanzId) { final WorkflowInfoClient infos = new WorkflowInfoClient(); infos.setProzessName(PROCESS_GENERAL); @@ -251,33 +251,35 @@ public class ZmrAddressSoapClient extends AbstractSoapClient { //set processId that we received from ZMR before, if already available if (prozessInstanzId != null) { infos.setProzessInstanzID(prozessInstanzId); - + } - + return infos; } - + private static BigInteger extractZmrProcessId(WorkflowInfoServer workflowInfoServer) { - return workflowInfoServer != null ? workflowInfoServer.getProzessInstanzID() : null; + return workflowInfoServer != null ? workflowInfoServer.getProzessInstanzID() : null; } - + private static DetailLevel extractAddressDetailLevel(AdresssuchergebnisType value) { + if (value.getDetailgrad() == null) + return DetailLevel.UNKNOWN; switch (value.getDetailgrad()) { case PROCESS_TASK_RESPONSE_LEVEL_CITY: return DetailLevel.CITY; - + case PROCESS_TASK_RESPONSE_LEVEL_STREET: return DetailLevel.STREET; - + case PROCESS_TASK_RESPONSE_LEVEL_NUMBER: return DetailLevel.NUMBER; - + default: return DetailLevel.UNKNOWN; - + } } - + } -- cgit v1.2.3 From ac56869c2a981e40d6cf4637fb8fd46c06207c9d Mon Sep 17 00:00:00 2001 From: Christian Kollmann Date: Thu, 2 Dec 2021 16:05:57 +0100 Subject: Add PLZ to search for adresses in ZMR --- .../modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java index 5fb839af..6e146ddf 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrAddressSoapClient.java @@ -264,8 +264,9 @@ public class ZmrAddressSoapClient extends AbstractSoapClient { } private static DetailLevel extractAddressDetailLevel(AdresssuchergebnisType value) { - if (value.getDetailgrad() == null) + if (value.getDetailgrad() == null) { return DetailLevel.UNKNOWN; + } switch (value.getDetailgrad()) { case PROCESS_TASK_RESPONSE_LEVEL_CITY: return DetailLevel.CITY; -- cgit v1.2.3