package ru.hflabs.rcd.task.performer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.util.Assert;
import ru.hflabs.rcd.model.task.TaskProgress;
import ru.hflabs.rcd.service.ITaskDefinitionRepository;
import ru.hflabs.rcd.service.task.ITaskPerformer;
import ru.hflabs.rcd.service.task.ITaskProgress;
import java.util.Map;
/**
* Класс <class>TaskPerformerTemplate</class> реализует базовый класс исполнителя задачи
*
* @author Nazin Alexander
*/
public abstract class TaskPerformerTemplate<P extends ParametersHolder, R extends ParametersHolder> implements ITaskPerformer, BeanNameAware {
protected final Logger LOG = LoggerFactory.getLogger(getClass());
/** Идентификатор исполнителя задачи */
private String performerName;
/** Сервис работы с репозиторием предопределенных задач */
private ITaskDefinitionRepository taskDefinitionRepository;
/** Идентификатор выполняемой задачи */
private final ThreadLocal<ITaskProgress> taskProgress;
protected TaskPerformerTemplate() {
this.taskProgress = new InheritableThreadLocal<>();
}
public void setTaskDefinitionRepository(ITaskDefinitionRepository taskDefinitionRepository) {
this.taskDefinitionRepository = taskDefinitionRepository;
}
@Override
public void setBeanName(String name) {
this.performerName = name;
}
@Override
public String retrieveName() {
return performerName;
}
/**
* Возвращает класс параметра задачи
*
* @return Возвращает класс параметров задачи
*/
public abstract Class<P> retrieveParameterClass();
/**
* Возвращает класс результата задачи
*
* @return Возвращает класс результата задачи
*/
public abstract Class<R> retrieveResultClass();
/**
* Выполняет задачу
*
* @param parameters параметры задачи
* @return Возвращает результат выполнения задачи
*/
protected abstract R doPerformTask(P parameters) throws Throwable;
/**
* Выполняет задачу с подготовленными параметрами
*
* @param progress слушатель прогресса выполнения задачи
* @param parameters параметры выполнения задачи
* @return Возвращает результат выполнения
*/
public R doPerformTask(ITaskProgress progress, P parameters) throws Throwable {
Assert.notNull(progress, "Task progress callback not be NULL");
Assert.notNull(parameters, "Task parameters must not be NULL");
taskProgress.set(progress);
try {
return doPerformTask(parameters);
} finally {
taskProgress.remove();
}
}
@Override
public Map<String, Object> performTask(ITaskProgress progress, Map<String, Object> parameters) throws Throwable {
// Формируем параметры задачи
P taskParameters = taskDefinitionRepository.convertTaskParameters(retrieveParameterClass(), parameters);
// Выполняем задачу
R taskResults = doPerformTask(progress, taskParameters);
// Формируем результат выполнения
return taskDefinitionRepository.convertTaskResults(taskResults);
}
/**
* Проверяет, что задача не была прервана
*
* @return Возвращает флаг проверки
*/
protected boolean isCancelled() {
return taskProgress.get().isTaskCanceled();
}
/**
* Формирует и возвращает код шага выполнения задачи
*
* @param stepName код шага
* @return Возвращает сформированный код шага выполнения задачи
*/
protected String createMessageCode(String stepName) {
return getClass().getSimpleName() + "." + stepName;
}
/**
* Публикует событие изменения прогресса выполняемой задачи
*
* @param progress прогресс выполнения задачи
*/
protected void changeProgress(TaskProgress progress) {
taskProgress.get().changeTaskProgress(retrieveName(), progress);
}
/**
* Формирует дескриптор прогресса выполнения и публикует событие
*
* @param percent процент выполнения
* @param step текущий шаг выполнения задачи
* @param code код шага
* @param arguments аргументы локализации
*/
protected void changeProgress(int percent, String step, String code, Object... arguments) {
changeProgress(new TaskProgress(Math.min(percent, 100), step, createMessageCode(code), arguments));
}
/**
* Формирует дескриптор прогресса выполнения и публикует событие
*
* @param progressHolder текущий прогресс выполнения
* @param step текущий шаг выполнения задачи
* @param code код шага
* @param arguments аргументы локализации
*/
protected void changeProgress(TaskProgressHolder progressHolder, String step, String code, Object... arguments) {
changeProgress(
Math.round(progressHolder.totalProgress() * 100.0f),
step,
code,
arguments
);
}
}