@Service
public class CampaignExecutionService {
private static final String CLIENT_KEY = "client";
@Autowired
private CampaignExecutionRepository executionRepository;
@Autowired
private ClientRepository clientRepository;
@Autowired
private ScriptManager scriptManager;
@Autowired
private ExceptionEntityService exceptionEntityService;
@Transactional(propagation = Propagation.MANDATORY)
public CampaignExecution createExecution(Campaign campaign) {
CampaignExecution execution = new CampaignExecution();
execution.setCampaign(campaign);
return executionRepository.saveAndFlush(execution);
}
@Transactional(propagation = Propagation.MANDATORY)
public void runExecution(CampaignExecution execution) {
_runExecution(execution);
}
@Transactional
public void runExecution(Long executionId) {
CampaignExecution execution = executionRepository.getSync(executionId);
_runExecution(execution);
}
private void _runExecution(CampaignExecution execution) {
try {
Set<Client> clients = getSuitedBorrowers(execution, clientRepository.getAllIds());
execution.getClients().addAll(clients);
execution.setException(null);
} catch (Exception e) {
ExceptionEntity exceptionEntity = exceptionEntityService.saveException(e, e.getMessage());
execution.setException(exceptionEntity);
execution.setStatus(CampaignExecutionStatus.EXCEPTION_OCCURRED);
}
execution.setStatus(CampaignExecutionStatus.FINISHED);
executionRepository.saveAndFlush(execution);
}
private Set<Client> getSuitedBorrowers(CampaignExecution execution, Set<UUID> candidates) throws ScriptException {
Script matchingScript = getClientMatchingScript(execution.getCampaign().getExpression());
Set<Client> suitedBorrowers = new HashSet<>();
for (UUID clientId : candidates) {
Optional<Client> client = evaluateClient(matchingScript, clientId);
client.ifPresent(suitedBorrowers::add);
}
return suitedBorrowers;
}
private Optional<Client> evaluateClient(Script script, UUID clientId) throws ScriptException {
Client client = clientRepository.getReferenceById(clientId);
Object evaluationResult = script.eval(Map.of(CLIENT_KEY, client));
return Boolean.TRUE.equals(evaluationResult) ? Optional.of(client) : Optional.empty();
}
private Script getClientMatchingScript(Expression expression) {
try {
return scriptManager.compile(expression);
} catch (ScriptException e) {
throw new RuntimeException("Script doesn't compile", e);
}
}
@Transactional
public Object evaluateExpression(UUID clientId, Expression expression) throws ScriptException, NotFoundException {
Client client = clientRepository.getReferenceById(clientId);
Script script = scriptManager.compile(expression);
Map<String, Client> binding = Map.of(CLIENT_KEY, client);
return script.eval(binding);
}
}