package ru.ulstu.students.service; import org.apache.commons.lang3.StringUtils; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.ulstu.core.util.DateUtils; import ru.ulstu.deadline.model.Deadline; import ru.ulstu.deadline.service.DeadlineService; import ru.ulstu.students.model.Scheduler; import ru.ulstu.students.model.Task; import ru.ulstu.students.model.TaskDto; import ru.ulstu.students.model.TaskFilterDto; import ru.ulstu.students.repository.SchedulerRepository; import ru.ulstu.students.repository.TaskRepository; import ru.ulstu.tags.model.Tag; import ru.ulstu.tags.service.TagService; import ru.ulstu.timeline.service.EventService; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.stream.Collectors; import static org.springframework.util.ObjectUtils.isEmpty; import static ru.ulstu.core.util.StreamApiUtils.convert; import static ru.ulstu.students.model.Task.TaskStatus.IN_WORK; @Service public class TaskService { private final static int MAX_DISPLAY_SIZE = 40; private final TaskRepository taskRepository; private final SchedulerRepository schedulerRepository; private final DeadlineService deadlineService; private final TagService tagService; private final EventService eventService; public TaskService(TaskRepository taskRepository, DeadlineService deadlineService, TagService tagService, SchedulerRepository schedulerRepository, EventService eventService) { this.taskRepository = taskRepository; this.deadlineService = deadlineService; this.tagService = tagService; this.eventService = eventService; this.schedulerRepository = schedulerRepository; } public List findAll() { return taskRepository.findAll(new Sort(Sort.Direction.DESC, "createDate")); } public List findAllDto() { List tasks = convert(findAll(), TaskDto::new); tasks.forEach(taskDto -> taskDto.setTitle(StringUtils.abbreviate(taskDto.getTitle(), MAX_DISPLAY_SIZE))); return tasks; } public TaskDto findOneDto(Integer id) { return new TaskDto(taskRepository.findOne(id)); } public List filter(TaskFilterDto filterDto) { if (filterDto.getOrder().compareTo("new") == 0) { return convert(taskRepository.filterNew( filterDto.getStatus(), filterDto.getTag() == null ? null : tagService.findById(filterDto.getTag())), TaskDto::new); } else { return convert(taskRepository.filterOld( filterDto.getStatus(), filterDto.getTag() == null ? null : tagService.findById(filterDto.getTag())), TaskDto::new); } } @Transactional public Integer create(TaskDto taskDto) throws IOException { Task newTask = copyFromDto(new Task(), taskDto); newTask = taskRepository.save(newTask); eventService.createFromTask(newTask); return newTask.getId(); } private Task copyFromDto(Task task, TaskDto taskDto) throws IOException { task.setTitle(taskDto.getTitle()); task.setDescription(taskDto.getDescription()); task.setStatus(taskDto.getStatus() == null ? IN_WORK : taskDto.getStatus()); task.setDeadlines(deadlineService.saveOrCreate(taskDto.getDeadlines())); task.setCreateDate(task.getCreateDate() == null ? new Date() : task.getCreateDate()); task.setUpdateDate(new Date()); task.getTags().clear(); task.setTags(tagService.saveOrCreate(taskDto.getTags())); return task; } @Transactional public Integer update(TaskDto taskDto) throws IOException { Task task = taskRepository.findOne(taskDto.getId()); taskRepository.save(copyFromDto(task, taskDto)); eventService.updateTaskDeadlines(task); return task.getId(); } @Transactional public boolean delete(Integer taskId) throws IOException { if (taskRepository.exists(taskId)) { Task scheduleTask = taskRepository.findOne(taskId); Scheduler sch = schedulerRepository.findOneByTask(scheduleTask); if (sch != null) { schedulerRepository.delete(sch.getId()); } taskRepository.delete(taskId); return true; } return false; } public void save(TaskDto taskDto) throws IOException { if (isEmpty(taskDto.getId())) { create(taskDto); } else { update(taskDto); } } private void copyMainPart(Task newTask, Task task) { newTask.setTitle(task.getTitle()); newTask.setTags(tagService.saveOrCreate(task.getTags())); newTask.setCreateDate(new Date()); newTask.setStatus(Task.TaskStatus.LOADED_FROM_KIAS); } private Task copyTaskWithNewDates(Task task) { Task newTask = new Task(); copyMainPart(newTask, task); Calendar cal1 = DateUtils.getCalendar(newTask.getCreateDate()); Calendar cal2 = DateUtils.getCalendar(task.getCreateDate()); Integer interval = cal1.get(Calendar.DAY_OF_YEAR) - cal2.get(Calendar.DAY_OF_YEAR); newTask.setDeadlines(newDatesDeadlines(task.getDeadlines(), interval)); return newTask; } private List newDatesDeadlines(List deadlines, Integer interval) { return deadlines .stream() .map(deadline -> { Deadline newDeadline = new Deadline(); Date newDate = DateUtils.addDays(deadline.getDate(), interval); newDeadline.setDescription(deadline.getDescription()); newDeadline.setDate(newDate); return deadlineService.create(newDeadline); }).collect(Collectors.toList()); } private Task copyTaskWithNewYear(Task task) { Task newTask = new Task(); copyMainPart(newTask, task); newTask.setDeadlines(newYearDeadlines(task.getDeadlines())); return newTask; } private List newYearDeadlines(List deadlines) { return deadlines .stream() .map(deadline -> { Deadline newDeadline = new Deadline(); newDeadline.setDescription(deadline.getDescription()); newDeadline.setDate(DateUtils.addYears(deadline.getDate(), 1)); return deadlineService.create(newDeadline); }).collect(Collectors.toList()); } private boolean equalsDate(Task task) { Calendar taskDate = DateUtils.getCalendar(task.getCreateDate()); Calendar nowDate = DateUtils.getCalendar(new Date()); return (taskDate.get(Calendar.DAY_OF_MONTH) == nowDate.get(Calendar.DAY_OF_MONTH) && taskDate.get(Calendar.MONTH) + 1 == nowDate.get(Calendar.MONTH) + 1 && taskDate.get(Calendar.YEAR) + 1 == nowDate.get(Calendar.YEAR)); } @Transactional public List generateYearTasks() { Set tags = checkRepeatingTags(false); List tasks = new ArrayList<>(); tags.forEach(tag -> { Task singleTask = findTasksByTag(tag).get(0); if (equalsDate(singleTask)) { if (!tasks.contains(singleTask)) { tasks.add(singleTask); } } }); if (tasks != null) { tasks.forEach(task -> { Task newTask = copyTaskWithNewYear(task); taskRepository.save(newTask); }); return tasks; } return null; } @Transactional public Set checkRepeatingTags(Boolean createPeriodTask) { //param: false = year task; true = period task Map tagsCount = new TreeMap<>(); List tags = tagService.getTags(); List tasks = taskRepository.findAllYear(DateUtils.clearTime(DateUtils.addYears(new Date(), -1))); tags.forEach(tag -> tagsCount.put(tag, tasks .stream() .filter(task -> task.getTags().contains(tag)) .count())); if (!createPeriodTask) { return tagsCount .entrySet() .stream() .filter(tagLongEntry -> tagLongEntry.getValue() == 1) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) .keySet(); } else { return tagsCount .entrySet() .stream() .filter(tagLongEntry -> tagLongEntry.getValue() >= 2) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) .keySet(); } } public List getTaskStatuses() { return Arrays.asList(Task.TaskStatus.values()); } public List getTags() { return tagService.getTags(); } public List findTasksByTag(Tag tag) { return taskRepository.findByTag(tag); } @Transactional public Task createPeriodTask(Scheduler scheduler) { Task newTask = copyTaskWithNewDates(scheduler.getTask()); taskRepository.save(newTask); return newTask; } }