From b76d1bba7ea3aab6a29146f8a1b60fbc7b0117c1 Mon Sep 17 00:00:00 2001 From: Monobikash Das Date: Mon, 29 Jan 2024 16:51:01 +0530 Subject: [PATCH 1/2] Latest address search drools engine API Signed-off-by: Monobikash Das --- admin/kernel-masterdata-service/pom.xml | 20 +++ .../config/AddressConfiguration.java | 132 ++++++++++++++++ .../controller/AddressSearchController.java | 60 +++++++ .../kernel/masterdata/dto/AddressDto.java | 18 +++ .../masterdata/service/AddressService.java | 10 ++ .../service/impl/AddressServiceImpl.java | 146 ++++++++++++++++++ 6 files changed, 386 insertions(+) create mode 100644 admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/config/AddressConfiguration.java create mode 100644 admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/controller/AddressSearchController.java create mode 100644 admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/dto/AddressDto.java create mode 100644 admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/service/AddressService.java create mode 100644 admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/service/impl/AddressServiceImpl.java diff --git a/admin/kernel-masterdata-service/pom.xml b/admin/kernel-masterdata-service/pom.xml index a48e2db1f0c..3f90715bede 100644 --- a/admin/kernel-masterdata-service/pom.xml +++ b/admin/kernel-masterdata-service/pom.xml @@ -41,6 +41,9 @@ 3.6.2 3.7.0 + + 7.53.0.Final + 1.2 @@ -251,6 +254,23 @@ ${spring.boot.version} provided + + org.drools + drools-decisiontables + ${drools.version} + + + + org.drools + drools-core + ${drools.version} + + + + org.drools + drools-compiler + ${drools.version} + diff --git a/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/config/AddressConfiguration.java b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/config/AddressConfiguration.java new file mode 100644 index 00000000000..8118a206ae8 --- /dev/null +++ b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/config/AddressConfiguration.java @@ -0,0 +1,132 @@ +package io.mosip.kernel.masterdata.config; + +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.kie.api.KieServices; +import org.kie.api.builder.*; +import org.kie.api.event.rule.ObjectDeletedEvent; +import org.kie.api.event.rule.ObjectInsertedEvent; +import org.kie.api.event.rule.ObjectUpdatedEvent; +import org.kie.api.event.rule.RuleRuntimeEventListener; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.io.StringReader; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.time.format.DateTimeFormatter; +import java.util.List; + +@Configuration +public class AddressConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(AddressConfiguration.class); + + private KieServices kieServices = KieServices.Factory.get(); + + @Value("${config.server.file.storage.uri}") + private String configServerFileStorageURL; + + @Value("#{T(java.util.Arrays).asList('${mosip.location.search.file.name:}')}") + private List droolsRuleFileName; + + @Bean + public RestTemplate restTemplate() + throws KeyStoreException, KeyManagementException, NoSuchAlgorithmException { + TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; + + SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom() + .loadTrustMaterial(null, acceptingTrustStrategy) + .build(); + + SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext); + + CloseableHttpClient httpClient = HttpClients.custom() + .setSSLSocketFactory(csf) + .build(); + + HttpComponentsClientHttpRequestFactory requestFactory = + new HttpComponentsClientHttpRequestFactory(); + + requestFactory.setHttpClient(httpClient); + RestTemplate restTemplate = new RestTemplate(requestFactory); + return restTemplate; + } + + @Bean + public KieSession kieSession() throws IOException { + LOGGER.info("Session created..."); + KieSession kieSession = getKieContainer().newKieSession(); + kieSession.addEventListener(new RuleRuntimeEventListener() { + @Override + public void objectInserted(ObjectInsertedEvent event) { + LOGGER.info("Object inserted \n " + + event.getObject().toString()); + } + + @Override + public void objectUpdated(ObjectUpdatedEvent event) { + LOGGER.info("Object was updated \n" + + "New Content \n" + + event.getObject().toString()); + } + + @Override + public void objectDeleted(ObjectDeletedEvent event) { + LOGGER.info("Object retracted \n" + + event.getOldObject().toString()); + } + }); + return kieSession; + } + + @Bean + public KieContainer getKieContainer() throws IOException { + LOGGER.info("Container created..."); + getKieRepository(); + KieBuilder kb = kieServices.newKieBuilder(getKieFileSystem()); + kb.buildAll(); + KieModule kieModule = kb.getKieModule(); + return kieServices.newKieContainer(kieModule.getReleaseId()); + } + + private void getKieRepository() { + final KieRepository kieRepository = kieServices.getRepository(); + kieRepository.addKieModule(new KieModule() { + @Override + public ReleaseId getReleaseId() { + return kieRepository.getDefaultReleaseId(); + } + }); + } + + private KieFileSystem getKieFileSystem() throws IOException { + KieFileSystem kieFileSystem = kieServices.newKieFileSystem(); + for (String fileName : droolsRuleFileName) { + LOGGER.info("loading Drools configuration file - " + fileName); + kieFileSystem.write("src/main/resources/" + fileName, + kieServices.getResources().newReaderResource( + new StringReader(getJson( + configServerFileStorageURL, fileName)))); + } + return kieFileSystem; + } + + public static String getJson(String configServerFileStorageURL, String uri) { + RestTemplate restTemplate = new RestTemplate(); + return restTemplate.getForObject(configServerFileStorageURL + uri, String.class); + } +} \ No newline at end of file diff --git a/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/controller/AddressSearchController.java b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/controller/AddressSearchController.java new file mode 100644 index 00000000000..fb7ccf89213 --- /dev/null +++ b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/controller/AddressSearchController.java @@ -0,0 +1,60 @@ +package io.mosip.kernel.masterdata.controller; + +import io.mosip.kernel.core.exception.BaseUncheckedException; +import io.mosip.kernel.core.exception.ServiceError; +import io.mosip.kernel.core.http.RequestWrapper; +import io.mosip.kernel.core.http.ResponseFilter; +import io.mosip.kernel.core.http.ResponseWrapper; +import io.mosip.kernel.masterdata.dto.AddressDto; +import io.mosip.kernel.masterdata.service.AddressService; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; + +@RefreshScope +@RestController +@Tag(name = "Latest Address Search", description = "Latest Address Search") +public class AddressSearchController { + + @Autowired + AddressService addressService; + + @ResponseFilter + @PostMapping(value = "/latestAddress") + public ResponseWrapper latestAddress(@Valid @RequestBody RequestWrapper dto) { + ResponseWrapper response = new ResponseWrapper<>(); + try { + AddressDto addressDto = addressService.getLatestAddress(dto.getRequest()); + response.setResponse(addressDto); + } catch (BaseUncheckedException e) { + ServiceError err = new ServiceError(e.getErrorCode(), e.getMessage()); + List li = new ArrayList<>(); + li.add(err); + response.setErrors(li); + } + return response; + } + + @ResponseFilter + @PostMapping(value = "/latestFhirAddress") + public ResponseWrapper latestFhirAddress(@Valid @RequestBody RequestWrapper dto) { + ResponseWrapper response = new ResponseWrapper<>(); + try { + AddressDto addressDto = addressService.getLatestFHIRAddress(dto.getRequest()); + response.setResponse(addressDto); + } catch (BaseUncheckedException e) { + ServiceError err = new ServiceError(e.getErrorCode(), e.getMessage()); + List li = new ArrayList<>(); + li.add(err); + response.setErrors(li); + } + return response; + } +} diff --git a/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/dto/AddressDto.java b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/dto/AddressDto.java new file mode 100644 index 00000000000..5d37bad260c --- /dev/null +++ b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/dto/AddressDto.java @@ -0,0 +1,18 @@ +package io.mosip.kernel.masterdata.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Map; + +@Data +public class AddressDto { + @ApiModelProperty( + notes = "Request Timestamp", + example = "2023-07-26T06:12:52.994Z", + required = true + ) + private LocalDateTime effectiveDate; + private Map address; +} diff --git a/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/service/AddressService.java b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/service/AddressService.java new file mode 100644 index 00000000000..b3603f38854 --- /dev/null +++ b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/service/AddressService.java @@ -0,0 +1,10 @@ +package io.mosip.kernel.masterdata.service; + +import io.mosip.kernel.masterdata.dto.AddressDto; + +public interface AddressService { + + public AddressDto getLatestAddress(AddressDto dto); + + public AddressDto getLatestFHIRAddress(AddressDto dto); +} diff --git a/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/service/impl/AddressServiceImpl.java b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/service/impl/AddressServiceImpl.java new file mode 100644 index 00000000000..c28d4a953b7 --- /dev/null +++ b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/service/impl/AddressServiceImpl.java @@ -0,0 +1,146 @@ +package io.mosip.kernel.masterdata.service.impl; + +import io.mosip.kernel.core.exception.BaseUncheckedException; +import io.mosip.kernel.core.util.JsonUtils; +import io.mosip.kernel.masterdata.dto.AddressDto; +import io.mosip.kernel.masterdata.service.AddressService; +import io.mosip.kernel.masterdata.service.LocationService; +import org.json.JSONObject; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.time.Duration; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class AddressServiceImpl implements AddressService { + + @Value("${opencrvs.locations.url}") + private String locationsUrl; + @Value("${opencrvs.data.lang.code.default}") + private String defaultLangCode; + @Value("${opencrvs.data.lang.code.mapping}") + private String langCodeMapping; + @Value("${opencrvs.data.address.line.mapping}") + private String addressLineMapping; + @Value("${opencrvs.data.address.location.mapping}") + private String addressLocationMapping; + @Value("${opencrvs.data.address.line.joiner}") + private String addressLineJoiner; + + @Autowired + private RestTemplate restTemplate; + + @Autowired + KieSession kieSession; + + private static final Logger LOGGER = LoggerFactory.getLogger(LocationService.class); + private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy"); + + + @Autowired + private KieContainer kieContainer; + + public AddressDto getLatestAddress(AddressDto dto) { + + try { + Instant start = Instant.now(); + Map addressJson = dto.getAddress(); + kieSession.insert(addressJson); + kieSession.insert(dto.getEffectiveDate()); + kieSession.fireAllRules(); + Instant end = Instant.now(); + Duration timeElapsed = Duration.between(start, end); + LOGGER.debug("Time taken: "+ timeElapsed.toMillis() +" milliseconds"); + // kieSession.dispose(); + dto.setAddress(addressJson); + } catch (Exception e) { + LOGGER.error("Exception occured - ", e); + throw new BaseUncheckedException("KER-LOC-001", e.getMessage()); + } + return dto; + } + + public AddressDto getLatestFHIRAddress(AddressDto dto) { + + try { + Map addressJson = new HashMap<>(); + getAddressLinesFromAddress(dto.getAddress(), addressJson); + getAddressLocationFromAddress(dto.getAddress(), addressJson); + LOGGER.debug("getLatestFHIRAddress - ", addressJson); + + // Map addressJson = new ObjectMapper().readValue(location, Map.class); + LOGGER.info(addressJson.toString()); + kieSession.insert(addressJson); + kieSession.insert(dto.getEffectiveDate()); + kieSession.fireAllRules(); + LOGGER.debug("getLatestFHIRAddress::Modified Address: " + JsonUtils.javaObjectToJsonString(addressJson)); + // kieSession.dispose(); + dto.setAddress(addressJson); + } catch (Exception e) { + LOGGER.error("Exception occured - " + e.getStackTrace()); + throw new BaseUncheckedException("KER-LOC-001", e.getMessage()); + } + return dto; + } + + public void getAddressLinesFromAddress(Map address, Map addressJson){ + String toReturn = ""; + for (String mappingLine : addressLineMapping.split("\\|")) { + String mosipLineNumber = mappingLine.split(":")[0]; + String opencrvsLines = mappingLine.split(":")[1]; + int opencrvsStartingLineNumber = Integer.parseInt(opencrvsLines.split("-")[0]) - 1; + int opencrvsEndingLineNumber = Integer.parseInt(opencrvsLines.split("-")[1]) - 1; + String lineValue = ""; + for(int i=opencrvsStartingLineNumber;i<=opencrvsEndingLineNumber; i++){ + if (!((List) address.get("line")).get(i).isBlank()) { + if (!lineValue.isBlank()) lineValue += + addressLineJoiner.replaceAll("\"", ""); + lineValue += ((List) address.get("line")).get(i); + } + } + Map langValMap = new HashMap<>(); + langValMap.put(defaultLangCode, lineValue.trim()); + addressJson.put("addressLine" + mosipLineNumber, langValMap); + } + } + + public void getAddressLocationFromAddress(Map address, Map addressJson){ + for (String mappingLocation : addressLocationMapping.split("\\|")) { + String mosipLocation = mappingLocation.split(":")[0]; + String opencrvsLocation = mappingLocation.split(":")[1]; + String opencrvsLocationIfId = mappingLocation.split(":")[2]; + if("id".equals(opencrvsLocationIfId)){ + String value = fetchAddressValueFromId((String)address.get(opencrvsLocation)); + Map langValMap = new HashMap<>(); + langValMap.put(defaultLangCode, value); + addressJson.put(mosipLocation, langValMap); + } else { + Map langValMap = new HashMap<>(); + String value = address.get(opencrvsLocation) != null? address.get(opencrvsLocation).toString(): null; + langValMap.put(defaultLangCode, value); + addressJson.put(mosipLocation, langValMap); + } + } + } + + public String fetchAddressValueFromId(String id){ + try{ + JSONObject json = new JSONObject( + restTemplate.getForObject(locationsUrl + "/" + id, String.class)); + return json.getString("name"); + } catch(Exception e){ + throw new BaseUncheckedException("KER-ADD-001", e.getMessage(), e); + } + } +} From f7b605eff9fdbcda246aae01ae6d68b6dd85b668 Mon Sep 17 00:00:00 2001 From: Monobikash Das Date: Mon, 29 Jan 2024 17:00:26 +0530 Subject: [PATCH 2/2] Latest address search drools engine API Signed-off-by: Monobikash Das --- .../config/AddressConfiguration.java | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/config/AddressConfiguration.java b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/config/AddressConfiguration.java index 8118a206ae8..52306194ebe 100644 --- a/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/config/AddressConfiguration.java +++ b/admin/kernel-masterdata-service/src/main/java/io/mosip/kernel/masterdata/config/AddressConfiguration.java @@ -43,29 +43,6 @@ public class AddressConfiguration { @Value("#{T(java.util.Arrays).asList('${mosip.location.search.file.name:}')}") private List droolsRuleFileName; - @Bean - public RestTemplate restTemplate() - throws KeyStoreException, KeyManagementException, NoSuchAlgorithmException { - TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; - - SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom() - .loadTrustMaterial(null, acceptingTrustStrategy) - .build(); - - SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext); - - CloseableHttpClient httpClient = HttpClients.custom() - .setSSLSocketFactory(csf) - .build(); - - HttpComponentsClientHttpRequestFactory requestFactory = - new HttpComponentsClientHttpRequestFactory(); - - requestFactory.setHttpClient(httpClient); - RestTemplate restTemplate = new RestTemplate(requestFactory); - return restTemplate; - } - @Bean public KieSession kieSession() throws IOException { LOGGER.info("Session created...");