Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Latest address search drools engine API #935

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions admin/kernel-masterdata-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<vertx.version>3.6.2</vertx.version>
<vertx.health.check.version>3.7.0</vertx.health.check.version>

<!-- Drools -->
<drools.version>7.53.0.Final</drools.version>


<!-- javax -->
<javax.interceptor.version>1.2</javax.interceptor.version>
Expand Down Expand Up @@ -251,6 +254,23 @@
<version>${spring.boot.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>${drools.version}</version>
</dependency>

<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.version}</version>
</dependency>

<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>
</dependencies>

<distributionManagement>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
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<String> droolsRuleFileName;

@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);
}
}
Original file line number Diff line number Diff line change
@@ -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<AddressDto> latestAddress(@Valid @RequestBody RequestWrapper<AddressDto> dto) {
ResponseWrapper<AddressDto> 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<ServiceError> li = new ArrayList<>();
li.add(err);
response.setErrors(li);
}
return response;
}

@ResponseFilter
@PostMapping(value = "/latestFhirAddress")
public ResponseWrapper<AddressDto> latestFhirAddress(@Valid @RequestBody RequestWrapper<AddressDto> dto) {
ResponseWrapper<AddressDto> 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<ServiceError> li = new ArrayList<>();
li.add(err);
response.setErrors(li);
}
return response;
}
}
Original file line number Diff line number Diff line change
@@ -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<String, Object> address;
}
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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<String, Object> 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<String, Object> addressJson = new HashMap<>();
getAddressLinesFromAddress(dto.getAddress(), addressJson);
getAddressLocationFromAddress(dto.getAddress(), addressJson);
LOGGER.debug("getLatestFHIRAddress - ", addressJson);

// Map<String, Object> 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<String, Object> address, Map<String, Object> 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<String>) address.get("line")).get(i).isBlank()) {
if (!lineValue.isBlank()) lineValue +=
addressLineJoiner.replaceAll("\"", "");
lineValue += ((List<String>) address.get("line")).get(i);
}
}
Map<String, String> langValMap = new HashMap<>();
langValMap.put(defaultLangCode, lineValue.trim());
addressJson.put("addressLine" + mosipLineNumber, langValMap);
}
}

public void getAddressLocationFromAddress(Map<String, Object> address, Map<String, Object> 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<String, String> langValMap = new HashMap<>();
langValMap.put(defaultLangCode, value);
addressJson.put(mosipLocation, langValMap);
} else {
Map<String, String> 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);
}
}
}
Loading