package com.qprogramming.tasq.task.link;
import com.qprogramming.tasq.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@Service
public class TaskLinkService {
private TaskLinkRepository linkRepo;
@Autowired
public TaskLinkService(TaskLinkRepository linkRepo) {
this.linkRepo = linkRepo;
}
public void save(TaskLink link) {
linkRepo.save(link);
}
public void delete(TaskLink link) {
linkRepo.delete(link);
}
/**
* Searches for existing link
*
* @param taskA
* @param taskB
* @param type
* @return link if it was found ( or counter link was found )
*/
public TaskLink findLink(String taskA, String taskB, TaskLinkType type) {
if (type.equals(TaskLinkType.RELATES_TO)) {
TaskLink link = linkRepo.findByTaskAAndTaskBAndLinkType(taskA, taskB, type);
if (link == null) {
link = linkRepo.findByTaskAAndTaskBAndLinkType(taskB, taskA, type);
}
return link;
} else {
return searchLinkAndCounterLink(taskA, taskB, type);
}
}
public Map<TaskLinkType, List<String>> findTaskLinks(String taskID) {
Map<TaskLinkType, List<String>> result = new LinkedHashMap<>();
Map<TaskLinkType, List<String>> finalResult = new LinkedHashMap<>();
// Prepopulate map to maintain order
result.put(TaskLinkType.RELATES_TO, new LinkedList<>());
result.put(TaskLinkType.BLOCKS, new LinkedList<>());
result.put(TaskLinkType.IS_BLOCKED_BY, new LinkedList<>());
result.put(TaskLinkType.DUPLICATES, new LinkedList<>());
result.put(TaskLinkType.IS_DUPLICATED_BY, new LinkedList<>());
List<TaskLink> listA = linkRepo.findByTaskA(taskID);
for (TaskLink taskLink : listA) {
List<String> tasks = result.get(taskLink.getLinkType());
tasks.add(taskLink.getTaskB());
result.put(taskLink.getLinkType(), tasks);
}
List<TaskLink> listB = linkRepo.findByTaskB(taskID);
for (TaskLink taskLink : listB) {
List<String> tasks = result.get(switchType(taskLink.getLinkType()));
if (tasks == null) {
tasks = new LinkedList<>();
}
tasks.add(taskLink.getTaskA());
result.put(switchType(taskLink.getLinkType()), tasks);
}
// clean all potential empty results
result.entrySet().stream().filter(entry -> !entry.getValue().isEmpty()).forEachOrdered(entry -> finalResult.put(entry.getKey(), entry.getValue()));
return finalResult;
}
public void deleteTaskLinks(Task task) {
List<TaskLink> listA = linkRepo.findByTaskA(task.getId());
listA.addAll(linkRepo.findByTaskB(task.getId()));
linkRepo.delete(listA);
}
public List<TaskLink> findAllTaskLinks(Task task) {
List<TaskLink> list = linkRepo.findByTaskA(task.getId());
list.addAll(linkRepo.findByTaskB(task.getId()));
return list;
}
/**
* Searches if link exists, then checks if there is counter link ( block ->
* is blocked by ) or if taskB don't have link either
*
* @param taskA
* @param taskB
* @param type
* @return
*/
private TaskLink searchLinkAndCounterLink(String taskA, String taskB, TaskLinkType type) {
TaskLink link;
link = linkRepo.findByTaskAAndTaskBAndLinkType(taskA, taskB, type);
if (link == null) {
link = linkRepo.findByTaskAAndTaskBAndLinkType(taskB, taskA, switchType(type));
if (link == null) {
return linkRepo.findByTaskBAndTaskAAndLinkType(taskA, taskB, type);
}
}
return link;
}
private TaskLinkType switchType(TaskLinkType type) {
switch (type) {
case BLOCKS:
return TaskLinkType.IS_BLOCKED_BY;
case IS_BLOCKED_BY:
return TaskLinkType.BLOCKS;
case DUPLICATES:
return TaskLinkType.IS_DUPLICATED_BY;
case IS_DUPLICATED_BY:
return TaskLinkType.DUPLICATES;
default:
return type;
}
}
}