From 1b8e741103669c1258e11b77c0f6122a98edd3dd Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Tue, 29 Jul 2025 06:19:01 +0300 Subject: [PATCH 1/9] Add files via upload --- src/Main.java | 72 +++--- src/manager/FileBackedTaskManager.java | 217 ++++++++++++++++++ src/manager/HistoryManager.java | 3 + src/manager/InMemoryHistoryManager.java | 3 +- src/manager/InMemoryTaskManager.java | 293 ++++++++++++++---------- src/manager/Managers.java | 6 + src/manager/TaskManager.java | 16 +- src/model/Epic.java | 32 ++- src/model/Subtask.java | 19 +- src/model/Task.java | 83 +++++-- 10 files changed, 545 insertions(+), 199 deletions(-) create mode 100644 src/manager/FileBackedTaskManager.java diff --git a/src/Main.java b/src/Main.java index af6285e..893737a 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,54 +1,52 @@ -import manager.InMemoryTaskManager; -import manager.Managers; +import manager.FileBackedTaskManager; import manager.TaskManager; -import model.Epic; -import model.Status; -import model.Subtask; -import model.Task; +import model.*; -import java.util.List; +import java.io.File; +import java.time.Duration; +import java.time.LocalDateTime; public class Main { public static void main(String[] args) { - TaskManager manager = Managers.getDefault(); - Task task1 = new Task("Task1", "Desc", Status.NEW); - Task task2 = new Task("Task2", "Desc", Status.NEW); + File file = new File("tasks.csv"); + TaskManager manager = new FileBackedTaskManager(file); + + Task task1 = new Task("Task 1", "Simple task", + Status.NEW, Duration.ofMinutes(30), LocalDateTime.of(2025, 7, 1, 8, 0)); // 08:00–08:30 + Task task2 = new Task("Task 2", "Another task", + Status.NEW, Duration.ofMinutes(45), LocalDateTime.of(2025, 7, 1, 8, 45)); // 08:45–09:30 manager.addTask(task1); manager.addTask(task2); - Epic epic1 = new Epic("Epic1", "Desc"); - Epic epic2 = new Epic("Epic2", "Desc"); - manager.addEpic(epic1); - manager.addEpic(epic2); + Epic epic = new Epic("Epic 1", "Epic with subtasks"); + manager.addEpic(epic); - Subtask subtask1 = new Subtask("Sub1", "Desc", Status.NEW, epic1.getId()); - Subtask subtask2 = new Subtask("Sub2", "Desc", Status.NEW, epic1.getId()); + Subtask subtask1 = new Subtask("Subtask 1", "Part 1", + Status.NEW, epic.getId(), Duration.ofMinutes(60), LocalDateTime.of(2025, 7, 1, 10, 0)); // 10:00–11:00 + Subtask subtask2 = new Subtask("Subtask 2", "Part 2", + Status.DONE, epic.getId(), Duration.ofMinutes(90), LocalDateTime.of(2025, 7, 1, 11, 30)); // 11:30–13:00 manager.addSubtask(subtask1); manager.addSubtask(subtask2); - manager.getTaskById(task1.getId()); - manager.getEpicById(epic1.getId()); - manager.getTaskById(task1.getId()); - manager.getSubtaskById(subtask1.getId()); - printHistory(manager); + System.out.println("=== Prioritized Tasks ==="); + for (Task task : manager.getPrioritizedTasks()) { + System.out.println(task + " | start=" + task.getStartTime() + " | end=" + task.getEndTime()); + } - manager.removeTaskById(task1.getId()); - printHistory(manager); + TaskManager loadedManager = FileBackedTaskManager.loadFromFile(file); + System.out.println("\n=== Loaded Tasks ==="); + for (Task task : loadedManager.getAllTasks()) { + System.out.println(task); + } - manager.removeEpicById(epic1.getId()); - printHistory(manager); // [] - } + System.out.println("\n=== Loaded Epics ==="); + for (Epic e : loadedManager.getAllEpics()) { + System.out.println(e); + } - private static void printHistory(TaskManager manager) { - List history = manager.getHistory(); - if (history.isEmpty()) { - System.out.println("History is empty"); - } else { - System.out.println("\nView history (" + history.size() + " items):"); - for (int i = 0; i < history.size(); i++) { - Task task = history.get(i); - System.out.println((i + 1) + ". " + task.getTitle() + " [ID:" + task.getId() + "]"); - } + System.out.println("\n=== Loaded Subtasks ==="); + for (Subtask s : loadedManager.getAllSubtasks()) { + System.out.println(s); } } -} \ No newline at end of file +} diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java new file mode 100644 index 0000000..f4c4c7c --- /dev/null +++ b/src/manager/FileBackedTaskManager.java @@ -0,0 +1,217 @@ +package manager; + +import model.Epic; +import model.Subtask; +import model.Task; +import model.Status; + +import java.io.*; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.*; + +public class FileBackedTaskManager extends InMemoryTaskManager { + + private final File file; + + public FileBackedTaskManager(File file) { + this.file = file; + } + + protected void save() { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { + writer.write("id,type,name,status,description,epic,duration,startTime\n"); + + for (Task task : getAllTasks()) { + writer.write(toString(task) + "\n"); + } + for (Epic epic : getAllEpics()) { + writer.write(toString(epic) + "\n"); + } + for (Subtask subtask : getAllSubtasks()) { + writer.write(toString(subtask) + "\n"); + } + + writer.write("\n"); + String history = historyToString(getHistory()); + writer.write(history); + + } catch (IOException e) { + System.out.println("Ошибка при сохранении в файл: " + e.getMessage()); + } + } + + private String toString(Task task) { + StringBuilder sb = new StringBuilder(); + sb.append(task.getId()).append(","); + if (task instanceof Epic) { + sb.append("EPIC"); + } else if (task instanceof Subtask) { + sb.append("SUBTASK"); + } else { + sb.append("TASK"); + } + sb.append(","); + sb.append(task.getTitle()).append(","); + sb.append(task.getStatus()).append(","); + sb.append(task.getDescription()).append(","); + if (task instanceof Subtask) { + sb.append(((Subtask) task).getEpicId()); + } else { + sb.append(""); + } + sb.append(","); + sb.append(task.getDuration() != null ? task.getDuration().toMinutes() : "").append(","); + sb.append(task.getStartTime() != null ? task.getStartTime() : ""); + return sb.toString(); + } + + private List historyFromString(String value) { + List history = new ArrayList<>(); + if (value == null || value.isEmpty()) { + return history; + } + String[] ids = value.split(","); + for (String idStr : ids) { + history.add(Integer.parseInt(idStr)); + } + return history; + } + + private String historyToString(List history) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < history.size(); i++) { + sb.append(history.get(i).getId()); + if (i < history.size() - 1) { + sb.append(","); + } + } + return sb.toString(); + } + + + public static FileBackedTaskManager loadFromFile(File file) { + FileBackedTaskManager manager = new FileBackedTaskManager(file); + + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line = reader.readLine(); + + while ((line = reader.readLine()) != null && !line.isEmpty()) { + Task task = fromString(line); + if (task instanceof Epic) { + manager.addEpic((Epic) task); + } else if (task instanceof Subtask) { + manager.addSubtask((Subtask) task); + } else { + manager.addTask(task); + } + } + + String emptyLine = reader.readLine(); + + if (emptyLine != null) { + String historyLine = reader.readLine(); + if (historyLine != null && !historyLine.isEmpty()) { + List historyIds = manager.historyFromString(historyLine); + for (Integer id : historyIds) { + Task t = manager.getTaskById(id); + if (t != null) { + manager.historyManager.add(t); + } + } + } + } + + } catch (IOException e) { + System.out.println("Ошибка при загрузке из файла: " + e.getMessage()); + } + + return manager; + } + + private static Task fromString(String value) { + String[] parts = value.split(",", -1); + int id = Integer.parseInt(parts[0]); + String type = parts[1]; + String title = parts[2]; + Status status = Status.valueOf(parts[3]); + String description = parts[4]; + String epicIdStr = parts[5]; + String durationStr = parts[6]; + String startTimeStr = parts[7]; + + Duration duration = durationStr.isEmpty() ? null : Duration.ofMinutes(Long.parseLong(durationStr)); + LocalDateTime startTime = startTimeStr.isEmpty() ? null : LocalDateTime.parse(startTimeStr); + + switch (type) { + case "EPIC": + Epic epic = new Epic(title, description); + epic.setId(id); + epic.setStatus(status); + return epic; + case "SUBTASK": + Subtask subtask = new Subtask(title, description, status, Integer.parseInt(epicIdStr), duration, startTime); + subtask.setId(id); + return subtask; + case "TASK": + default: + Task task = new Task(title, description, status, duration, startTime); + task.setId(id); + return task; + } + } + + @Override + public void addTask(Task task) { + super.addTask(task); + save(); + } + + @Override + public void addEpic(Epic epic) { + super.addEpic(epic); + save(); + } + + @Override + public void addSubtask(Subtask subtask) { + super.addSubtask(subtask); + save(); + } + + @Override + public void updateTask(Task task) { + super.updateTask(task); + save(); + } + + @Override + public void updateEpic(Epic epic) { + super.updateEpic(epic); + save(); + } + + @Override + public void updateSubtask(Subtask subtask) { + super.updateSubtask(subtask); + save(); + } + + @Override + public void removeTaskById(int id) { + super.removeTaskById(id); + save(); + } + + @Override + public void removeEpicById(int id) { + super.removeEpicById(id); + save(); + } + + @Override + public void removeSubtaskById(int id) { + super.removeSubtaskById(id); + save(); + } +} \ No newline at end of file diff --git a/src/manager/HistoryManager.java b/src/manager/HistoryManager.java index 079236c..bfe6cfc 100644 --- a/src/manager/HistoryManager.java +++ b/src/manager/HistoryManager.java @@ -4,7 +4,10 @@ import java.util.List; public interface HistoryManager { + void add(Task task); + void remove(int id); + List getHistory(); } \ No newline at end of file diff --git a/src/manager/InMemoryHistoryManager.java b/src/manager/InMemoryHistoryManager.java index 3dd9200..df5343b 100644 --- a/src/manager/InMemoryHistoryManager.java +++ b/src/manager/InMemoryHistoryManager.java @@ -24,7 +24,8 @@ protected static class Node { public void add(Task task) { if (task == null) return; int id = task.getId(); - remove(id); // Удаляем предыдущий просмотр + remove(id); + linkLast(task); } diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 34c5bc2..ee4427b 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -1,63 +1,85 @@ package manager; -import model.Epic; -import model.Status; -import model.Subtask; -import model.Task; - +import model.*; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.*; public class InMemoryTaskManager implements TaskManager { - - protected int nextId = 1; - protected final Map tasks = new HashMap<>(); - protected final Map epics = new HashMap<>(); protected final Map subtasks = new HashMap<>(); - + protected final Map epics = new HashMap<>(); protected final HistoryManager historyManager = Managers.getDefaultHistory(); + protected int nextId = 1; + protected final Set prioritizedTasks = new TreeSet<>(Comparator + .comparing(Task::getStartTime, Comparator.nullsLast(LocalDateTime::compareTo)) + .thenComparingInt(Task::getId)); - private int generateId() { + protected int generateId() { return nextId++; } + private boolean checkTimeIntersection(Task task) { + if (task.getStartTime() == null || task.getEndTime() == null) { + return false; + } + for (Task t : prioritizedTasks) { + if (t.getId() == task.getId() || t.getStartTime() == null || t.getEndTime() == null) continue; + if (!(task.getEndTime().isBefore(t.getStartTime()) || task.getStartTime().isAfter(t.getEndTime()))) { + return true; + } + } + return false; + } + @Override - public void addTask(Task task) { - task.setId(generateId()); - tasks.put(task.getId(), task); + public List getAllTasks() { + return new ArrayList<>(tasks.values()); } @Override - public void addEpic(Epic epic) { - epic.setId(generateId()); - epics.put(epic.getId(), epic); + public List getAllSubtasks() { + return new ArrayList<>(subtasks.values()); } @Override - public void addSubtask(Subtask subtask) { - int epicId = subtask.getEpicId(); - Epic epic = epics.get(epicId); - if (epic != null) { - subtask.setId(generateId()); - subtasks.put(subtask.getId(), subtask); - epic.addSubtask(subtask); - updateEpicStatus(epicId); - } + public List getAllEpics() { + return new ArrayList<>(epics.values()); } @Override - public List getAllTasks() { - return new ArrayList<>(tasks.values()); + public void clearTasks() { + for (Task task : tasks.values()) { + prioritizedTasks.remove(task); + historyManager.remove(task.getId()); + } + tasks.clear(); } @Override - public List getAllEpics() { - return new ArrayList<>(epics.values()); + public void clearSubtasks() { + for (Subtask subtask : subtasks.values()) { + prioritizedTasks.remove(subtask); + historyManager.remove(subtask.getId()); + } + subtasks.clear(); + for (Epic epic : epics.values()) { + epic.getSubtaskIds().clear(); + updateEpicFields(epic); + } } @Override - public List getAllSubtasks() { - return new ArrayList<>(subtasks.values()); + public void clearEpics() { + for (Epic epic : epics.values()) { + historyManager.remove(epic.getId()); + } + for (Subtask subtask : subtasks.values()) { + prioritizedTasks.remove(subtask); + historyManager.remove(subtask.getId()); + } + epics.clear(); + subtasks.clear(); } @Override @@ -67,6 +89,13 @@ public Task getTaskById(int id) { return task; } + @Override + public Subtask getSubtaskById(int id) { + Subtask subtask = subtasks.get(id); + if (subtask != null) historyManager.add(subtask); + return subtask; + } + @Override public Epic getEpicById(int id) { Epic epic = epics.get(id); @@ -75,63 +104,80 @@ public Epic getEpicById(int id) { } @Override - public Subtask getSubtaskById(int id) { - Subtask subtask = subtasks.get(id); - if (subtask != null) historyManager.add(subtask); - return subtask; + public void addTask(Task task) { + if (checkTimeIntersection(task)) { + throw new IllegalArgumentException("Task time overlaps with another task"); + } + task.setId(generateId()); + tasks.put(task.getId(), task); + prioritizedTasks.add(task); } @Override - public void updateTask(Task task) { - if (tasks.containsKey(task.getId())) { - tasks.put(task.getId(), task); + public void addEpic(Epic epic) { + epic.setId(generateId()); + epics.put(epic.getId(), epic); + } + + @Override + public void addSubtask(Subtask subtask) { + if (!epics.containsKey(subtask.getEpicId())) { + throw new IllegalArgumentException("Epic not found"); } + if (checkTimeIntersection(subtask)) { + throw new IllegalArgumentException("Subtask time overlaps with another task"); + } + subtask.setId(generateId()); + subtasks.put(subtask.getId(), subtask); + prioritizedTasks.add(subtask); + Epic epic = epics.get(subtask.getEpicId()); + epic.addSubtaskId(subtask.getId()); + updateEpicFields(epic); } @Override - public void updateEpic(Epic epic) { - int id = epic.getId(); - Epic oldEpic = epics.get(id); - if (oldEpic == null) { - throw new IllegalArgumentException("Эпик с id " + id + " не найден"); + public void updateTask(Task task) { + if (!tasks.containsKey(task.getId())) return; + if (checkTimeIntersection(task)) { + throw new IllegalArgumentException("Task time overlaps with another task"); } - oldEpic.setTitle(epic.getTitle()); - oldEpic.setDescription(epic.getDescription()); + prioritizedTasks.remove(tasks.get(task.getId())); + tasks.put(task.getId(), task); + prioritizedTasks.add(task); } @Override public void updateSubtask(Subtask subtask) { - int id = subtask.getId(); - if (!subtasks.containsKey(id)) { - throw new IllegalArgumentException("Подзадача с id " + id + " не найдена"); + if (!subtasks.containsKey(subtask.getId())) return; + Subtask existingSubtask = subtasks.get(subtask.getId()); + if (existingSubtask.getEpicId() != subtask.getEpicId()) { + throw new IllegalArgumentException("Cannot change epicId of subtask"); } - Subtask existingSubtask = subtasks.get(id); - if (subtask.getEpicId() != existingSubtask.getEpicId()) { - throw new IllegalArgumentException("Нельзя изменить epicId подзадачи"); + if (checkTimeIntersection(subtask)) { + throw new IllegalArgumentException("Subtask time overlaps with another task"); } - subtasks.put(id, subtask); - Epic epic = epics.get(subtask.getEpicId()); - if (epic != null) { - updateEpicStatus(epic.getId()); - } + prioritizedTasks.remove(existingSubtask); + subtasks.put(subtask.getId(), subtask); + prioritizedTasks.add(subtask); + updateEpicFields(epics.get(subtask.getEpicId())); } @Override - public void removeTaskById(int id) { - tasks.remove(id); - historyManager.remove(id); + public void updateEpic(Epic epic) { + int id = epic.getId(); + Epic saved = epics.get(id); + if (saved == null) return; + saved.setTitle(epic.getTitle()); + saved.setDescription(epic.getDescription()); } @Override - public void removeEpicById(int id) { - Epic epic = epics.remove(id); - if (epic != null) { - for (int subId : epic.getSubtaskIds()) { - subtasks.remove(subId); - historyManager.remove(subId); - } + public void removeTaskById(int id) { + Task task = tasks.remove(id); + if (task != null) { + prioritizedTasks.remove(task); historyManager.remove(id); } } @@ -140,90 +186,75 @@ public void removeEpicById(int id) { public void removeSubtaskById(int id) { Subtask subtask = subtasks.remove(id); if (subtask != null) { + prioritizedTasks.remove(subtask); Epic epic = epics.get(subtask.getEpicId()); if (epic != null) { - epic.removeSubtask(id); - updateEpicStatus(epic.getId()); + epic.removeSubtaskId(id); + updateEpicFields(epic); } historyManager.remove(id); } } @Override - public void clearTasks() { - for (int id : tasks.keySet()) { + public void removeEpicById(int id) { + Epic epic = epics.remove(id); + if (epic != null) { + for (int subtaskId : epic.getSubtaskIds()) { + Subtask subtask = subtasks.remove(subtaskId); + if (subtask != null) { + prioritizedTasks.remove(subtask); + historyManager.remove(subtaskId); + } + } historyManager.remove(id); } - tasks.clear(); - } - - @Override - public void clearEpics() { - for (int epicId : epics.keySet()) { - historyManager.remove(epicId); - } - for (int subtaskId : subtasks.keySet()) { - historyManager.remove(subtaskId); - } - epics.clear(); - subtasks.clear(); - } - - @Override - public void clearSubtasks() { - for (int subtaskId : subtasks.keySet()) { - historyManager.remove(subtaskId); - } - subtasks.clear(); - for (Epic epic : epics.values()) { - epic.getSubtaskIds().clear(); - updateEpicStatus(epic.getId()); - } } @Override public List getSubtasksOfEpic(int epicId) { + if (!epics.containsKey(epicId)) return Collections.emptyList(); List result = new ArrayList<>(); - Epic epic = epics.get(epicId); - if (epic != null) { - for (int subId : epic.getSubtaskIds()) { - Subtask subtask = subtasks.get(subId); - if (subtask != null) { - result.add(subtask); - } + for (int subtaskId : epics.get(epicId).getSubtaskIds()) { + Subtask subtask = subtasks.get(subtaskId); + if (subtask != null) { + result.add(subtask); } } return result; } - @Override - public List getHistory() { - return historyManager.getHistory(); - } - - private void updateEpicStatus(int epicId) { - Epic epic = epics.get(epicId); - if (epic == null) return; - - List subtaskIds = epic.getSubtaskIds(); - if (subtaskIds.isEmpty()) { + protected void updateEpicFields(Epic epic) { + List subtasksOfEpic = getSubtasksOfEpic(epic.getId()); + if (subtasksOfEpic.isEmpty()) { epic.setStatus(Status.NEW); + epic.setDuration(Duration.ZERO); + epic.setStartTime(null); + epic.setEndTime(null); return; } boolean allNew = true; boolean allDone = true; - - for (int id : subtaskIds) { - Subtask subtask = subtasks.get(id); - if (subtask == null) continue; - - if (subtask.getStatus() != Status.NEW) { - allNew = false; - } - if (subtask.getStatus() != Status.DONE) { - allDone = false; + Duration totalDuration = Duration.ZERO; + LocalDateTime earliestStart = null; + LocalDateTime latestEnd = null; + + for (Subtask subtask : subtasksOfEpic) { + Status status = subtask.getStatus(); + if (status != Status.NEW) allNew = false; + if (status != Status.DONE) allDone = false; + + if (subtask.getStartTime() != null) { + if (earliestStart == null || subtask.getStartTime().isBefore(earliestStart)) { + earliestStart = subtask.getStartTime(); + } + LocalDateTime subtaskEnd = subtask.getEndTime(); + if (latestEnd == null || subtaskEnd.isAfter(latestEnd)) { + latestEnd = subtaskEnd; + } } + totalDuration = totalDuration.plus(subtask.getDuration()); } if (allNew) { @@ -233,5 +264,19 @@ private void updateEpicStatus(int epicId) { } else { epic.setStatus(Status.IN_PROGRESS); } + + epic.setDuration(totalDuration); + epic.setStartTime(earliestStart); + epic.setEndTime(latestEnd); + } + + @Override + public List getHistory() { + return historyManager.getHistory(); + } + + @Override + public List getPrioritizedTasks() { + return new ArrayList<>(prioritizedTasks); } } \ No newline at end of file diff --git a/src/manager/Managers.java b/src/manager/Managers.java index 64dfb6f..71ee949 100644 --- a/src/manager/Managers.java +++ b/src/manager/Managers.java @@ -1,5 +1,7 @@ package manager; +import java.io.File; + public class Managers { public static TaskManager getDefault() { @@ -9,4 +11,8 @@ public static TaskManager getDefault() { public static HistoryManager getDefaultHistory() { return new InMemoryHistoryManager(); } + + public static TaskManager getFileBackedTaskManager(File file) { + return new FileBackedTaskManager(file); + } } \ No newline at end of file diff --git a/src/manager/TaskManager.java b/src/manager/TaskManager.java index 9a4c891..d97556d 100644 --- a/src/manager/TaskManager.java +++ b/src/manager/TaskManager.java @@ -1,38 +1,52 @@ package manager; -import model.Task; import model.Epic; import model.Subtask; +import model.Task; import java.util.List; public interface TaskManager { void addTask(Task task); + void addEpic(Epic epic); + void addSubtask(Subtask subtask); List getAllTasks(); + List getAllEpics(); + List getAllSubtasks(); Task getTaskById(int id); + Epic getEpicById(int id); + Subtask getSubtaskById(int id); void updateTask(Task task); + void updateEpic(Epic epic); + void updateSubtask(Subtask subtask); void removeTaskById(int id); + void removeEpicById(int id); + void removeSubtaskById(int id); void clearTasks(); + void clearEpics(); + void clearSubtasks(); List getSubtasksOfEpic(int epicId); List getHistory(); + + List getPrioritizedTasks(); } \ No newline at end of file diff --git a/src/model/Epic.java b/src/model/Epic.java index bdbde3d..cd578ea 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -1,34 +1,46 @@ package model; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Objects; public class Epic extends Task { private final List subtaskIds = new ArrayList<>(); + private LocalDateTime endTime; public Epic(String title, String description) { - super(title, description, Status.NEW); + super(title, description, Status.NEW, Duration.ZERO, null); } + public List getSubtaskIds() { return subtaskIds; } - public void addSubtask(Subtask subtask) { - subtaskIds.add(subtask.getId()); + public void addSubtaskId(int id) { + subtaskIds.add(id); } - public void removeSubtask(int subtaskId) { - subtaskIds.remove((Integer) subtaskId); + public void removeSubtaskId(int id) { + subtaskIds.remove(Integer.valueOf(id)); + } + + @Override + public LocalDateTime getEndTime() { + return endTime; + } + + public void setEndTime(LocalDateTime endTime) { + this.endTime = endTime; } @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Epic)) return false; + if (!(o instanceof Epic epic)) return false; if (!super.equals(o)) return false; - Epic epic = (Epic) o; return Objects.equals(subtaskIds, epic.subtaskIds); } @@ -36,6 +48,7 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(super.hashCode(), subtaskIds); } + @Override public String toString() { return "Epic{" + @@ -43,7 +56,10 @@ public String toString() { ", title='" + getTitle() + '\'' + ", description='" + getDescription() + '\'' + ", status=" + getStatus() + + ", startTime=" + getStartTime() + + ", duration=" + getDuration() + + ", endTime=" + getEndTime() + ", subtaskIds=" + subtaskIds + '}'; } -} \ No newline at end of file +} diff --git a/src/model/Subtask.java b/src/model/Subtask.java index 0b4eef5..5ea97ba 100644 --- a/src/model/Subtask.java +++ b/src/model/Subtask.java @@ -1,10 +1,13 @@ package model; +import java.time.Duration; +import java.time.LocalDateTime; + public class Subtask extends Task { - private final int epicId; + private int epicId; - public Subtask(String title, String description, Status status, int epicId) { - super(title, description, status); + public Subtask(String title, String description, Status status, int epicId, Duration duration, LocalDateTime startTime) { + super(title, description, status, duration, startTime); this.epicId = epicId; } @@ -12,14 +15,20 @@ public int getEpicId() { return epicId; } + public void setEpicId(int epicId) { + this.epicId = epicId; + } + @Override public String toString() { return "Subtask{" + - "id=" + getId() + + "epicId=" + epicId + + ", id=" + getId() + ", title='" + getTitle() + '\'' + ", description='" + getDescription() + '\'' + ", status=" + getStatus() + - ", epicId=" + epicId + + ", duration=" + (getDuration() != null ? getDuration().toMinutes() : "null") + + ", startTime=" + getStartTime() + '}'; } } \ No newline at end of file diff --git a/src/model/Task.java b/src/model/Task.java index 79a3730..c89496c 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -1,43 +1,78 @@ package model; - -import java.util.Objects; +import java.time.Duration; +import java.time.LocalDateTime; public class Task { private int id; private String title; private String description; private Status status; + private Duration duration; + private LocalDateTime startTime; - public Task(String title, String description, Status status) { + public Task(String title, String description, Status status, Duration duration, LocalDateTime startTime) { this.title = title; this.description = description; this.status = status; + this.duration = duration; + this.startTime = startTime; } - public int getId() { return id; } - public void setId(int id) { this.id = id; } - public String getTitle() { return title; } - public void setTitle(String title) { this.title = title; } - public String getDescription() { return description; } - public void setDescription(String description) { this.description = description; } - public Status getStatus() { return status; } - public void setStatus(Status status) { this.status = status; } + public int getId() { + return id; + } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Task)) return false; - Task task = (Task) o; - return id == task.id && - Objects.equals(title, task.title) && - Objects.equals(description, task.description) && - status == task.status; + public void setId(int id) { + this.id = id; } - @Override - public int hashCode() { - return Objects.hash(id, title, description, status); + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public Duration getDuration() { + return duration; + } + + public void setDuration(Duration duration) { + this.duration = duration; + } + + public LocalDateTime getStartTime() { + return startTime; + } + + public void setStartTime(LocalDateTime startTime) { + this.startTime = startTime; + } + + public LocalDateTime getEndTime() { + if (startTime != null && duration != null) { + return startTime.plus(duration); + } + return null; } @Override @@ -47,6 +82,8 @@ public String toString() { ", title='" + title + '\'' + ", description='" + description + '\'' + ", status=" + status + + ", duration=" + (duration != null ? duration.toMinutes() : "null") + + ", startTime=" + startTime + '}'; } } \ No newline at end of file From f9f2f1809d1d4985a3ba1d14ae5f8499bfd00242 Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Tue, 29 Jul 2025 06:20:38 +0300 Subject: [PATCH 2/9] Add files via upload --- test/manager/FileBackedTaskManagerTest.java | 105 +++++++++++++++++++ test/manager/InMemoryHistoryManagerTest.java | 56 +++++----- test/manager/InMemoryTaskManagerTest.java | 17 ++- test/model/EpicTest.java | 51 ++++----- test/model/SubtaskTest.java | 47 +++++++++ test/model/TaskTest.java | 96 +++++++---------- 6 files changed, 252 insertions(+), 120 deletions(-) create mode 100644 test/manager/FileBackedTaskManagerTest.java create mode 100644 test/model/SubtaskTest.java diff --git a/test/manager/FileBackedTaskManagerTest.java b/test/manager/FileBackedTaskManagerTest.java new file mode 100644 index 0000000..77dded5 --- /dev/null +++ b/test/manager/FileBackedTaskManagerTest.java @@ -0,0 +1,105 @@ +package test.manager; + +import manager.FileBackedTaskManager; +import manager.TaskManager; +import model.Epic; +import model.Status; +import model.Subtask; +import model.Task; +import org.junit.jupiter.api.*; + +import java.io.File; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class FileBackedTaskManagerTest { + + static File file; + TaskManager manager; + + @BeforeAll + static void beforeAll() { + file = new File("test_data.csv"); + } + + @BeforeEach + void setUp() { + manager = new FileBackedTaskManager(file); + manager.clearTasks(); + manager.clearEpics(); + manager.clearSubtasks(); + } + + @AfterEach + void tearDown() { + if (file.exists()) { + file.delete(); + } + } + + @Test + public void testSaveAndLoad() { + Task task = new Task("Task 1", "Description 1", Status.NEW, + Duration.ofMinutes(30), LocalDateTime.of(2025, 7, 1, 9, 0)); + manager.addTask(task); + + Epic epic = new Epic("Epic 1", "Epic description"); + manager.addEpic(epic); + + Subtask subtask1 = new Subtask("Subtask 1", "Part 1", Status.NEW, + epic.getId(), Duration.ofMinutes(60), LocalDateTime.of(2025, 7, 1, 10, 0)); + Subtask subtask2 = new Subtask("Subtask 2", "Part 2", Status.DONE, + epic.getId(), Duration.ofMinutes(90), LocalDateTime.of(2025, 7, 1, 12, 0)); + manager.addSubtask(subtask1); + manager.addSubtask(subtask2); + + manager.getTaskById(task.getId()); + manager.getEpicById(epic.getId()); + manager.getSubtaskById(subtask1.getId()); + + TaskManager loadedManager = FileBackedTaskManager.loadFromFile(file); + + Task loadedTask = loadedManager.getTaskById(task.getId()); + assertNotNull(loadedTask); + assertEquals(task.getTitle(), loadedTask.getTitle()); + assertEquals(task.getDuration(), loadedTask.getDuration()); + assertEquals(task.getStartTime(), loadedTask.getStartTime()); + + Epic loadedEpic = loadedManager.getEpicById(epic.getId()); + assertNotNull(loadedEpic); + assertEquals(epic.getTitle(), loadedEpic.getTitle()); + + List loadedSubtasks = loadedManager.getSubtasksOfEpic(epic.getId()); + assertEquals(2, loadedSubtasks.size()); + + Subtask loadedSubtask1 = loadedManager.getSubtaskById(subtask1.getId()); + assertEquals(subtask1.getDuration(), loadedSubtask1.getDuration()); + assertEquals(subtask1.getStartTime(), loadedSubtask1.getStartTime()); + + List history = loadedManager.getHistory(); + assertEquals(3, history.size()); + assertEquals(task.getId(), history.get(0).getId()); + assertEquals(epic.getId(), history.get(1).getId()); + assertEquals(subtask1.getId(), history.get(2).getId()); + } + + @Test + public void testLoadFromCorruptedFile() { + try { + java.nio.file.Files.writeString(file.toPath(), "Not a valid CSV content\n"); + } catch (Exception e) { + fail("Не удалось записать тестовый файл"); + } + + TaskManager loadedManager = FileBackedTaskManager.loadFromFile(file); + assertNotNull(loadedManager); + assertTrue(loadedManager.getAllTasks().isEmpty()); + assertTrue(loadedManager.getAllEpics().isEmpty()); + assertTrue(loadedManager.getAllSubtasks().isEmpty()); + assertTrue(loadedManager.getHistory().isEmpty()); + } + +} \ No newline at end of file diff --git a/test/manager/InMemoryHistoryManagerTest.java b/test/manager/InMemoryHistoryManagerTest.java index 92122b9..81f606f 100644 --- a/test/manager/InMemoryHistoryManagerTest.java +++ b/test/manager/InMemoryHistoryManagerTest.java @@ -1,18 +1,24 @@ package test.manager; -import manager.HistoryManager; + import manager.InMemoryHistoryManager; import model.Task; import model.Status; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.time.LocalDateTime; + import java.util.List; import static org.junit.jupiter.api.Assertions.*; class InMemoryHistoryManagerTest { - private HistoryManager historyManager; + + private InMemoryHistoryManager historyManager; + @BeforeEach void setUp() { @@ -20,47 +26,41 @@ void setUp() { } @Test - void addAndGetHistory() { - Task task1 = new Task("Task1", "Desc", Status.NEW); - task1.setId(1); - Task task2 = new Task("Task2", "Desc", Status.IN_PROGRESS); - task2.setId(2); - - historyManager.add(task1); - historyManager.add(task2); + void shouldAddAndReturnHistory() { + Task task = new Task("Test task", "Description", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + task.setId(1); + historyManager.add(task); List history = historyManager.getHistory(); - assertEquals(2, history.size()); - assertEquals(task1, history.get(0)); - assertEquals(task2, history.get(1)); + + assertEquals(1, history.size()); + assertEquals(task, history.get(0)); } @Test - void shouldRemoveDuplicates() { - Task task = new Task("Task", "Desc", Status.NEW); + void shouldNotAddDuplicates() { + Task task = new Task("Task", "Desc", Status.NEW, Duration.ofMinutes(20), LocalDateTime.now()); task.setId(1); - historyManager.add(task); historyManager.add(task); - List history = historyManager.getHistory(); - assertEquals(1, history.size()); + assertEquals(1, historyManager.getHistory().size()); } @Test - void shouldRemoveNodeFromMiddle() { - Task task1 = new Task("Task1", "Desc", Status.NEW); - Task task2 = new Task("Task2", "Desc", Status.NEW); - Task task3 = new Task("Task3", "Desc", Status.NEW); - task1.setId(1); task2.setId(2); task3.setId(3); + void shouldRemoveFromHistory() { + Task task1 = new Task("Task 1", "Desc 1", Status.NEW, Duration.ofMinutes(10), LocalDateTime.now()); + task1.setId(1); + Task task2 = new Task("Task 2", "Desc 2", Status.NEW, Duration.ofMinutes(10), LocalDateTime.now()); + task2.setId(2); historyManager.add(task1); historyManager.add(task2); - historyManager.add(task3); - historyManager.add(task2); // Дубликат + historyManager.remove(1); List history = historyManager.getHistory(); - assertEquals(3, history.size()); - assertEquals(List.of(task1, task3, task2), history); + assertEquals(1, history.size()); + assertEquals(task2, history.get(0)); } -} \ No newline at end of file +} + diff --git a/test/manager/InMemoryTaskManagerTest.java b/test/manager/InMemoryTaskManagerTest.java index 196ce8a..4e9a49a 100644 --- a/test/manager/InMemoryTaskManagerTest.java +++ b/test/manager/InMemoryTaskManagerTest.java @@ -8,6 +8,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.time.Duration; + import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -23,7 +25,8 @@ public void setUp() { @Test public void testAddAndGetTask() { - Task task = new Task("Task 1", "Description task 1", Status.NEW); + Task task = new Task("Task 1", "Description task 1", Status.NEW, Duration.ZERO, null); + manager.addTask(task); List tasks = manager.getAllTasks(); @@ -46,7 +49,8 @@ public void testAddAndGetSubtask() { Epic epic = new Epic("Epic 1", "Description epic 1"); manager.addEpic(epic); - Subtask subtask = new Subtask("Subtask 1", "Description subtask 1", Status.NEW, epic.getId()); + Subtask subtask = new Subtask("Subtask 1", "Description subtask 1", Status.NEW, epic.getId(), Duration.ZERO, null); + manager.addSubtask(subtask); List subtasks = manager.getAllSubtasks(); @@ -59,7 +63,8 @@ public void testAddAndGetSubtask() { @Test public void testRemoveTask() { - Task task = new Task("Task 1", "Description task 1", Status.NEW); + Task task = new Task("Task 1", "Description task 1", Status.NEW, Duration.ZERO, null); + manager.addTask(task); manager.removeTaskById(task.getId()); @@ -71,7 +76,8 @@ public void testRemoveEpicAlsoRemovesSubtasks() { Epic epic = new Epic("Epic 1", "Description epic 1"); manager.addEpic(epic); - Subtask subtask = new Subtask("Subtask 1", "Description subtask 1", Status.NEW, epic.getId()); + Subtask subtask = new Subtask("Subtask 1", "Description subtask 1", Status.NEW, epic.getId(), Duration.ZERO, null); + manager.addSubtask(subtask); manager.removeEpicById(epic.getId()); @@ -83,7 +89,8 @@ public void testRemoveEpicAlsoRemovesSubtasks() { @Test public void testUpdateTask() { - Task task = new Task("Task 1", "Description task 1", Status.NEW); + Task task = new Task("Task 1", "Description task 1", Status.NEW, Duration.ZERO, null); + manager.addTask(task); task.setStatus(Status.DONE); diff --git a/test/model/EpicTest.java b/test/model/EpicTest.java index 0455b5a..d183a63 100644 --- a/test/model/EpicTest.java +++ b/test/model/EpicTest.java @@ -6,50 +6,43 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.time.Duration; +import java.time.LocalDateTime; + import static org.junit.jupiter.api.Assertions.*; -class EpicTest { +public class EpicTest { + private Epic epic; - private Subtask subtask1; - private Subtask subtask2; + private Subtask s1; + private Subtask s2; @BeforeEach - void setUp() { + public void setUp() { epic = new Epic("Epic Title", "Epic Description"); - - subtask1 = new Subtask("Subtask 1", "Description 1", Status.NEW, epic.getId()); - subtask2 = new Subtask("Subtask 2", "Description 2", Status.NEW, epic.getId()); - - subtask1.setId(1); - subtask2.setId(2); } @Test - void epicIsCreatedWithEmptySubtaskList() { - assertNotNull(epic.getSubtaskIds()); - assertTrue(epic.getSubtaskIds().isEmpty()); - } + public void shouldReturnNewStatusIfAllSubtasksNew() { + Subtask s1 = new Subtask("Sub1", "Desc1", Status.NEW, epic.getId(), + Duration.ofMinutes(30), LocalDateTime.of(2025, 7, 1, 10, 0)); + Subtask s2 = new Subtask("Sub2", "Desc2", Status.NEW, epic.getId(), + Duration.ofMinutes(60), LocalDateTime.of(2025, 7, 1, 12, 0)); - @Test - void addSubtask_addsIdToList() { - epic.addSubtask(subtask1); - epic.addSubtask(subtask2); + epic.addSubtaskId(s1.getEpicId()); + epic.addSubtaskId(s2.getEpicId()); - assertEquals(2, epic.getSubtaskIds().size()); - assertTrue(epic.getSubtaskIds().contains(subtask1.getId())); - assertTrue(epic.getSubtaskIds().contains(subtask2.getId())); + assertEquals(Status.NEW, epic.getStatus()); } - @Test - void removeSubtask_removesCorrectId() { - epic.addSubtask(subtask1); - epic.addSubtask(subtask2); - epic.removeSubtask(subtask1.getId()); - assertEquals(1, epic.getSubtaskIds().size()); - assertFalse(epic.getSubtaskIds().contains(subtask1.getId())); - assertTrue(epic.getSubtaskIds().contains(subtask2.getId())); + + @Test + void epicIsCreatedWithEmptySubtaskList() { + assertNotNull(epic.getSubtaskIds()); + assertTrue(epic.getSubtaskIds().isEmpty()); } + } \ No newline at end of file diff --git a/test/model/SubtaskTest.java b/test/model/SubtaskTest.java new file mode 100644 index 0000000..e4fb140 --- /dev/null +++ b/test/model/SubtaskTest.java @@ -0,0 +1,47 @@ +package test.model; + +import model.Status; +import model.Subtask; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.*; + +class SubtaskTest { + + private Subtask subtask; + + @BeforeEach + void setUp() { + subtask = new Subtask("Subtask 1", "Subtask Description", Status.IN_PROGRESS, 10, Duration.ZERO, null); + subtask.setId(2); + subtask.setDuration(Duration.ofMinutes(45)); + subtask.setStartTime(LocalDateTime.of(2025, 7, 10, 11, 0)); + } + + @Test + void testGettersAndSetters() { + assertEquals(2, subtask.getId()); + assertEquals("Subtask 1", subtask.getTitle()); + assertEquals("Subtask Description", subtask.getDescription()); + assertEquals(Status.IN_PROGRESS, subtask.getStatus()); + assertEquals(10, subtask.getEpicId()); + assertEquals(Duration.ofMinutes(45), subtask.getDuration()); + assertEquals(LocalDateTime.of(2025, 7, 10, 11, 0), subtask.getStartTime()); + } + + @Test + void testGetEndTimeCalculation() { + LocalDateTime expectedEnd = subtask.getStartTime().plus(subtask.getDuration()); + assertEquals(expectedEnd, subtask.getEndTime()); + } + + @Test + void testToStringContainsEpicId() { + String toString = subtask.toString(); + assertTrue(toString.contains("epicId=10")); + } +} \ No newline at end of file diff --git a/test/model/TaskTest.java b/test/model/TaskTest.java index d6302bd..7b5d6e2 100644 --- a/test/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -5,91 +5,71 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.time.Duration; +import java.time.LocalDateTime; + import static org.junit.jupiter.api.Assertions.*; -class TaskTest { +public class TaskTest { + private Task task; @BeforeEach - void setUp() { - task = new Task("Test Task", "Test Description", Status.NEW); - task.setId(1); + public void setUp() { + task = new Task( + "Test Task", + "Description of test task", + Status.NEW, + Duration.ofMinutes(120), + LocalDateTime.of(2025, 7, 10, 9, 0) + ); } @Test - void testConstructorAndGetters() { - assertEquals(1, task.getId()); + public void shouldCreateTaskWithCorrectFields() { assertEquals("Test Task", task.getTitle()); - assertEquals("Test Description", task.getDescription()); + assertEquals("Description of test task", task.getDescription()); assertEquals(Status.NEW, task.getStatus()); + assertEquals(Duration.ofMinutes(120), task.getDuration()); + assertEquals(LocalDateTime.of(2025, 7, 10, 9, 0), task.getStartTime()); } @Test - void testSetters() { - task.setId(42); - task.setTitle("Updated Title"); - task.setDescription("Updated Description"); - task.setStatus(Status.IN_PROGRESS); - - assertEquals(42, task.getId()); - assertEquals("Updated Title", task.getTitle()); - assertEquals("Updated Description", task.getDescription()); - assertEquals(Status.IN_PROGRESS, task.getStatus()); - } - - @Test - void testEquals_sameValues_shouldBeEqual() { - Task other = new Task("Test Task", "Test Description", Status.NEW); - other.setId(1); - - assertEquals(task, other); - } - - @Test - void testEquals_differentId_shouldNotBeEqual() { - Task other = new Task("Test Task", "Test Description", Status.NEW); - other.setId(99); - - assertNotEquals(task, other); + public void shouldCalculateEndTimeCorrectly() { + LocalDateTime expectedEndTime = LocalDateTime.of(2025, 7, 10, 11, 0); + assertEquals(expectedEndTime, task.getEndTime()); } @Test - void testEquals_differentTitle_shouldNotBeEqual() { - Task other = new Task("Different Title", "Test Description", Status.NEW); - other.setId(1); - - assertNotEquals(task, other); + public void shouldUpdateStatus() { + task.setStatus(Status.IN_PROGRESS); + assertEquals(Status.IN_PROGRESS, task.getStatus()); } @Test - void testEquals_differentDescription_shouldNotBeEqual() { - Task other = new Task("Test Task", "Other Description", Status.NEW); - other.setId(1); + public void shouldUpdateStartTimeAndDuration() { + task.setStartTime(LocalDateTime.of(2025, 7, 10, 10, 0)); + task.setDuration(Duration.ofMinutes(30)); - assertNotEquals(task, other); + assertEquals(LocalDateTime.of(2025, 7, 10, 10, 0), task.getStartTime()); + assertEquals(Duration.ofMinutes(30), task.getDuration()); + assertEquals(LocalDateTime.of(2025, 7, 10, 10, 30), task.getEndTime()); } @Test - void testEquals_differentStatus_shouldNotBeEqual() { - Task other = new Task("Test Task", "Test Description", Status.DONE); - other.setId(1); + public void toStringShouldContainAllFields() { + String str = task.toString(); - assertNotEquals(task, other); - } + assertNotNull(str); + assertFalse(str.isEmpty()); - @Test - void testHashCode_sameValues_shouldBeEqual() { - Task other = new Task("Test Task", "Test Description", Status.NEW); - other.setId(1); + assertTrue(str.contains(task.getTitle())); + assertTrue(str.contains(task.getDescription())); + assertTrue(str.contains(task.getStatus().toString())); - assertEquals(task.hashCode(), other.hashCode()); - } + assertTrue(str.contains(String.valueOf(task.getDuration().toMinutes()))); - @Test - void testHashCode_differentValues_shouldNotBeEqual() { - Task other = new Task("Other", "Other", Status.DONE); - other.setId(999); + assertTrue(str.contains(task.getStartTime().toString())); - assertNotEquals(task.hashCode(), other.hashCode()); } } \ No newline at end of file From c52f3e8ee1907c223dbcc99365f63e8322b55ce4 Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Tue, 29 Jul 2025 07:24:31 +0300 Subject: [PATCH 3/9] Add files via upload --- src/manager/BaseHttpHandler.java | 32 +++++++++ src/manager/DurationAdapter.java | 18 ++++++ src/manager/EpicsHandler.java | 59 +++++++++++++++++ src/manager/HistoryHandler.java | 32 +++++++++ src/manager/HttpTaskServer.java | 53 +++++++++++++++ src/manager/LocalDateTimeAdapter.java | 20 ++++++ src/manager/PrioritizedHandler.java | 33 ++++++++++ src/manager/SubtasksHandler.java | 76 ++++++++++++++++++++++ src/manager/TaskNotFoundException.java | 8 +++ src/manager/TaskOverlapException.java | 8 +++ src/manager/TasksHandler.java | 90 ++++++++++++++++++++++++++ 11 files changed, 429 insertions(+) create mode 100644 src/manager/BaseHttpHandler.java create mode 100644 src/manager/DurationAdapter.java create mode 100644 src/manager/EpicsHandler.java create mode 100644 src/manager/HistoryHandler.java create mode 100644 src/manager/HttpTaskServer.java create mode 100644 src/manager/LocalDateTimeAdapter.java create mode 100644 src/manager/PrioritizedHandler.java create mode 100644 src/manager/SubtasksHandler.java create mode 100644 src/manager/TaskNotFoundException.java create mode 100644 src/manager/TaskOverlapException.java create mode 100644 src/manager/TasksHandler.java diff --git a/src/manager/BaseHttpHandler.java b/src/manager/BaseHttpHandler.java new file mode 100644 index 0000000..990188e --- /dev/null +++ b/src/manager/BaseHttpHandler.java @@ -0,0 +1,32 @@ +package manager; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public abstract class BaseHttpHandler implements HttpHandler { + + protected void sendText(HttpExchange exchange, String text, int code) throws IOException { + byte[] resp = text.getBytes(StandardCharsets.UTF_8); + exchange.getResponseHeaders().add("Content-Type", "application/json; charset=utf-8"); + exchange.sendResponseHeaders(code, resp.length); + exchange.getResponseBody().write(resp); + exchange.close(); + } + + protected void sendNotFound(HttpExchange exchange) throws IOException { + String response = "{\"error\":\"Not Found\"}"; + sendText(exchange, response, 404); + } + + protected void sendHasOverlaps(HttpExchange exchange) throws IOException { + String response = "{\"error\":\"Task time overlap detected\"}"; + sendText(exchange, response, 406); + } + + protected void sendInternalError(HttpExchange exchange) throws IOException { + String response = "{\"error\":\"Internal Server Error\"}"; + sendText(exchange, response, 500); + } +} diff --git a/src/manager/DurationAdapter.java b/src/manager/DurationAdapter.java new file mode 100644 index 0000000..e3dc9bf --- /dev/null +++ b/src/manager/DurationAdapter.java @@ -0,0 +1,18 @@ +package manager; + +import com.google.gson.*; +import java.lang.reflect.Type; +import java.time.Duration; + +public class DurationAdapter implements JsonSerializer, JsonDeserializer { + @Override + public JsonElement serialize(Duration src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.toMillis()); + } + + @Override + public Duration deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + return Duration.ofMillis(json.getAsLong()); + } +} + diff --git a/src/manager/EpicsHandler.java b/src/manager/EpicsHandler.java new file mode 100644 index 0000000..4dfce10 --- /dev/null +++ b/src/manager/EpicsHandler.java @@ -0,0 +1,59 @@ +package manager; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import model.Epic; + +import java.io.IOException; +import java.util.List; + +public class EpicsHandler extends BaseHttpHandler { + + private final TaskManager manager; + private final Gson gson = HttpTaskServer.getGson(); + + public EpicsHandler(TaskManager manager) { + this.manager = manager; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + String method = exchange.getRequestMethod(); + String query = exchange.getRequestURI().getQuery(); + + if ("GET".equalsIgnoreCase(method)) { + if (query == null) { + List epics = manager.getAllEpics(); + sendText(exchange, gson.toJson(epics), 200); + } else if (query.startsWith("id=")) { + int id = Integer.parseInt(query.split("=")[1]); + Epic epic = manager.getEpicById(id); + if (epic == null) { + sendNotFound(exchange); + return; + } + sendText(exchange, gson.toJson(epic), 200); + } + } else if ("DELETE".equalsIgnoreCase(method)) { + if (query == null) { + manager.clearEpics(); + sendText(exchange, "{\"status\":\"all epics deleted\"}", 200); + } else if (query.startsWith("id=")) { + int id = Integer.parseInt(query.split("=")[1]); + try { + manager.removeEpicById(id); + sendText(exchange, "{\"status\":\"epic deleted\"}", 200); + } catch (TaskNotFoundException e) { + sendNotFound(exchange); + } + } + } else { + sendNotFound(exchange); + } + } catch (Exception e) { + e.printStackTrace(); + sendInternalError(exchange); + } + } +} diff --git a/src/manager/HistoryHandler.java b/src/manager/HistoryHandler.java new file mode 100644 index 0000000..5c9e8d4 --- /dev/null +++ b/src/manager/HistoryHandler.java @@ -0,0 +1,32 @@ +package manager; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import model.Task; + +import java.io.IOException; +import java.util.List; + +public class HistoryHandler extends BaseHttpHandler { + + private final TaskManager manager; + private final Gson gson = HttpTaskServer.getGson(); + + public HistoryHandler(TaskManager manager) { + this.manager = manager; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + if ("GET".equalsIgnoreCase(exchange.getRequestMethod())) { + List history = manager.getHistory(); + sendText(exchange, gson.toJson(history), 200); + } else { + sendNotFound(exchange); + } + } catch (Exception e) { + sendInternalError(exchange); + } + } +} diff --git a/src/manager/HttpTaskServer.java b/src/manager/HttpTaskServer.java new file mode 100644 index 0000000..ce93bea --- /dev/null +++ b/src/manager/HttpTaskServer.java @@ -0,0 +1,53 @@ +package manager; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.sun.net.httpserver.HttpServer; +import manager.TaskManager; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.time.Duration; +import java.time.LocalDateTime; + +public class HttpTaskServer { + + private static final int PORT = 8080; + private final HttpServer server; + private final TaskManager manager; + private static final Gson gson = new GsonBuilder() + .registerTypeAdapter(Duration.class, new DurationAdapter()) + .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()) + .create(); + + public HttpTaskServer(TaskManager manager) throws IOException { + this.manager = manager; + this.server = HttpServer.create(new InetSocketAddress(PORT), 0); + + server.createContext("/tasks", new TasksHandler(manager)); + server.createContext("/subtasks", new SubtasksHandler(manager)); + server.createContext("/epics", new EpicsHandler(manager)); + server.createContext("/history", new HistoryHandler(manager)); + server.createContext("/prioritized", new PrioritizedHandler(manager)); + } + + public void start() { + server.start(); + System.out.println("HTTP-сервер запущен на порту " + PORT); + } + + public void stop() { + server.stop(0); + System.out.println("HTTP-сервер остановлен"); + } + + public static Gson getGson() { + return gson; + } + + public static void main(String[] args) throws IOException { + TaskManager manager = Managers.getDefault(); + HttpTaskServer taskServer = new HttpTaskServer(manager); + taskServer.start(); + } +} diff --git a/src/manager/LocalDateTimeAdapter.java b/src/manager/LocalDateTimeAdapter.java new file mode 100644 index 0000000..de43b0d --- /dev/null +++ b/src/manager/LocalDateTimeAdapter.java @@ -0,0 +1,20 @@ +package manager; +import com.google.gson.*; +import java.lang.reflect.Type; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class LocalDateTimeAdapter implements JsonSerializer, JsonDeserializer { + private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; + + @Override + public JsonElement serialize(LocalDateTime src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.format(formatter)); + } + + @Override + public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + return LocalDateTime.parse(json.getAsString(), formatter); + } +} + diff --git a/src/manager/PrioritizedHandler.java b/src/manager/PrioritizedHandler.java new file mode 100644 index 0000000..69014e3 --- /dev/null +++ b/src/manager/PrioritizedHandler.java @@ -0,0 +1,33 @@ +package manager; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import model.Task; + +import java.io.IOException; +import java.util.List; + +public class PrioritizedHandler extends BaseHttpHandler { + + private final TaskManager manager; + private final Gson gson = HttpTaskServer.getGson(); + + public PrioritizedHandler(TaskManager manager) { + this.manager = manager; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + if ("GET".equalsIgnoreCase(exchange.getRequestMethod())) { + List prioritized = manager.getPrioritizedTasks(); + sendText(exchange, gson.toJson(prioritized), 200); + } else { + sendNotFound(exchange); + } + } catch (Exception e) { + sendInternalError(exchange); + } + } +} + diff --git a/src/manager/SubtasksHandler.java b/src/manager/SubtasksHandler.java new file mode 100644 index 0000000..48ca284 --- /dev/null +++ b/src/manager/SubtasksHandler.java @@ -0,0 +1,76 @@ +package manager; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import model.Subtask; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.List; + +public class SubtasksHandler extends BaseHttpHandler { + + private final TaskManager manager; + private final Gson gson = HttpTaskServer.getGson(); + + public SubtasksHandler(TaskManager manager) { + this.manager = manager; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + String method = exchange.getRequestMethod(); + String query = exchange.getRequestURI().getQuery(); + + if ("GET".equalsIgnoreCase(method)) { + if (query == null) { + List subtasks = manager.getAllSubtasks(); + sendText(exchange, gson.toJson(subtasks), 200); + } else if (query.startsWith("id=")) { + int id = Integer.parseInt(query.split("=")[1]); + Subtask subtask = manager.getSubtaskById(id); + if (subtask == null) { + sendNotFound(exchange); + return; + } + sendText(exchange, gson.toJson(subtask), 200); + } + } else if ("POST".equalsIgnoreCase(method)) { + InputStreamReader isr = new InputStreamReader(exchange.getRequestBody(), StandardCharsets.UTF_8); + Subtask subtask = gson.fromJson(isr, Subtask.class); + isr.close(); + + try { + if (subtask.getId() == 0) { + manager.addSubtask(subtask); + } else { + manager.updateSubtask(subtask); + } + sendText(exchange, "{\"status\":\"ok\"}", 201); + } catch (TaskOverlapException e) { + sendHasOverlaps(exchange); + } + } else if ("DELETE".equalsIgnoreCase(method)) { + if (query == null) { + manager.clearSubtasks(); + sendText(exchange, "{\"status\":\"all subtasks deleted\"}", 200); + } else if (query.startsWith("id=")) { + int id = Integer.parseInt(query.split("=")[1]); + try { + manager.removeSubtaskById(id); + sendText(exchange, "{\"status\":\"subtask deleted\"}", 200); + } catch (TaskNotFoundException e) { + sendNotFound(exchange); + } + } + } else { + sendNotFound(exchange); + } + } catch (Exception e) { + e.printStackTrace(); + sendInternalError(exchange); + } + } +} diff --git a/src/manager/TaskNotFoundException.java b/src/manager/TaskNotFoundException.java new file mode 100644 index 0000000..e21fe90 --- /dev/null +++ b/src/manager/TaskNotFoundException.java @@ -0,0 +1,8 @@ +package manager; + +public class TaskNotFoundException extends RuntimeException { + public TaskNotFoundException(String msg) { + super(msg); + } +} + diff --git a/src/manager/TaskOverlapException.java b/src/manager/TaskOverlapException.java new file mode 100644 index 0000000..7237a00 --- /dev/null +++ b/src/manager/TaskOverlapException.java @@ -0,0 +1,8 @@ +package manager; + +public class TaskOverlapException extends RuntimeException { + public TaskOverlapException(String msg) { + super(msg); + } +} + diff --git a/src/manager/TasksHandler.java b/src/manager/TasksHandler.java new file mode 100644 index 0000000..7134c76 --- /dev/null +++ b/src/manager/TasksHandler.java @@ -0,0 +1,90 @@ +package manager; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import manager.TaskManager; +import model.Task; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.List; + +public class TasksHandler extends BaseHttpHandler { + + private final TaskManager manager; + private final Gson gson = HttpTaskServer.getGson(); + + public TasksHandler(TaskManager manager) { + this.manager = manager; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + String method = exchange.getRequestMethod(); + String path = exchange.getRequestURI().getPath(); + String query = exchange.getRequestURI().getQuery(); + + if ("GET".equalsIgnoreCase(method)) { + if (query == null) { + List tasks = manager.getAllTasks(); + String json = gson.toJson(tasks); + sendText(exchange, json, 200); + } else { + String[] parts = query.split("="); + if (parts.length == 2 && "id".equals(parts[0])) { + int id = Integer.parseInt(parts[1]); + Task task = manager.getTaskById(id); + if (task == null) { + sendNotFound(exchange); + return; + } + String json = gson.toJson(task); + sendText(exchange, json, 200); + } else { + sendNotFound(exchange); + } + } + } else if ("POST".equalsIgnoreCase(method)) { + InputStreamReader isr = new InputStreamReader(exchange.getRequestBody(), StandardCharsets.UTF_8); + Task task = gson.fromJson(isr, Task.class); + isr.close(); + + try { + if (task.getId() == 0) { + manager.addTask(task); + } else { + manager.updateTask(task); + } + sendText(exchange, "{\"status\":\"ok\"}", 201); + } catch (TaskOverlapException e) { + sendHasOverlaps(exchange); + } + } else if ("DELETE".equalsIgnoreCase(method)) { + if (query == null) { + manager.clearTasks(); + sendText(exchange, "{\"status\":\"all tasks deleted\"}", 200); + } else { + String[] parts = query.split("="); + if (parts.length == 2 && "id".equals(parts[0])) { + int id = Integer.parseInt(parts[1]); + try { + manager.removeTaskById(id); + sendText(exchange, "{\"status\":\"task deleted\"}", 200); + } catch (TaskNotFoundException e) { + sendNotFound(exchange); + } + } else { + sendNotFound(exchange); + } + } + } else { + sendNotFound(exchange); + } + } catch (Exception e) { + e.printStackTrace(); + sendInternalError(exchange); + } + } +} From 4961a8c3f18eafffbb179ce341af47e4369e5c5b Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Tue, 29 Jul 2025 07:25:35 +0300 Subject: [PATCH 4/9] Add files via upload --- test/manager/HttpTaskServerTasksTest.java | 57 +++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 test/manager/HttpTaskServerTasksTest.java diff --git a/test/manager/HttpTaskServerTasksTest.java b/test/manager/HttpTaskServerTasksTest.java new file mode 100644 index 0000000..77fb712 --- /dev/null +++ b/test/manager/HttpTaskServerTasksTest.java @@ -0,0 +1,57 @@ +package test.manager; + +import com.google.gson.Gson; +import model.Status; +import model.Task; +import org.junit.jupiter.api.*; +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; +import manager.TaskManager; +import manager.*; + +import static org.junit.jupiter.api.Assertions.*; + +public class HttpTaskServerTasksTest { + + private TaskManager manager; + private HttpTaskServer server; + private final HttpClient client = HttpClient.newHttpClient(); + private final Gson gson = HttpTaskServer.getGson(); + + @BeforeEach + public void setUp() throws IOException { + manager = new InMemoryTaskManager(); + server = new HttpTaskServer(manager); + server.start(); + } + + @AfterEach + public void tearDown() { + server.stop(); + } + + @Test + public void testAddTask() throws IOException, InterruptedException { + Task task = new Task("Test", "Check HTTP", Status.NEW, + Duration.ofMinutes(30), LocalDateTime.now()); + + String json = gson.toJson(task); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:8080/tasks")) + .POST(HttpRequest.BodyPublishers.ofString(json)) + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + assertEquals(201, response.statusCode(), "Должен вернуться код 201"); + List tasks = manager.getAllTasks(); + assertEquals(1, tasks.size()); + assertEquals("Test", tasks.get(0).getTitle()); + } +} From ce69591f6e54cf14389443092e693d836eedced6 Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Wed, 30 Jul 2025 06:21:03 +0300 Subject: [PATCH 5/9] Add files via upload --- src/manager/BaseHttpHandler.java | 43 +++++++++++----- src/manager/EpicsHandler.java | 60 ++++++++++------------ src/manager/HistoryHandler.java | 16 +++--- src/manager/PrioritizedHandler.java | 17 +++--- src/manager/SubtasksHandler.java | 80 +++++++++++++---------------- src/manager/TasksHandler.java | 80 +++++++++-------------------- 6 files changed, 129 insertions(+), 167 deletions(-) diff --git a/src/manager/BaseHttpHandler.java b/src/manager/BaseHttpHandler.java index 990188e..97be981 100644 --- a/src/manager/BaseHttpHandler.java +++ b/src/manager/BaseHttpHandler.java @@ -1,32 +1,47 @@ package manager; + import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; import java.io.IOException; +import java.io.OutputStream; import java.nio.charset.StandardCharsets; -public abstract class BaseHttpHandler implements HttpHandler { +public class BaseHttpHandler { protected void sendText(HttpExchange exchange, String text, int code) throws IOException { byte[] resp = text.getBytes(StandardCharsets.UTF_8); - exchange.getResponseHeaders().add("Content-Type", "application/json; charset=utf-8"); + exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); exchange.sendResponseHeaders(code, resp.length); - exchange.getResponseBody().write(resp); - exchange.close(); + try (OutputStream os = exchange.getResponseBody()) { + os.write(resp); + } finally { + exchange.close(); + } + } + + protected void sendNotFound(HttpExchange exchange) { + sendStatus(exchange, 404, "Not Found"); } - protected void sendNotFound(HttpExchange exchange) throws IOException { - String response = "{\"error\":\"Not Found\"}"; - sendText(exchange, response, 404); + protected void sendHasOverlaps(HttpExchange exchange) { + sendStatus(exchange, 406, "Task time overlaps with existing task"); } - protected void sendHasOverlaps(HttpExchange exchange) throws IOException { - String response = "{\"error\":\"Task time overlap detected\"}"; - sendText(exchange, response, 406); + protected void sendInternalError(HttpExchange exchange) { + sendStatus(exchange, 500, "Internal Server Error"); } - protected void sendInternalError(HttpExchange exchange) throws IOException { - String response = "{\"error\":\"Internal Server Error\"}"; - sendText(exchange, response, 500); + private void sendStatus(HttpExchange exchange, int code, String message) { + try { + byte[] resp = message.getBytes(StandardCharsets.UTF_8); + exchange.sendResponseHeaders(code, resp.length); + try (OutputStream os = exchange.getResponseBody()) { + os.write(resp); + } + } catch (IOException e) { + System.err.println("Ошибка при отправке ответа: " + e.getMessage()); + } finally { + exchange.close(); + } } } diff --git a/src/manager/EpicsHandler.java b/src/manager/EpicsHandler.java index 4dfce10..8652633 100644 --- a/src/manager/EpicsHandler.java +++ b/src/manager/EpicsHandler.java @@ -2,13 +2,12 @@ import com.google.gson.Gson; import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; import model.Epic; - -import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.List; -public class EpicsHandler extends BaseHttpHandler { - +public class EpicsHandler extends BaseHttpHandler implements HttpHandler { private final TaskManager manager; private final Gson gson = HttpTaskServer.getGson(); @@ -17,42 +16,37 @@ public EpicsHandler(TaskManager manager) { } @Override - public void handle(HttpExchange exchange) throws IOException { + public void handle(HttpExchange exchange) { try { String method = exchange.getRequestMethod(); - String query = exchange.getRequestURI().getQuery(); + switch (method) { + case "GET" -> sendText(exchange, gson.toJson(manager.getAllEpics()), 200); + case "POST" -> { + String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + Epic epic = gson.fromJson(body, Epic.class); - if ("GET".equalsIgnoreCase(method)) { - if (query == null) { - List epics = manager.getAllEpics(); - sendText(exchange, gson.toJson(epics), 200); - } else if (query.startsWith("id=")) { - int id = Integer.parseInt(query.split("=")[1]); - Epic epic = manager.getEpicById(id); - if (epic == null) { - sendNotFound(exchange); - return; - } - sendText(exchange, gson.toJson(epic), 200); + if (epic.getId() == 0) { + manager.addEpic(epic); + sendText(exchange, "{\"id\":" + epic.getId() + "}", 201); + } else if (manager.getEpicById(epic.getId()) != null) { + manager.updateEpic(epic); + sendText(exchange, gson.toJson(epic), 201); + } else sendNotFound(exchange); } - } else if ("DELETE".equalsIgnoreCase(method)) { - if (query == null) { - manager.clearEpics(); - sendText(exchange, "{\"status\":\"all epics deleted\"}", 200); - } else if (query.startsWith("id=")) { - int id = Integer.parseInt(query.split("=")[1]); - try { - manager.removeEpicById(id); - sendText(exchange, "{\"status\":\"epic deleted\"}", 200); - } catch (TaskNotFoundException e) { - sendNotFound(exchange); - } + case "DELETE" -> { + String query = exchange.getRequestURI().getQuery(); + if (query != null && query.startsWith("id=")) { + int id = Integer.parseInt(query.substring(3)); + if (manager.getEpicById(id) != null) { + manager.removeEpicById(id); + sendText(exchange, "{\"status\":\"deleted\"}", 201); + } else sendNotFound(exchange); + } else sendNotFound(exchange); } - } else { - sendNotFound(exchange); + default -> sendNotFound(exchange); } } catch (Exception e) { - e.printStackTrace(); + System.err.println("Ошибка EpicsHandler: " + e.getMessage()); sendInternalError(exchange); } } diff --git a/src/manager/HistoryHandler.java b/src/manager/HistoryHandler.java index 5c9e8d4..1218e42 100644 --- a/src/manager/HistoryHandler.java +++ b/src/manager/HistoryHandler.java @@ -2,13 +2,9 @@ import com.google.gson.Gson; import com.sun.net.httpserver.HttpExchange; -import model.Task; - -import java.io.IOException; -import java.util.List; - -public class HistoryHandler extends BaseHttpHandler { +import com.sun.net.httpserver.HttpHandler; +public class HistoryHandler extends BaseHttpHandler implements HttpHandler { private final TaskManager manager; private final Gson gson = HttpTaskServer.getGson(); @@ -17,15 +13,15 @@ public HistoryHandler(TaskManager manager) { } @Override - public void handle(HttpExchange exchange) throws IOException { + public void handle(HttpExchange exchange) { try { - if ("GET".equalsIgnoreCase(exchange.getRequestMethod())) { - List history = manager.getHistory(); - sendText(exchange, gson.toJson(history), 200); + if ("GET".equals(exchange.getRequestMethod())) { + sendText(exchange, gson.toJson(manager.getHistory()), 200); } else { sendNotFound(exchange); } } catch (Exception e) { + System.err.println("Ошибка HistoryHandler: " + e.getMessage()); sendInternalError(exchange); } } diff --git a/src/manager/PrioritizedHandler.java b/src/manager/PrioritizedHandler.java index 69014e3..1c8c7d3 100644 --- a/src/manager/PrioritizedHandler.java +++ b/src/manager/PrioritizedHandler.java @@ -2,13 +2,9 @@ import com.google.gson.Gson; import com.sun.net.httpserver.HttpExchange; -import model.Task; - -import java.io.IOException; -import java.util.List; - -public class PrioritizedHandler extends BaseHttpHandler { +import com.sun.net.httpserver.HttpHandler; +public class PrioritizedHandler extends BaseHttpHandler implements HttpHandler { private final TaskManager manager; private final Gson gson = HttpTaskServer.getGson(); @@ -17,17 +13,16 @@ public PrioritizedHandler(TaskManager manager) { } @Override - public void handle(HttpExchange exchange) throws IOException { + public void handle(HttpExchange exchange) { try { - if ("GET".equalsIgnoreCase(exchange.getRequestMethod())) { - List prioritized = manager.getPrioritizedTasks(); - sendText(exchange, gson.toJson(prioritized), 200); + if ("GET".equals(exchange.getRequestMethod())) { + sendText(exchange, gson.toJson(manager.getPrioritizedTasks()), 200); } else { sendNotFound(exchange); } } catch (Exception e) { + System.err.println("Ошибка PrioritizedHandler: " + e.getMessage()); sendInternalError(exchange); } } } - diff --git a/src/manager/SubtasksHandler.java b/src/manager/SubtasksHandler.java index 48ca284..f4d174d 100644 --- a/src/manager/SubtasksHandler.java +++ b/src/manager/SubtasksHandler.java @@ -2,15 +2,12 @@ import com.google.gson.Gson; import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; import model.Subtask; -import java.io.IOException; -import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import java.util.List; - -public class SubtasksHandler extends BaseHttpHandler { +public class SubtasksHandler extends BaseHttpHandler implements HttpHandler { private final TaskManager manager; private final Gson gson = HttpTaskServer.getGson(); @@ -19,57 +16,52 @@ public SubtasksHandler(TaskManager manager) { } @Override - public void handle(HttpExchange exchange) throws IOException { + public void handle(HttpExchange exchange) { try { String method = exchange.getRequestMethod(); - String query = exchange.getRequestURI().getQuery(); + switch (method) { + case "GET" -> sendText(exchange, gson.toJson(manager.getAllSubtasks()), 200); - if ("GET".equalsIgnoreCase(method)) { - if (query == null) { - List subtasks = manager.getAllSubtasks(); - sendText(exchange, gson.toJson(subtasks), 200); - } else if (query.startsWith("id=")) { - int id = Integer.parseInt(query.split("=")[1]); - Subtask subtask = manager.getSubtaskById(id); - if (subtask == null) { - sendNotFound(exchange); - return; - } - sendText(exchange, gson.toJson(subtask), 200); - } - } else if ("POST".equalsIgnoreCase(method)) { - InputStreamReader isr = new InputStreamReader(exchange.getRequestBody(), StandardCharsets.UTF_8); - Subtask subtask = gson.fromJson(isr, Subtask.class); - isr.close(); + case "POST" -> { + String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + Subtask subtask = gson.fromJson(body, Subtask.class); - try { if (subtask.getId() == 0) { + if (manager.getEpicById(subtask.getEpicId()) == null) { + sendNotFound(exchange); + return; + } manager.addSubtask(subtask); + sendText(exchange, "{\"id\":" + subtask.getId() + "}", 201); + } else { - manager.updateSubtask(subtask); + Subtask old = manager.getSubtaskById(subtask.getId()); + if (old == null) { + sendNotFound(exchange); + } else if (old.getEpicId() != subtask.getEpicId()) { + sendHasOverlaps(exchange); + } else { + manager.updateSubtask(subtask); + sendText(exchange, gson.toJson(subtask), 201); + } } - sendText(exchange, "{\"status\":\"ok\"}", 201); - } catch (TaskOverlapException e) { - sendHasOverlaps(exchange); } - } else if ("DELETE".equalsIgnoreCase(method)) { - if (query == null) { - manager.clearSubtasks(); - sendText(exchange, "{\"status\":\"all subtasks deleted\"}", 200); - } else if (query.startsWith("id=")) { - int id = Integer.parseInt(query.split("=")[1]); - try { - manager.removeSubtaskById(id); - sendText(exchange, "{\"status\":\"subtask deleted\"}", 200); - } catch (TaskNotFoundException e) { - sendNotFound(exchange); - } + + case "DELETE" -> { + String query = exchange.getRequestURI().getQuery(); + if (query != null && query.startsWith("id=")) { + int id = Integer.parseInt(query.substring(3)); + if (manager.getSubtaskById(id) != null) { + manager.removeSubtaskById(id); + sendText(exchange, "{\"status\":\"deleted\"}", 201); + } else sendNotFound(exchange); + } else sendNotFound(exchange); } - } else { - sendNotFound(exchange); + + default -> sendNotFound(exchange); } } catch (Exception e) { - e.printStackTrace(); + System.err.println("Ошибка SubtasksHandler: " + e.getMessage()); sendInternalError(exchange); } } diff --git a/src/manager/TasksHandler.java b/src/manager/TasksHandler.java index 7134c76..0c32b5b 100644 --- a/src/manager/TasksHandler.java +++ b/src/manager/TasksHandler.java @@ -2,16 +2,14 @@ import com.google.gson.Gson; import com.sun.net.httpserver.HttpExchange; -import manager.TaskManager; +import com.sun.net.httpserver.HttpHandler; import model.Task; - import java.io.IOException; -import java.io.InputStreamReader; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.List; -public class TasksHandler extends BaseHttpHandler { - +public class TasksHandler extends BaseHttpHandler implements HttpHandler { private final TaskManager manager; private final Gson gson = HttpTaskServer.getGson(); @@ -20,70 +18,42 @@ public TasksHandler(TaskManager manager) { } @Override - public void handle(HttpExchange exchange) throws IOException { + public void handle(HttpExchange exchange) { try { String method = exchange.getRequestMethod(); - String path = exchange.getRequestURI().getPath(); - String query = exchange.getRequestURI().getQuery(); - - if ("GET".equalsIgnoreCase(method)) { - if (query == null) { + switch (method) { + case "GET" -> { List tasks = manager.getAllTasks(); - String json = gson.toJson(tasks); - sendText(exchange, json, 200); - } else { - String[] parts = query.split("="); - if (parts.length == 2 && "id".equals(parts[0])) { - int id = Integer.parseInt(parts[1]); - Task task = manager.getTaskById(id); - if (task == null) { - sendNotFound(exchange); - return; - } - String json = gson.toJson(task); - sendText(exchange, json, 200); - } else { - sendNotFound(exchange); - } + sendText(exchange, gson.toJson(tasks), 200); } - } else if ("POST".equalsIgnoreCase(method)) { - InputStreamReader isr = new InputStreamReader(exchange.getRequestBody(), StandardCharsets.UTF_8); - Task task = gson.fromJson(isr, Task.class); - isr.close(); + case "POST" -> { + String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + Task task = gson.fromJson(body, Task.class); - try { if (task.getId() == 0) { manager.addTask(task); - } else { + sendText(exchange, "{\"id\":" + task.getId() + "}", 201); + } else if (manager.getTaskById(task.getId()) != null) { manager.updateTask(task); - } - sendText(exchange, "{\"status\":\"ok\"}", 201); - } catch (TaskOverlapException e) { - sendHasOverlaps(exchange); - } - } else if ("DELETE".equalsIgnoreCase(method)) { - if (query == null) { - manager.clearTasks(); - sendText(exchange, "{\"status\":\"all tasks deleted\"}", 200); - } else { - String[] parts = query.split("="); - if (parts.length == 2 && "id".equals(parts[0])) { - int id = Integer.parseInt(parts[1]); - try { - manager.removeTaskById(id); - sendText(exchange, "{\"status\":\"task deleted\"}", 200); - } catch (TaskNotFoundException e) { - sendNotFound(exchange); - } + sendText(exchange, gson.toJson(task), 201); } else { sendNotFound(exchange); } } - } else { - sendNotFound(exchange); + case "DELETE" -> { + String query = exchange.getRequestURI().getQuery(); + if (query != null && query.startsWith("id=")) { + int id = Integer.parseInt(query.substring(3)); + if (manager.getTaskById(id) != null) { + manager.removeTaskById(id); + sendText(exchange, "{\"status\":\"deleted\"}", 201); + } else sendNotFound(exchange); + } else sendNotFound(exchange); + } + default -> sendNotFound(exchange); } } catch (Exception e) { - e.printStackTrace(); + System.err.println("Ошибка TasksHandler: " + e.getMessage()); sendInternalError(exchange); } } From ff03b646ed49d53f6bc43a76745b66c9b69614ea Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Wed, 30 Jul 2025 06:23:03 +0300 Subject: [PATCH 6/9] Update TasksHandler.java --- src/manager/TasksHandler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/manager/TasksHandler.java b/src/manager/TasksHandler.java index 0c32b5b..23c8f8b 100644 --- a/src/manager/TasksHandler.java +++ b/src/manager/TasksHandler.java @@ -4,8 +4,6 @@ import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import model.Task; -import java.io.IOException; -import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.List; From f7eb315933f384ce29625e73d61f13da53397153 Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Wed, 30 Jul 2025 06:25:02 +0300 Subject: [PATCH 7/9] Update EpicsHandler.java --- src/manager/EpicsHandler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/manager/EpicsHandler.java b/src/manager/EpicsHandler.java index 8652633..fde01c4 100644 --- a/src/manager/EpicsHandler.java +++ b/src/manager/EpicsHandler.java @@ -5,7 +5,6 @@ import com.sun.net.httpserver.HttpHandler; import model.Epic; import java.nio.charset.StandardCharsets; -import java.util.List; public class EpicsHandler extends BaseHttpHandler implements HttpHandler { private final TaskManager manager; From 1970b442187e5e6aae998d5a59a1dc1b39625772 Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Thu, 31 Jul 2025 09:27:59 +0300 Subject: [PATCH 8/9] Add files via upload --- src/manager/BaseHttpHandler.java | 7 +- src/manager/EpicsHandler.java | 101 ++++++++++++++++++++++------- src/manager/SubtasksHandler.java | 106 +++++++++++++++++++++---------- src/manager/TasksHandler.java | 98 +++++++++++++++++++--------- 4 files changed, 224 insertions(+), 88 deletions(-) diff --git a/src/manager/BaseHttpHandler.java b/src/manager/BaseHttpHandler.java index ec309b8..de0cb7b 100644 --- a/src/manager/BaseHttpHandler.java +++ b/src/manager/BaseHttpHandler.java @@ -45,5 +45,10 @@ private void sendStatus(HttpExchange exchange, int code, String message) { } } - + protected void sendError(HttpExchange exchange, int statusCode, String message) { + try { + String json = "{\"error\":\"" + message + "\"}"; + sendText(exchange, json, statusCode); + } catch (IOException ignored) {} + } } diff --git a/src/manager/EpicsHandler.java b/src/manager/EpicsHandler.java index 5123c5f..7b91737 100644 --- a/src/manager/EpicsHandler.java +++ b/src/manager/EpicsHandler.java @@ -4,8 +4,9 @@ import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import model.Epic; +import model.Subtask; import java.nio.charset.StandardCharsets; - +import java.util.List; public class EpicsHandler extends BaseHttpHandler implements HttpHandler { private final TaskManager manager; @@ -19,36 +20,88 @@ public EpicsHandler(TaskManager manager) { public void handle(HttpExchange exchange) { try { String method = exchange.getRequestMethod(); + String path = exchange.getRequestURI().getPath(); + String query = exchange.getRequestURI().getQuery(); switch (method) { - case "GET" -> sendText(exchange, gson.toJson(manager.getAllEpics()), 200); - case "POST" -> { - String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); - Epic epic = gson.fromJson(body, Epic.class); - - if (epic.getId() == 0) { - manager.addEpic(epic); - sendText(exchange, "{\"id\":" + epic.getId() + "}", 201); - } else if (manager.getEpicById(epic.getId()) != null) { - manager.updateEpic(epic); - sendText(exchange, gson.toJson(epic), 201); - } else sendNotFound(exchange); + case "GET" -> handleGet(exchange, query, path); + case "POST" -> handlePost(exchange); + case "DELETE" -> handleDelete(exchange, query); + default -> sendError(exchange, 405, "Method not allowed"); + } + } catch (Exception e) { + System.err.println("Ошибка EpicsHandler: " + e.getMessage()); + sendInternalError(exchange); + } finally { + exchange.close(); + } + } + + private void handleGet(HttpExchange exchange, String query, String path) { + try { + if (query != null && query.startsWith("id=")) { + int id = Integer.parseInt(query.substring(3)); + Epic epic = manager.getEpicById(id); + if (epic != null) { + sendText(exchange, gson.toJson(epic), 200); + } else { + sendError(exchange, 404, "Epic not found"); } - case "DELETE" -> { - String query = exchange.getRequestURI().getQuery(); - if (query != null && query.startsWith("id=")) { - int id = Integer.parseInt(query.substring(3)); - if (manager.getEpicById(id) != null) { - manager.removeEpicById(id); - sendText(exchange, "{\"status\":\"deleted\"}", 201); - } else sendNotFound(exchange); - } else sendNotFound(exchange); + + } else if (path.contains("/subtasks") && query != null && query.startsWith("id=")) { + int id = Integer.parseInt(query.substring(3)); + if (manager.getEpicById(id) == null) { + sendError(exchange, 404, "Epic not found"); + return; } - default -> sendNotFound(exchange); + List subtasks = manager.getSubtasksOfEpic(id); + sendText(exchange, gson.toJson(subtasks), 200); + + } else { + sendText(exchange, gson.toJson(manager.getAllEpics()), 200); } } catch (Exception e) { - System.err.println("Ошибка EpicsHandler: " + e.getMessage()); + System.err.println("Ошибка обработки GET EpicsHandler: " + e.getMessage()); + sendInternalError(exchange); + } + } + + private void handlePost(HttpExchange exchange) { + try { + String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + Epic epic = gson.fromJson(body, Epic.class); + if (epic.getId() == 0) { + manager.addEpic(epic); + sendText(exchange, "{\"id\":" + epic.getId() + "}", 201); + } else if (manager.getEpicById(epic.getId()) != null) { + manager.updateEpic(epic); + sendText(exchange, gson.toJson(epic), 201); + } else { + sendError(exchange, 404, "Epic not found"); + } + } catch (Exception e) { + System.err.println("Ошибка обработки POST EpicsHandler: " + e.getMessage()); + sendInternalError(exchange); + } + } + + private void handleDelete(HttpExchange exchange, String query) { + try { + if (query != null && query.startsWith("id=")) { + int id = Integer.parseInt(query.substring(3)); + if (manager.getEpicById(id) != null) { + manager.removeEpicById(id); + sendText(exchange, "{\"status\":\"deleted\"}", 200); + } else { + sendError(exchange, 404, "Epic not found"); + } + } else { + manager.clearEpics(); + sendText(exchange, "{\"status\":\"all epics deleted\"}", 200); + } + } catch (Exception e) { + System.err.println("Ошибка обработки DELETE EpicsHandler: " + e.getMessage()); sendInternalError(exchange); } } diff --git a/src/manager/SubtasksHandler.java b/src/manager/SubtasksHandler.java index 551f275..57382b9 100644 --- a/src/manager/SubtasksHandler.java +++ b/src/manager/SubtasksHandler.java @@ -18,51 +18,91 @@ public SubtasksHandler(TaskManager manager) { public void handle(HttpExchange exchange) { try { String method = exchange.getRequestMethod(); + String query = exchange.getRequestURI().getQuery(); switch (method) { - case "GET" -> sendText(exchange, gson.toJson(manager.getAllSubtasks()), 200); + case "GET" -> handleGet(exchange, query); + case "POST" -> handlePost(exchange); + case "DELETE" -> handleDelete(exchange, query); + default -> sendError(exchange, 405, "Method not allowed"); + } + } catch (Exception e) { + System.err.println("Ошибка SubtasksHandler: " + e.getMessage()); + sendInternalError(exchange); + } finally { + exchange.close(); + } + } - case "POST" -> { - String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); - Subtask subtask = gson.fromJson(body, Subtask.class); + private void handleGet(HttpExchange exchange, String query) { + try { + if (query != null && query.startsWith("id=")) { + int id = Integer.parseInt(query.substring(3)); + Subtask subtask = manager.getSubtaskById(id); + if (subtask != null) { + sendText(exchange, gson.toJson(subtask), 200); + } else { + sendError(exchange, 404, "Subtask not found"); + } + } else { + sendText(exchange, gson.toJson(manager.getAllSubtasks()), 200); + } + } catch (Exception e) { + System.err.println("Ошибка обработки GET SubtasksHandler: " + e.getMessage()); + sendInternalError(exchange); + } + } - if (subtask.getId() == 0) { - if (manager.getEpicById(subtask.getEpicId()) == null) { - sendNotFound(exchange); - return; - } - manager.addSubtask(subtask); - sendText(exchange, "{\"id\":" + subtask.getId() + "}", 201); + private void handlePost(HttpExchange exchange) { + try { + String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + Subtask subtask = gson.fromJson(body, Subtask.class); + + try { + if (subtask.getId() == 0) { + if (manager.getEpicById(subtask.getEpicId()) == null) { + sendError(exchange, 400, "Related epic not found"); + return; + } + manager.addSubtask(subtask); + sendText(exchange, "{\"id\":" + subtask.getId() + "}", 201); + } else { + Subtask old = manager.getSubtaskById(subtask.getId()); + if (old == null) { + sendError(exchange, 404, "Subtask not found"); + } else if (old.getEpicId() != subtask.getEpicId()) { + sendError(exchange, 400, "Cannot change epicId of subtask"); } else { - Subtask old = manager.getSubtaskById(subtask.getId()); - if (old == null) { - sendNotFound(exchange); - } else if (old.getEpicId() != subtask.getEpicId()) { - sendHasOverlaps(exchange); - } else { - manager.updateSubtask(subtask); - sendText(exchange, gson.toJson(subtask), 201); - } + manager.updateSubtask(subtask); + sendText(exchange, gson.toJson(subtask), 201); } } + } catch (TaskOverlapException e) { + sendError(exchange, 409, e.getMessage()); + } + } catch (Exception e) { + System.err.println("Ошибка обработки POST SubtasksHandler: " + e.getMessage()); + sendInternalError(exchange); + } + } - case "DELETE" -> { - String query = exchange.getRequestURI().getQuery(); - if (query != null && query.startsWith("id=")) { - int id = Integer.parseInt(query.substring(3)); - if (manager.getSubtaskById(id) != null) { - manager.removeSubtaskById(id); - sendText(exchange, "{\"status\":\"deleted\"}", 201); - } else sendNotFound(exchange); - } else sendNotFound(exchange); + private void handleDelete(HttpExchange exchange, String query) { + try { + if (query != null && query.startsWith("id=")) { + int id = Integer.parseInt(query.substring(3)); + if (manager.getSubtaskById(id) != null) { + manager.removeSubtaskById(id); + sendText(exchange, "{\"status\":\"deleted\"}", 200); + } else { + sendError(exchange, 404, "Subtask not found"); } - - default -> sendNotFound(exchange); + } else { + manager.clearSubtasks(); + sendText(exchange, "{\"status\":\"all subtasks deleted\"}", 200); } } catch (Exception e) { - System.err.println("Ошибка SubtasksHandler: " + e.getMessage()); - + System.err.println("Ошибка обработки DELETE SubtasksHandler: " + e.getMessage()); sendInternalError(exchange); } } diff --git a/src/manager/TasksHandler.java b/src/manager/TasksHandler.java index b97d162..77b3fa2 100644 --- a/src/manager/TasksHandler.java +++ b/src/manager/TasksHandler.java @@ -5,8 +5,6 @@ import com.sun.net.httpserver.HttpHandler; import model.Task; import java.nio.charset.StandardCharsets; -import java.util.List; - public class TasksHandler extends BaseHttpHandler implements HttpHandler { private final TaskManager manager; @@ -20,41 +18,81 @@ public TasksHandler(TaskManager manager) { public void handle(HttpExchange exchange) { try { String method = exchange.getRequestMethod(); + String query = exchange.getRequestURI().getQuery(); switch (method) { - case "GET" -> { - List tasks = manager.getAllTasks(); - sendText(exchange, gson.toJson(tasks), 200); - } - case "POST" -> { - String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); - Task task = gson.fromJson(body, Task.class); - - if (task.getId() == 0) { - manager.addTask(task); - sendText(exchange, "{\"id\":" + task.getId() + "}", 201); - } else if (manager.getTaskById(task.getId()) != null) { - manager.updateTask(task); - sendText(exchange, gson.toJson(task), 201); - } else { - sendNotFound(exchange); - } + case "GET" -> handleGet(exchange, query); + case "POST" -> handlePost(exchange); + case "DELETE" -> handleDelete(exchange, query); + default -> sendError(exchange, 405, "Method not allowed"); + } + } catch (Exception e) { + System.err.println("Ошибка TasksHandler: " + e.getMessage()); + sendInternalError(exchange); + } finally { + exchange.close(); + } + } + + private void handleGet(HttpExchange exchange, String query) { + try { + if (query != null && query.startsWith("id=")) { + int id = Integer.parseInt(query.substring(3)); + Task task = manager.getTaskById(id); + if (task != null) { + sendText(exchange, gson.toJson(task), 200); + } else { + sendError(exchange, 404, "Task not found"); } - case "DELETE" -> { - String query = exchange.getRequestURI().getQuery(); - if (query != null && query.startsWith("id=")) { - int id = Integer.parseInt(query.substring(3)); - if (manager.getTaskById(id) != null) { - manager.removeTaskById(id); - sendText(exchange, "{\"status\":\"deleted\"}", 201); - } else sendNotFound(exchange); - } else sendNotFound(exchange); + } else { + sendText(exchange, gson.toJson(manager.getAllTasks()), 200); + } + } catch (Exception e) { + System.err.println("Ошибка обработки GET TasksHandler: " + e.getMessage()); + sendInternalError(exchange); + } + } + + private void handlePost(HttpExchange exchange) { + try { + String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + Task task = gson.fromJson(body, Task.class); + + try { + if (task.getId() == 0) { + manager.addTask(task); + sendText(exchange, "{\"id\":" + task.getId() + "}", 201); + } else if (manager.getTaskById(task.getId()) != null) { + manager.updateTask(task); + sendText(exchange, gson.toJson(task), 201); + } else { + sendError(exchange, 404, "Task not found"); } - default -> sendNotFound(exchange); + } catch (TaskOverlapException e) { + sendError(exchange, 409, e.getMessage()); } } catch (Exception e) { - System.err.println("Ошибка TasksHandler: " + e.getMessage()); + System.err.println("Ошибка обработки POST TasksHandler: " + e.getMessage()); + sendInternalError(exchange); + } + } + private void handleDelete(HttpExchange exchange, String query) { + try { + if (query != null && query.startsWith("id=")) { + int id = Integer.parseInt(query.substring(3)); + if (manager.getTaskById(id) != null) { + manager.removeTaskById(id); + sendText(exchange, "{\"status\":\"deleted\"}", 200); + } else { + sendError(exchange, 404, "Task not found"); + } + } else { + manager.clearTasks(); + sendText(exchange, "{\"status\":\"all tasks deleted\"}", 200); + } + } catch (Exception e) { + System.err.println("Ошибка обработки DELETE TasksHandler: " + e.getMessage()); sendInternalError(exchange); } } From b70d036c94456c0c52a493982f9f29953fb14e48 Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Thu, 31 Jul 2025 09:31:45 +0300 Subject: [PATCH 9/9] Update BaseHttpHandler.java --- src/manager/BaseHttpHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/manager/BaseHttpHandler.java b/src/manager/BaseHttpHandler.java index de0cb7b..1ddc39b 100644 --- a/src/manager/BaseHttpHandler.java +++ b/src/manager/BaseHttpHandler.java @@ -49,6 +49,6 @@ protected void sendError(HttpExchange exchange, int statusCode, String message) try { String json = "{\"error\":\"" + message + "\"}"; sendText(exchange, json, statusCode); - } catch (IOException ignored) {} + } catch (IOException ignored) { } } }