diff --git a/resources/task.csv b/resources/task.csv new file mode 100644 index 0000000..6958abc --- /dev/null +++ b/resources/task.csv @@ -0,0 +1,6 @@ +id,type,name,status,description,epic +1,TASK,Дом,NEW,Убраться в кухни и ванной, +2,TASK,Работа,IN_PROGRESS,Сделать куча рутины и пойти домой:), +3,EPIC,Прогулка,NEW,Прежде чем погулять нужно:, +4,EPIC,Приготовить кофе,NEW,Пойти на кухню и:, + diff --git a/src/ru/yandex/javacource/golotin/schedule/Main.java b/src/ru/yandex/javacource/golotin/schedule/Main.java index bf9e5d0..8e49743 100644 --- a/src/ru/yandex/javacource/golotin/schedule/Main.java +++ b/src/ru/yandex/javacource/golotin/schedule/Main.java @@ -4,12 +4,13 @@ import ru.yandex.javacource.golotin.schedule.model.Status; import ru.yandex.javacource.golotin.schedule.model.Subtask; import ru.yandex.javacource.golotin.schedule.model.Task; -import ru.yandex.javacource.golotin.schedule.service.InMemoryTaskManager; + +import ru.yandex.javacource.golotin.schedule.service.Manager; import ru.yandex.javacource.golotin.schedule.service.TaskManager; public class Main { public static void main(String[] args) { - TaskManager taskManager = new InMemoryTaskManager(); + TaskManager taskManager = Manager.getDefault(); taskManager.createTask(new Task("Дом", Status.NEW, "Убраться в кухни и ванной")); taskManager.createTask(new Task("Работа", Status.IN_PROGRESS, "Сделать куча рутины и пойти домой:)")); @@ -30,13 +31,6 @@ public static void main(String[] args) { System.out.println(taskManager.getTasks()); System.out.println(taskManager.getEpics()); - taskManager.deleteTask(1); - taskManager.deleteEpic(1); - taskManager.deleteSubtask(1); - - taskManager.cleanTasks(); - taskManager.cleanSubtasks(); - taskManager.cleanEpics(); } } \ No newline at end of file diff --git a/src/ru/yandex/javacource/golotin/schedule/exception/ManagerSaveException.java b/src/ru/yandex/javacource/golotin/schedule/exception/ManagerSaveException.java new file mode 100644 index 0000000..61cd6ef --- /dev/null +++ b/src/ru/yandex/javacource/golotin/schedule/exception/ManagerSaveException.java @@ -0,0 +1,18 @@ +package ru.yandex.javacource.golotin.schedule.exception; + +public class ManagerSaveException extends RuntimeException { + public ManagerSaveException() { + } + + public ManagerSaveException(String message) { + super(message); + } + + public ManagerSaveException(String message, Throwable cause) { + super(message, cause); + } + + public ManagerSaveException(Throwable cause) { + super(cause); + } +} diff --git a/src/ru/yandex/javacource/golotin/schedule/exception/NotFoundException.java b/src/ru/yandex/javacource/golotin/schedule/exception/NotFoundException.java new file mode 100644 index 0000000..09ef1ad --- /dev/null +++ b/src/ru/yandex/javacource/golotin/schedule/exception/NotFoundException.java @@ -0,0 +1,18 @@ +package ru.yandex.javacource.golotin.schedule.exception; + +public class NotFoundException extends RuntimeException { + public NotFoundException() { + } + + public NotFoundException(String message) { + super(message); + } + + public NotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public NotFoundException(Throwable cause) { + super(cause); + } +} diff --git a/src/ru/yandex/javacource/golotin/schedule/model/Epic.java b/src/ru/yandex/javacource/golotin/schedule/model/Epic.java index bd4eea1..7176116 100644 --- a/src/ru/yandex/javacource/golotin/schedule/model/Epic.java +++ b/src/ru/yandex/javacource/golotin/schedule/model/Epic.java @@ -1,15 +1,20 @@ package ru.yandex.javacource.golotin.schedule.model; import java.util.ArrayList; +import java.util.List; public class Epic extends Task { - private final ArrayList subtaskIds = new ArrayList<>(); + private final List subtaskIds = new ArrayList<>(); public Epic(String name, Status status, String description) { super(name, status, description); } + public Epic(int id, String name, String description, Status status) { + super(name, status, description); + setId(id); + } public void addSubtaskId(int id) { subtaskIds.add(id); @@ -23,10 +28,14 @@ public void removeSubtask(int id) { subtaskIds.remove(id); } - public ArrayList getSubtaskIds() { + public List getSubtaskIds() { return subtaskIds; } + public TaskType getType() { + return TaskType.EPIC; + } + @Override public String toString() { return "Epic{" + diff --git a/src/ru/yandex/javacource/golotin/schedule/model/Subtask.java b/src/ru/yandex/javacource/golotin/schedule/model/Subtask.java index 9c0e1ce..53ed50c 100644 --- a/src/ru/yandex/javacource/golotin/schedule/model/Subtask.java +++ b/src/ru/yandex/javacource/golotin/schedule/model/Subtask.java @@ -4,16 +4,28 @@ public class Subtask extends Task { private Integer epicId; - public Subtask(String name, Status status, String description,int epicId) { + public Subtask(String name, Status status, String description, int epicId) { super(name, status, description); setEpicId(epicId); } + public Subtask(int id, String name, String description, Status status, Integer epicId) { + super(name, status, description); + setId(id); + setEpicId(epicId); + } + + @Override public Integer getEpicId() { return epicId; } + @Override + public TaskType getType() { + return TaskType.SUBTASK; + } + public void setEpicId(Integer epicId) { this.epicId = epicId; } diff --git a/src/ru/yandex/javacource/golotin/schedule/model/Task.java b/src/ru/yandex/javacource/golotin/schedule/model/Task.java index 2fa635c..adf1482 100644 --- a/src/ru/yandex/javacource/golotin/schedule/model/Task.java +++ b/src/ru/yandex/javacource/golotin/schedule/model/Task.java @@ -14,6 +14,13 @@ public Task(String name, Status status, String description) { this.description = description; } + public Task(int id, String name, String description, Status status) { + setId(id); + this.name = name; + this.status = status; + this.description = description; + } + public int getId() { return id; } @@ -26,6 +33,10 @@ public String getName() { return name; } + public Integer getEpicId() { + return null; + } + public void setName(String name) { this.name = name; } @@ -34,6 +45,10 @@ public String getDescription() { return description; } + public TaskType getType() { + return TaskType.TASK; + } + public void setDescription(String description) { this.description = description; } diff --git a/src/ru/yandex/javacource/golotin/schedule/model/TaskType.java b/src/ru/yandex/javacource/golotin/schedule/model/TaskType.java new file mode 100644 index 0000000..b3fda4f --- /dev/null +++ b/src/ru/yandex/javacource/golotin/schedule/model/TaskType.java @@ -0,0 +1,7 @@ +package ru.yandex.javacource.golotin.schedule.model; + +public enum TaskType { + TASK, + SUBTASK, + EPIC +} diff --git a/src/ru/yandex/javacource/golotin/schedule/service/FileBackedTaskManager.java b/src/ru/yandex/javacource/golotin/schedule/service/FileBackedTaskManager.java new file mode 100644 index 0000000..c162686 --- /dev/null +++ b/src/ru/yandex/javacource/golotin/schedule/service/FileBackedTaskManager.java @@ -0,0 +1,177 @@ +package ru.yandex.javacource.golotin.schedule.service; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.*; + +import java.nio.file.Files; + +import java.util.Map; + +import ru.yandex.javacource.golotin.schedule.exception.ManagerSaveException; +import ru.yandex.javacource.golotin.schedule.model.*; + +public class FileBackedTaskManager extends InMemoryTaskManager { + + private static final String HEADER = "id,type,name,status,description,epic"; + private final File file; + + public FileBackedTaskManager(File file) { + super(Manager.getDefaultHistory()); + this.file = file; + } + + public static FileBackedTaskManager loadFromFile(File file) { + final FileBackedTaskManager taskManager = new FileBackedTaskManager(file); + try { + final String csv = Files.readString(file.toPath()); + final String[] lines = csv.split(System.lineSeparator()); + int generatorId = 0; + for (int i = 1; i < lines.length; i++) { + String line = lines[i]; + if (line.isEmpty()) { + break; + } + final Task task = taskFromString(line); + final int id = task.getId(); + if (id > generatorId) { + generatorId = id; + } + if (task.getType() == TaskType.TASK) { + taskManager.createTask(task); + } else if (task.getType() == TaskType.SUBTASK) { + taskManager.createSubtask(new Subtask(task.getId(), task.getName(), task.getDescription(), + task.getStatus(), task.getEpicId())); + } else if (task.getType() == TaskType.EPIC) { + taskManager.createEpic(new Epic(task.getId(), task.getName(), task.getDescription(), + task.getStatus())); + for (Subtask subtask : taskManager.subtasks.values()) {// Поиск подзадач эпика + if (subtask.getEpicId() == task.getId()) { + Epic epic = taskManager.epics.get(task.getId()); + epic.addSubtaskId(subtask.getId()); + } + } + } + } + for (Map.Entry e : taskManager.subtasks.entrySet()) { + final Subtask subtask = e.getValue(); + final Epic epic = taskManager.epics.get(subtask.getEpicId()); + epic.addSubtaskId(subtask.getId()); + } + taskManager.counterId = generatorId; + } catch (IOException e) { + throw new ManagerSaveException("Невозможно прочитать файл: " + file.getName(), e); + } + return taskManager; + } + + @Override + public Task createTask(Task task) { + Task newTask = super.createTask(task); + saveToFile(); + return newTask; + } + + @Override + public Epic createEpic(Epic epic) { + Epic newEpic = super.createEpic(epic); + saveToFile(); + return newEpic; + } + + @Override + public Subtask createSubtask(Subtask subtask) { + Subtask newSubtask = super.createSubtask(subtask); + saveToFile(); + return newSubtask; + } + + @Override + public void updateTask(Task task) { + super.updateTask(task); + saveToFile(); + } + + @Override + public void updateEpic(Epic epic) { + super.updateEpic(epic); + saveToFile(); + } + + @Override + public void updateSubtask(Subtask subTask) { + super.updateSubtask(subTask); + saveToFile(); + } + + @Override + public void deleteTask(int id) { + super.deleteTask(id); + saveToFile(); + } + + @Override + public void deleteEpic(int id) { + super.deleteEpic(id); + saveToFile(); + } + + @Override + public void deleteSubtask(int id) { + super.deleteSubtask(id); + saveToFile(); + } + + public static String toString(Task task) { + return task.getId() + "," + task.getType() + "," + task.getName() + "," + task.getStatus() + "," + + task.getDescription() + "," + (task.getType().equals(TaskType.SUBTASK) ? task.getEpicId() : ""); + } + + + public static Task taskFromString(String value) { + final String[] values = value.split(","); + final int id = Integer.parseInt(values[0]); + final TaskType type = TaskType.valueOf(values[1]); + final String name = values[2]; + final Status status = Status.valueOf(values[3]); + final String description = values[4]; + if (type == TaskType.TASK) { + return new Task(id, name, description, status); + } + if (type == TaskType.SUBTASK) { + final int epicId = Integer.parseInt(values[5]); + return new Subtask(id, name, description, status, epicId); + } + + return new Epic(id, name, description, status); + } + + protected void saveToFile() { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { + writer.write(HEADER); + writer.newLine(); + + for (Map.Entry entry : tasks.entrySet()) { + final Task task = entry.getValue(); + writer.write(toString(task)); + writer.newLine(); + } + + for (Map.Entry entry : subtasks.entrySet()) { + final Task task = entry.getValue(); + writer.write(toString(task)); + writer.newLine(); + } + + for (Map.Entry entry : epics.entrySet()) { + final Task task = entry.getValue(); + writer.write(toString(task)); + writer.newLine(); + } + + writer.newLine(); + } catch (IOException e) { + throw new ManagerSaveException("Ошибка сохранения файла: " + file.getName(), e); + } + } +} diff --git a/src/ru/yandex/javacource/golotin/schedule/service/InMemoryTaskManager.java b/src/ru/yandex/javacource/golotin/schedule/service/InMemoryTaskManager.java index 4d81f5f..f5cb431 100644 --- a/src/ru/yandex/javacource/golotin/schedule/service/InMemoryTaskManager.java +++ b/src/ru/yandex/javacource/golotin/schedule/service/InMemoryTaskManager.java @@ -1,5 +1,6 @@ package ru.yandex.javacource.golotin.schedule.service; +import ru.yandex.javacource.golotin.schedule.exception.NotFoundException; import ru.yandex.javacource.golotin.schedule.model.Epic; import ru.yandex.javacource.golotin.schedule.model.Status; import ru.yandex.javacource.golotin.schedule.model.Subtask; @@ -13,10 +14,18 @@ public class InMemoryTaskManager implements TaskManager { protected int counterId = 0; - final Map tasks = new HashMap<>(); - final Map epics = new HashMap<>(); - final Map subtasks = new HashMap<>(); - final HistoryManager historyManager = Manager.getDefaultHistory(); + protected final Map tasks; + protected final Map epics; + protected final Map subtasks; + protected final HistoryManager historyManager; + + + public InMemoryTaskManager(HistoryManager historyManager) { + this.historyManager = historyManager; // 3 + this.tasks = new HashMap<>(); + this.epics = new HashMap<>(); + this.subtasks = new HashMap<>(); + } @Override public Task createTask(Task task) {// создание Task @@ -134,17 +143,17 @@ public void deleteEpic(int id) {// удаление по id Epic } @Override - public ArrayList getTasks() { + public List getTasks() { return new ArrayList<>(tasks.values()); }// получаем список Tasks @Override - public ArrayList getEpics() { + public List getEpics() { return new ArrayList<>(epics.values()); }// получаем список Epics @Override - public ArrayList getEpicSubtasks(int epicId) {// получаем список Epic с Subtasks + public List getEpicSubtasks(int epicId) {// получаем список Epic с Subtasks Epic epic = epics.get(epicId); ArrayList getSubtasks = null; for (Integer subtaskId : epic.getSubtaskIds()) { @@ -158,6 +167,9 @@ public ArrayList getEpicSubtasks(int epicId) {// получаем сп @Override public Task getTask(int id) {// получаем Task по id final Task task = tasks.get(id); + if (task == null) { + throw new NotFoundException("Задача с ид=" + id); + } historyManager.add(task); return task; @@ -166,6 +178,9 @@ public Task getTask(int id) {// получаем Task по id @Override public Epic getEpic(int id) {// получаем Epic по id final Epic epic = epics.get(id); + if (epic == null) { + throw new NotFoundException("Эпик с ид=" + id); + } historyManager.add(epic); return epic; } @@ -173,6 +188,9 @@ public Epic getEpic(int id) {// получаем Epic по id @Override public Subtask getSubtask(int id) {// получаем Subtask по id final Subtask subtask = subtasks.get(id); + if (subtask == null) { + throw new NotFoundException("Подзадача с ид=" + id); + } historyManager.add(subtask); return subtask; } diff --git a/src/ru/yandex/javacource/golotin/schedule/service/Manager.java b/src/ru/yandex/javacource/golotin/schedule/service/Manager.java index dd0f7c9..d9c4911 100644 --- a/src/ru/yandex/javacource/golotin/schedule/service/Manager.java +++ b/src/ru/yandex/javacource/golotin/schedule/service/Manager.java @@ -1,8 +1,10 @@ package ru.yandex.javacource.golotin.schedule.service; +import java.io.File; + public class Manager { - public static TaskManager getDefaults() { - return new InMemoryTaskManager(); + public static TaskManager getDefault() { + return new FileBackedTaskManager(new File("resources/task.csv")); } public static InMemoryHistoryManager getDefaultHistory() { diff --git a/src/ru/yandex/javacource/golotin/schedule/service/TaskManager.java b/src/ru/yandex/javacource/golotin/schedule/service/TaskManager.java index 9740aeb..d8f5a77 100644 --- a/src/ru/yandex/javacource/golotin/schedule/service/TaskManager.java +++ b/src/ru/yandex/javacource/golotin/schedule/service/TaskManager.java @@ -4,13 +4,12 @@ import ru.yandex.javacource.golotin.schedule.model.Subtask; import ru.yandex.javacource.golotin.schedule.model.Task; -import java.util.ArrayList; import java.util.List; public interface TaskManager { Task createTask(Task task); - Epic createEpic(Epic epic); + Task createEpic(Epic epic); Subtask createSubtask(Subtask subtask);