From 3f26783a5f510a866f3e61a5d68bdd8474fabaab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BB=D0=B0=D0=B2=D0=B0?= Date: Fri, 20 Dec 2024 19:12:38 +0400 Subject: [PATCH 1/5] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=B0=D1=8F=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=A2=D0=97=209=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=BD=D1=82=D0=B0...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/inspectionProfiles/Project_Default.xml | 9 ++ .idea/libraries/google_code_gson.xml | 10 ++ .idea/libraries/lib.xml | 10 ++ java-kanban.iml | 1 + src/Main.java | 40 +++-- src/exception/NotFoundException.java | 7 + src/manager/DurationAdapter.java | 24 +++ src/manager/InMemoryTaskManager.java | 3 +- src/manager/LocalDateTimeAdapter.java | 33 ++++ src/manager/Managers.java | 16 ++ src/manager/TaskManager.java | 4 +- src/server/BaseHttpHandler.java | 48 ++++++ src/server/EpicHandler.java | 114 ++++++++++++++ src/server/HistoryHandler.java | 28 ++++ src/server/HttpTaskServer.java | 56 +++++++ src/server/PriorityzedHandler.java | 28 ++++ src/server/SubtaskHandler.java | 148 ++++++++++++++++++ src/server/TaskHandler.java | 152 +++++++++++++++++++ src/task/Task.java | 15 +- 19 files changed, 723 insertions(+), 23 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/libraries/google_code_gson.xml create mode 100644 .idea/libraries/lib.xml create mode 100644 src/exception/NotFoundException.java create mode 100644 src/manager/DurationAdapter.java create mode 100644 src/manager/LocalDateTimeAdapter.java create mode 100644 src/server/BaseHttpHandler.java create mode 100644 src/server/EpicHandler.java create mode 100644 src/server/HistoryHandler.java create mode 100644 src/server/HttpTaskServer.java create mode 100644 src/server/PriorityzedHandler.java create mode 100644 src/server/SubtaskHandler.java create mode 100644 src/server/TaskHandler.java diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..62a5ab0 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/.idea/libraries/google_code_gson.xml b/.idea/libraries/google_code_gson.xml new file mode 100644 index 0000000..6a53471 --- /dev/null +++ b/.idea/libraries/google_code_gson.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/lib.xml b/.idea/libraries/lib.xml new file mode 100644 index 0000000..fa8838a --- /dev/null +++ b/.idea/libraries/lib.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/java-kanban.iml b/java-kanban.iml index 5cfcb5a..e2da860 100644 --- a/java-kanban.iml +++ b/java-kanban.iml @@ -71,5 +71,6 @@ + \ No newline at end of file diff --git a/src/Main.java b/src/Main.java index a1d7249..b940299 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,20 +1,35 @@ + + import exception.IntersectionException; -import manager.*; -import task.Epic; -import task.Status; -import task.Subtask; -import task.Task; -import java.io.File; -import java.time.Duration; -import java.time.LocalDateTime; + +import java.io.IOException; public class Main { - public static void main(String[] args) throws IntersectionException { + public static void main(String[] args) throws IntersectionException, IOException, InterruptedException { + + // Я не могу понять в чём ошибка. Пишет Failed making field 'java.time.format.DateTimeFormatter#printerParser' accessible. + // Вроде DateTimeAdapter написан правильно и подключил его к gson... + + + /* TaskManager taskManager = new InMemoryTaskManager(Managers.getDefaultHistory()); + HttpTaskServer httpTaskServer = new HttpTaskServer(taskManager); + Gson gson = httpTaskServer.getGson(); + Task task = new Task("Test 2", "Testing task 2", + Status.NEW); + String taskJson = gson.toJson(task); + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder().uri(url).POST(HttpRequest.BodyPublishers.ofString(taskJson)).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + System.out.println(response); */ - File file = new File("src/loadFile.csv"); + + + + /* File file = new File("src/loadFile.csv"); System.out.println(FileBackedTaskManager.loadFromFile(file).getHistory()); FileBackedTaskManager taskManager = new FileBackedTaskManager(Managers.getDefaultHistory()); Epic epic1 = new Epic("Epic-1", "Epic-1", Status.IN_PROGRESS); @@ -36,9 +51,8 @@ public static void main(String[] args) throws IntersectionException { taskManager.deleteSubtask(4); System.out.println(epic1); System.out.println(taskManager.getHistory()); - - - System.out.println(taskManager.getPrioritizedTasks()); + System.out.println(task1); + System.out.println(taskManager.getPrioritizedTasks());*/ } diff --git a/src/exception/NotFoundException.java b/src/exception/NotFoundException.java new file mode 100644 index 0000000..c6cc4ea --- /dev/null +++ b/src/exception/NotFoundException.java @@ -0,0 +1,7 @@ +package exception; + +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } +} diff --git a/src/manager/DurationAdapter.java b/src/manager/DurationAdapter.java new file mode 100644 index 0000000..9eec119 --- /dev/null +++ b/src/manager/DurationAdapter.java @@ -0,0 +1,24 @@ +package manager; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.time.Duration; + +public class DurationAdapter extends TypeAdapter { + @Override + public void write(JsonWriter jsonWriter, Duration duration) throws IOException { + if (duration != null) { + jsonWriter.value(duration.toMinutes()); + } else { + jsonWriter.nullValue(); + } + } + + @Override + public Duration read(JsonReader jsonReader) throws IOException { + return Duration.ofMinutes(jsonReader.nextInt()); + } +} diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index a3efc3f..d39a318 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -150,7 +150,8 @@ private Status epicStatus(Epic epic) { @Override - public Task updateTask(Task task) { + public Task updateTask(Task task) throws IntersectionException { + taskIntersection(task); Integer taskId = task.getId(); if (taskId == null || !tasks.containsKey(taskId)) { return null; diff --git a/src/manager/LocalDateTimeAdapter.java b/src/manager/LocalDateTimeAdapter.java new file mode 100644 index 0000000..792044a --- /dev/null +++ b/src/manager/LocalDateTimeAdapter.java @@ -0,0 +1,33 @@ +package manager; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class LocalDateTimeAdapter extends TypeAdapter { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); + + @Override + public void write(JsonWriter jsonWriter, LocalDateTime localDateTime) throws IOException { + + if (localDateTime != null) { + jsonWriter.value(localDateTime.format(dateTimeFormatter)); + } else { + jsonWriter.nullValue(); + } + } + + + @Override + public LocalDateTime read(JsonReader jsonReader) throws IOException { + String string = jsonReader.nextString(); + if (string.isBlank()) { + return null; + } + return LocalDateTime.parse(string, dateTimeFormatter); + } +} diff --git a/src/manager/Managers.java b/src/manager/Managers.java index 2907ede..aaeea2d 100644 --- a/src/manager/Managers.java +++ b/src/manager/Managers.java @@ -1,5 +1,12 @@ package manager; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.time.Duration; +import java.time.LocalDateTime; + public class Managers { @@ -10,4 +17,13 @@ public static TaskManager getDefault() { public static HistoryManager getDefaultHistory() { return new InMemoryHistoryManager(); } + public static Gson getGson() { + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.serializeNulls(); + gsonBuilder.setPrettyPrinting(); + gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()); + gsonBuilder.registerTypeAdapter(Duration.class, new DurationAdapter()); + return gsonBuilder.create(); + } + } diff --git a/src/manager/TaskManager.java b/src/manager/TaskManager.java index 61acfe4..6b63e02 100644 --- a/src/manager/TaskManager.java +++ b/src/manager/TaskManager.java @@ -9,6 +9,7 @@ import java.util.HashMap; import java.util.List; +import java.util.Set; public interface TaskManager { @@ -35,7 +36,7 @@ public interface TaskManager { Task createEpic(Epic epic); - Task updateTask(Task task); + Task updateTask(Task task) throws IntersectionException; Subtask updateSubtask(Subtask subtask); @@ -53,6 +54,7 @@ public interface TaskManager { boolean deleteEpic(int taskId); int getNextId(); + Set getPrioritizedTasks(); } diff --git a/src/server/BaseHttpHandler.java b/src/server/BaseHttpHandler.java new file mode 100644 index 0000000..425a800 --- /dev/null +++ b/src/server/BaseHttpHandler.java @@ -0,0 +1,48 @@ +package server; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import manager.TaskManager; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public abstract class BaseHttpHandler implements HttpHandler { + protected TaskManager taskManager; + protected Gson gson; + + public BaseHttpHandler(TaskManager taskManager, Gson gson) { + this.taskManager = taskManager; + this.gson = gson; + } + + private void sendResponse(HttpExchange h, int statusCode, String text) throws IOException { + byte[] response = text.getBytes(StandardCharsets.UTF_8); + h.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); + h.sendResponseHeaders(statusCode, response.length); + h.getResponseBody().write(response); + h.close(); + } + + protected void sendText(HttpExchange h, String text) throws IOException { + sendResponse(h, 200, text); + } + + protected void sendAdd(HttpExchange h, String text) throws IOException { + sendResponse(h, 201, text); + } + + public void sendNotFound(HttpExchange h, String text) throws IOException { + sendResponse(h, 404, text); + } + + + public void sendHasInteractions(HttpExchange h, String text) throws IOException { + sendResponse(h, 406, text); + } + + public void sendInternalServerError(HttpExchange httpExchange) throws IOException { + httpExchange.sendResponseHeaders(500, 0); + } +} diff --git a/src/server/EpicHandler.java b/src/server/EpicHandler.java new file mode 100644 index 0000000..f18f31c --- /dev/null +++ b/src/server/EpicHandler.java @@ -0,0 +1,114 @@ +package server; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import exception.NotFoundException; +import manager.TaskManager; +import task.Epic; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.regex.Pattern; + +public class EpicHandler extends BaseHttpHandler { + public EpicHandler(TaskManager taskManager, Gson gson) { + super(taskManager, gson); + } + + private int parsePathID(String path) { + try { + return Integer.parseInt(path); + } catch (NumberFormatException e) { + return -1; + } + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + + } + + private void handleGet(HttpExchange exchange) throws IOException { + String path = exchange.getRequestURI().getPath(); + if (Pattern.matches("^/epics$", path)) { + try { + String response = gson.toJson(taskManager.getEpics()); + sendText(exchange, response); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + if (Pattern.matches("^/epics/\\d+$", path)) { + try { + String pathId = path.replaceFirst("/epics/", ""); + int id = parsePathID(pathId); + if (id != -1) { + String response = gson.toJson(taskManager.getEpic(id)); + sendText(exchange, response); + } + } catch (NotFoundException e) { + sendNotFound(exchange, "Эпик не найден"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + if (Pattern.matches("^/subtasks$", path)) { + try { + String pathId = path.replaceFirst("/epics/", "").replaceFirst("/subtasks$", ""); + int id = parsePathID(pathId); + if (id != -1) { + Epic epic = taskManager.getEpic(id); + String response = gson.toJson(taskManager.getSubtasksFromEpic(epic)); + sendText(exchange, response); + } + } catch (NotFoundException e) { + sendNotFound(exchange, "Эпик не найден"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + } + + private void handlePost(HttpExchange exchange) throws IOException { + + try { + String epic = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + Epic epic1 = gson.fromJson(epic, Epic.class); + taskManager.createEpic(epic1); + sendAdd(exchange, "Эпик создан"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + + private void handleDelete(HttpExchange exchange) throws IOException { + String path = exchange.getRequestURI().getPath(); + try { + if (Pattern.matches("^/epics$", path)) { + try { + + + taskManager.deleteAllEpic(); + sendText(exchange, "Удалены все Эпики"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + if (Pattern.matches("^/epics/\\d+$", path)) { + String epicId = path.replaceFirst("/epics/", ""); + int id = parsePathID(epicId); + if (id != -1) { + taskManager.deleteEpic(id); + sendText(exchange, "Удалён эпик с id " + id); + } + } + + } catch (NotFoundException e) { + sendNotFound(exchange, "Эпик не найден"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + + } + +} diff --git a/src/server/HistoryHandler.java b/src/server/HistoryHandler.java new file mode 100644 index 0000000..4b9edfb --- /dev/null +++ b/src/server/HistoryHandler.java @@ -0,0 +1,28 @@ +package server; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import manager.TaskManager; + +import java.io.IOException; + +public class HistoryHandler extends BaseHttpHandler { + public HistoryHandler(TaskManager taskManager, Gson gson) { + super(taskManager, gson); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + String requestMethod = exchange.getRequestMethod(); + if (requestMethod.equals("GET")) { + try { + String history = gson.toJson(taskManager.getHistory()); + sendText(exchange, history); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } else { + sendInternalServerError(exchange); + } + } +} diff --git a/src/server/HttpTaskServer.java b/src/server/HttpTaskServer.java new file mode 100644 index 0000000..a906eca --- /dev/null +++ b/src/server/HttpTaskServer.java @@ -0,0 +1,56 @@ +package server; + +import com.google.gson.Gson; + +import com.sun.net.httpserver.HttpServer; +import manager.*; + + +import java.io.IOException; +import java.net.InetSocketAddress; + + +public class HttpTaskServer { + public static final int PORT = 8080; + private HttpServer httpServer; + /* public static final Gson gson = new GsonBuilder() + .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()) + .registerTypeAdapter(Duration.class, new DurationAdapter()) + .create();*/ + private TaskManager taskManager; + private Gson gson; + + public Gson getGson() { + return gson; + } + + public HttpTaskServer(TaskManager taskManager) throws IOException { + this.taskManager = taskManager; + gson = Managers.getGson(); + httpServer = HttpServer.create(new InetSocketAddress("localhost", PORT), 0); + httpServer.createContext("/tasks", new TaskHandler(taskManager, gson)); + httpServer.createContext("/subtasks", new SubtaskHandler(taskManager, gson)); + httpServer.createContext("/epics", new EpicHandler(taskManager, gson)); + httpServer.createContext("/history", new TaskHandler(taskManager, gson)); + httpServer.createContext("/prioritized", new TaskHandler(taskManager, gson)); + } + + public void start() { + System.out.println("Сервер запущен на порту: " + PORT); + httpServer.start(); + } + + public void stop() { + httpServer.stop(0); + System.out.println("Сервер остановлен на порту: " + PORT); + } + + public static void main(String[] args) throws IOException { + InMemoryTaskManager taskManager = new InMemoryTaskManager(Managers.getDefaultHistory()); + HttpTaskServer httpTaskServer = new HttpTaskServer(taskManager); + httpTaskServer.start(); + + + } + +} diff --git a/src/server/PriorityzedHandler.java b/src/server/PriorityzedHandler.java new file mode 100644 index 0000000..f043c10 --- /dev/null +++ b/src/server/PriorityzedHandler.java @@ -0,0 +1,28 @@ +package server; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import manager.TaskManager; + +import java.io.IOException; + +public class PriorityzedHandler extends BaseHttpHandler { + public PriorityzedHandler(TaskManager taskManager, Gson gson) { + super(taskManager, gson); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + String requestMethod = exchange.getRequestMethod(); + if (requestMethod.equals("GET")) { + try { + String prioritized = gson.toJson(taskManager.getPrioritizedTasks()); + sendText(exchange, prioritized); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } else { + sendInternalServerError(exchange); + } + } +} diff --git a/src/server/SubtaskHandler.java b/src/server/SubtaskHandler.java new file mode 100644 index 0000000..2d0b173 --- /dev/null +++ b/src/server/SubtaskHandler.java @@ -0,0 +1,148 @@ +package server; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import exception.IntersectionException; +import exception.NotFoundException; +import manager.TaskManager; +import task.Subtask; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.regex.Pattern; + +public class SubtaskHandler extends BaseHttpHandler { + public SubtaskHandler(TaskManager taskManager, Gson gson) { + super(taskManager, gson); + } + + private int parsePathID(String path) { + try { + return Integer.parseInt(path); + } catch (NumberFormatException e) { + return -1; + } + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + String method = exchange.getRequestMethod(); + switch (method) { + case "GET": { + handleGet(exchange); + break; + } + case "POST": { + handlePost(exchange); + break; + } + case "DELETE": { + handleDelete(exchange); + break; + } + default: { + sendNotFound(exchange, "Некорректный запрос"); + break; + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + exchange.close(); + } + + } + + private void handleGet(HttpExchange exchange) throws IOException { + String path = exchange.getRequestURI().getPath(); + if (Pattern.matches("^/subtasks$", path)) { + try { + String response = gson.toJson(taskManager.getSubtasks()); + sendText(exchange, response); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + if (Pattern.matches("^/subtasks/\\\\d+$", path)) { + try { + String pathId = path.replaceFirst("/subtasks/", ""); + int id = parsePathID(pathId); + if (id != -1) { + String response = gson.toJson(taskManager.getSubtask(id)); + sendText(exchange, response); + } + } catch (NotFoundException e) { + sendNotFound(exchange, "Подзадача не найдена"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + } + + private void handlePost(HttpExchange exchange) throws IOException { + String path = exchange.getRequestURI().getPath(); + if (Pattern.matches("^/subtasks$", path)) { + try { + String subtask = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + Subtask subtask1 = gson.fromJson(subtask, Subtask.class); + taskManager.createTask(subtask1); + sendAdd(exchange, "Подзадача создана"); + } catch (IntersectionException e) { + sendHasInteractions(exchange, " Подзадача пересекается по времени с уже существующей"); + + } catch (NotFoundException e) { + sendNotFound(exchange, "Эпик не найден"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + if (Pattern.matches("^/subtasks/\\d+$", path)) { + try { + String taskId = path.replaceFirst("/subtask", ""); + int id = parsePathID(taskId); + if (id != -1) { + String subtask = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + Subtask subtask1 = gson.fromJson(subtask, Subtask.class); + taskManager.updateTask(subtask1); + sendAdd(exchange, "Подзадача обновлена"); + } + + } catch (IntersectionException e) { + sendHasInteractions(exchange, "Обновлённая подзадача пересекается по времени с уже существующей"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + + } + + private void handleDelete(HttpExchange exchange) throws IOException { + String path = exchange.getRequestURI().getPath(); + + if (Pattern.matches("^/subtasks$", path)) { + try { + taskManager.deleteAllSubtasks(); + sendText(exchange, "Всё подзадачи удалены"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + if (Pattern.matches("^/subtasks/\\d+$", path)) { + String subtaskId = path.replaceFirst("/subtask", ""); + int id = parsePathID(subtaskId); + if (id != -1) { + try { + taskManager.deleteSubtask(id); + sendText(exchange, "Подзадача с id " + id + " удалена"); + } catch (NotFoundException e) { + sendNotFound(exchange, "Подзадача не найдена"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + + } + + } +} diff --git a/src/server/TaskHandler.java b/src/server/TaskHandler.java new file mode 100644 index 0000000..bd9d583 --- /dev/null +++ b/src/server/TaskHandler.java @@ -0,0 +1,152 @@ +package server; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import exception.IntersectionException; +import exception.NotFoundException; +import manager.TaskManager; +import task.Task; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.regex.Pattern; + +public class TaskHandler extends BaseHttpHandler { + public TaskHandler(TaskManager taskManager, Gson gson) { + super(taskManager, gson); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + String method = exchange.getRequestMethod(); + switch (method) { + case "GET": { + + + handleGet(exchange); + break; + } + case "POST": { + handlePost(exchange); + break; + + } + case "DELETE": { + handleDelete(exchange); + break; + + } + default: + sendNotFound(exchange, "Некорректный запрос"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + exchange.close(); + } + + } + + private int parsePathID(String path) { + try { + return Integer.parseInt(path); + } catch (NumberFormatException e) { + return -1; + } + } + + private void handleGet(HttpExchange exchange) throws IOException { + String path = exchange.getRequestURI().getPath(); + if (Pattern.matches("^/tasks$", path)) { + try { + String response = gson.toJson(taskManager.getTasks()); + sendText(exchange, response); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + if (Pattern.matches("^/tasks/\\d+$", path)) { + try { + String pathId = path.replaceFirst("/tasks/", ""); + int id = parsePathID(pathId); + if (id != -1) { + String response = gson.toJson(taskManager.getTask(id)); + sendText(exchange, response); + } + } catch (NotFoundException e) { + sendNotFound(exchange, "Задача не найдена"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + } + + private void handlePost(HttpExchange exchange) throws IOException { + String path = exchange.getRequestURI().getPath(); + if (Pattern.matches("^/tasks$", path)) { + try { + InputStream inputStream = exchange.getRequestBody(); + String task = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + Task task1 = gson.fromJson(task, Task.class); + taskManager.createTask(task1); + sendAdd(exchange, "Задача создана"); + } catch (IntersectionException e) { + sendHasInteractions(exchange, " Задача пересекается по времени с уже существующей"); + + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + if (Pattern.matches("^/tasks/\\d+$", path)) { + try { + String taskId = path.replaceFirst("/task", ""); + int id = parsePathID(taskId); + if (id != -1) { + InputStream inputStream = exchange.getRequestBody(); + String task = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + Task task1 = gson.fromJson(task, Task.class); + taskManager.updateTask(task1); + sendAdd(exchange, "Задача обновлена"); + } + + } catch (IntersectionException e) { + sendHasInteractions(exchange, "Обновлённая задача пересекается по времени с уже существующей"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + + } + + private void handleDelete(HttpExchange exchange) throws IOException { + String path = exchange.getRequestURI().getPath(); + + if (Pattern.matches("^/tasks$", path)) { + try { + taskManager.deleteAllTasks(); + sendText(exchange, "Всё задачи удалены"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + if (Pattern.matches("^/tasks/\\d+$", path)) { + String taskId = path.replaceFirst("/task", ""); + int id = parsePathID(taskId); + if (id != -1) { + try { + taskManager.deleteTask(id); + sendText(exchange, "Задача с id " + id + " удалена"); + } catch (NotFoundException e) { + sendNotFound(exchange, "Задача не найдена"); + } catch (Exception e) { + sendInternalServerError(exchange); + } + } + + } + + } + +} diff --git a/src/task/Task.java b/src/task/Task.java index 9316c45..f9f3544 100644 --- a/src/task/Task.java +++ b/src/task/Task.java @@ -131,14 +131,13 @@ public Status getStatus() { @Override public String toString() { - return "Task{" + - "id=" + id + - ", name='" + name + '\'' + - ", description='" + description + '\'' + - ", status=" + status + - ", type=" + type + - ", startTime=" + startTime.format(DateTimeFormatter.ofPattern("dd.MM.yy HH:mm")) + - ", duration=" + duration + + return "ModelTask.Task{" + + "id=" + getId() + + ", name='" + getName() + '\'' + + ", description='" + getDescription() + '\'' + + ", status=" + getStatus() + '\'' + + ", duration=" + getDuration() + '\'' + + ", startTime=" + getStartTime() + '\'' + '}'; } From 097bb7b68b14724b96704f1ebdccee8ab9cb1159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BB=D0=B0=D0=B2=D0=B0?= Date: Fri, 20 Dec 2024 19:15:08 +0400 Subject: [PATCH 2/5] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=B0=D1=8F=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=A2=D0=97=209=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=BD=D1=82=D0=B0...=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D0=B0?= =?UTF-8?q?=D0=B2=D1=82=D0=BE=D1=82=D0=B5=D1=81=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/TaskManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/manager/TaskManager.java b/src/manager/TaskManager.java index 6b63e02..7575a7b 100644 --- a/src/manager/TaskManager.java +++ b/src/manager/TaskManager.java @@ -54,6 +54,7 @@ public interface TaskManager { boolean deleteEpic(int taskId); int getNextId(); + Set getPrioritizedTasks(); } From 5abc60993c5ac985e9c0f40a8fd380513a12e10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BB=D0=B0=D0=B2=D0=B0?= Date: Fri, 20 Dec 2024 19:16:19 +0400 Subject: [PATCH 3/5] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=B0=D1=8F=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=A2=D0=97=209=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=BD=D1=82=D0=B0...=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D0=B0?= =?UTF-8?q?=D0=B2=D1=82=D0=BE=D1=82=D0=B5=D1=81=D1=82=D0=B0=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/Managers.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/manager/Managers.java b/src/manager/Managers.java index aaeea2d..fc8478d 100644 --- a/src/manager/Managers.java +++ b/src/manager/Managers.java @@ -17,6 +17,7 @@ public static TaskManager getDefault() { public static HistoryManager getDefaultHistory() { return new InMemoryHistoryManager(); } + public static Gson getGson() { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.serializeNulls(); From 34ddea679066f8e7eb6dea4ba8623584a0f2b9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BB=D0=B0=D0=B2=D0=B0?= Date: Sat, 21 Dec 2024 18:46:31 +0400 Subject: [PATCH 4/5] =?UTF-8?q?=D0=92=D1=82=D0=BE=D1=80=D0=B0=D1=8F=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=A2=D0=97=209=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=BD=D1=82=D0=B0.=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D1=81=D0=BE=D0=B7?= =?UTF-8?q?=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Main.java | 35 +++++------- src/manager/LocalDateTimeAdapter.java | 5 +- src/manager/Managers.java | 15 +----- src/server/HttpTaskServer.java | 45 ++++++++++++---- src/server/TaskHandler.java | 4 +- src/task/Task.java | 5 +- test/manager/HttpTaskServerTest.java | 78 +++++++++++++++++++++++++++ 7 files changed, 134 insertions(+), 53 deletions(-) create mode 100644 test/manager/HttpTaskServerTest.java diff --git a/src/Main.java b/src/Main.java index b940299..7537f9f 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,35 +1,26 @@ - - import exception.IntersectionException; +import manager.FileBackedTaskManager; +import manager.Managers; -import java.io.IOException; - +import task.Epic; +import task.Status; +import task.Subtask; +import task.Task; -public class Main { - - public static void main(String[] args) throws IntersectionException, IOException, InterruptedException { - // Я не могу понять в чём ошибка. Пишет Failed making field 'java.time.format.DateTimeFormatter#printerParser' accessible. - // Вроде DateTimeAdapter написан правильно и подключил его к gson... +import java.io.File; +import java.time.Duration; +import java.time.LocalDateTime; - /* TaskManager taskManager = new InMemoryTaskManager(Managers.getDefaultHistory()); - HttpTaskServer httpTaskServer = new HttpTaskServer(taskManager); - Gson gson = httpTaskServer.getGson(); - Task task = new Task("Test 2", "Testing task 2", - Status.NEW); - String taskJson = gson.toJson(task); - HttpClient client = HttpClient.newHttpClient(); - URI url = URI.create("http://localhost:8080/tasks"); - HttpRequest request = HttpRequest.newBuilder().uri(url).POST(HttpRequest.BodyPublishers.ofString(taskJson)).build(); - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - System.out.println(response); */ +public class Main { + public static void main(String[] args) throws IntersectionException { - /* File file = new File("src/loadFile.csv"); + File file = new File("src/loadFile.csv"); System.out.println(FileBackedTaskManager.loadFromFile(file).getHistory()); FileBackedTaskManager taskManager = new FileBackedTaskManager(Managers.getDefaultHistory()); Epic epic1 = new Epic("Epic-1", "Epic-1", Status.IN_PROGRESS); @@ -52,7 +43,7 @@ public static void main(String[] args) throws IntersectionException, IOException System.out.println(epic1); System.out.println(taskManager.getHistory()); System.out.println(task1); - System.out.println(taskManager.getPrioritizedTasks());*/ + System.out.println(taskManager.getPrioritizedTasks()); } diff --git a/src/manager/LocalDateTimeAdapter.java b/src/manager/LocalDateTimeAdapter.java index 792044a..b9007f3 100644 --- a/src/manager/LocalDateTimeAdapter.java +++ b/src/manager/LocalDateTimeAdapter.java @@ -1,6 +1,6 @@ package manager; -import com.google.gson.TypeAdapter; +import com.google.gson.*; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; @@ -8,8 +8,9 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; + public class LocalDateTimeAdapter extends TypeAdapter { - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); + private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); @Override public void write(JsonWriter jsonWriter, LocalDateTime localDateTime) throws IOException { diff --git a/src/manager/Managers.java b/src/manager/Managers.java index fc8478d..63bc905 100644 --- a/src/manager/Managers.java +++ b/src/manager/Managers.java @@ -1,12 +1,6 @@ package manager; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import java.time.Duration; -import java.time.LocalDateTime; - public class Managers { @@ -18,13 +12,6 @@ public static HistoryManager getDefaultHistory() { return new InMemoryHistoryManager(); } - public static Gson getGson() { - GsonBuilder gsonBuilder = new GsonBuilder(); - gsonBuilder.serializeNulls(); - gsonBuilder.setPrettyPrinting(); - gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()); - gsonBuilder.registerTypeAdapter(Duration.class, new DurationAdapter()); - return gsonBuilder.create(); - } + } diff --git a/src/server/HttpTaskServer.java b/src/server/HttpTaskServer.java index a906eca..d8ebe2b 100644 --- a/src/server/HttpTaskServer.java +++ b/src/server/HttpTaskServer.java @@ -2,31 +2,43 @@ import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.sun.net.httpserver.HttpServer; import manager.*; +import task.Status; +import task.Task; import java.io.IOException; import java.net.InetSocketAddress; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.LocalDateTime; public class HttpTaskServer { - public static final int PORT = 8080; + public static final int PORT = 8081; //У меня что-то сломалось и теперь на порту 8080 всегда пишет Address already in use: bind private HttpServer httpServer; - /* public static final Gson gson = new GsonBuilder() - .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()) - .registerTypeAdapter(Duration.class, new DurationAdapter()) - .create();*/ private TaskManager taskManager; private Gson gson; - public Gson getGson() { - return gson; + + public static Gson getGson() { + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.serializeNulls(); + gsonBuilder.setPrettyPrinting(); + gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()); + gsonBuilder.registerTypeAdapter(Duration.class, new DurationAdapter()); + return gsonBuilder.create(); } public HttpTaskServer(TaskManager taskManager) throws IOException { this.taskManager = taskManager; - gson = Managers.getGson(); + gson = HttpTaskServer.getGson(); httpServer = HttpServer.create(new InetSocketAddress("localhost", PORT), 0); httpServer.createContext("/tasks", new TaskHandler(taskManager, gson)); httpServer.createContext("/subtasks", new SubtaskHandler(taskManager, gson)); @@ -45,10 +57,23 @@ public void stop() { System.out.println("Сервер остановлен на порту: " + PORT); } - public static void main(String[] args) throws IOException { - InMemoryTaskManager taskManager = new InMemoryTaskManager(Managers.getDefaultHistory()); + public static void main(String[] args) throws IOException, InterruptedException { + TaskManager taskManager = Managers.getDefault(); HttpTaskServer httpTaskServer = new HttpTaskServer(taskManager); + HttpClient client = HttpClient.newHttpClient(); httpTaskServer.start(); + Task task = new Task(1,"Task1", "Description", Status.NEW,LocalDateTime.of(2024, 12, 12, 12, 12), + Duration.ofMinutes(15)); + URI url = URI.create("http://localhost:8081/tasks"); + String body = getGson().toJson(task); + System.out.println(body); + HttpRequest request = HttpRequest.newBuilder().uri(url).POST(HttpRequest.BodyPublishers.ofString(body, + StandardCharsets.UTF_8)).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + System.out.println( response.statusCode()); + System.out.println(taskManager.getTasks()); + httpTaskServer.stop(); + } diff --git a/src/server/TaskHandler.java b/src/server/TaskHandler.java index bd9d583..a846de8 100644 --- a/src/server/TaskHandler.java +++ b/src/server/TaskHandler.java @@ -101,11 +101,11 @@ private void handlePost(HttpExchange exchange) throws IOException { } if (Pattern.matches("^/tasks/\\d+$", path)) { try { - String taskId = path.replaceFirst("/task", ""); + String taskId = path.replaceFirst("/task/", ""); int id = parsePathID(taskId); if (id != -1) { InputStream inputStream = exchange.getRequestBody(); - String task = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + String task = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); Task task1 = gson.fromJson(task, Task.class); taskManager.updateTask(task1); sendAdd(exchange, "Задача обновлена"); diff --git a/src/task/Task.java b/src/task/Task.java index f9f3544..dd2e656 100644 --- a/src/task/Task.java +++ b/src/task/Task.java @@ -4,7 +4,6 @@ import java.time.Duration; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.Objects; public class Task { @@ -15,7 +14,7 @@ public class Task { private TaskType type; private LocalDateTime startTime; private Duration duration; - private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm"); + public Task(String name, String description) { this.name = name; @@ -131,7 +130,7 @@ public Status getStatus() { @Override public String toString() { - return "ModelTask.Task{" + + return "{" + "id=" + getId() + ", name='" + getName() + '\'' + ", description='" + getDescription() + '\'' + diff --git a/test/manager/HttpTaskServerTest.java b/test/manager/HttpTaskServerTest.java new file mode 100644 index 0000000..1a0738a --- /dev/null +++ b/test/manager/HttpTaskServerTest.java @@ -0,0 +1,78 @@ +package manager; + +import com.google.gson.Gson; +import exception.IntersectionException; +import exception.NotFoundException; + +import org.junit.jupiter.api.*; +import server.HttpTaskServer; + +import task.Status; + +import task.Task; + +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.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.LocalDateTime; + + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class HttpTaskServerTest { + Gson gson = HttpTaskServer.getGson(); + TaskManager taskManager; + HttpTaskServer taskServer; + HttpClient client = HttpClient.newHttpClient(); + + + @BeforeEach + void beforEach() throws IOException { + taskManager = Managers.getDefault(); + taskServer = new HttpTaskServer(taskManager); + taskServer.start(); + } + + @AfterEach + void afterEach() { + taskServer.stop(); + } + + @Test + public void shouldCreateTask() throws IOException, NotFoundException, InterruptedException { + + Task task = new Task(1, "Task1", "Description", Status.NEW, LocalDateTime.of(2024, 12, 12, 12, 12), + Duration.ofMinutes(15)); + URI url = URI.create("http://localhost:8081/tasks"); + String body = gson.toJson(task); + HttpRequest request = HttpRequest.newBuilder().uri(url).POST(HttpRequest.BodyPublishers.ofString(body, + StandardCharsets.UTF_8)).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode(), "Код ответа не совпадает"); + assertEquals(task, taskManager.getTask(task.getId()), "Задачи не совпадают"); + + } + + + @Test + public void shouldCorrectlyReturnListOfTasks() throws IOException, InterruptedException, IntersectionException { + Task createdTask = new Task("Task", "Description", Status.NEW, + LocalDateTime.of(2024, 12, 12, 12, 12), Duration.ofMinutes(15)); + Task createdTask2 = new Task("Task", "Description", Status.NEW, + LocalDateTime.of(2025, 12, 12, 12, 12), Duration.ofMinutes(15)); + URI url = URI.create("http://localhost:8081/tasks"); + taskManager.createTask(createdTask); + taskManager.createTask(createdTask2); + String expectedResponse = gson.toJson(taskManager.getTasks()); + HttpRequest request = HttpRequest.newBuilder().uri(url).GET().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + assertEquals(expectedResponse, response.body()); + } + + +} From 9aa31b3dc78da1803d8ae7545f9c1a16ade7730f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BB=D0=B0=D0=B2=D0=B0?= Date: Sat, 21 Dec 2024 18:48:08 +0400 Subject: [PATCH 5/5] =?UTF-8?q?=D0=92=D1=82=D0=BE=D1=80=D0=B0=D1=8F=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=A2=D0=97=209=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=BD=D1=82=D0=B0.=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D1=81=D0=BE=D0=B7?= =?UTF-8?q?=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2.=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D0=B0=D0=B2=D1=82?= =?UTF-8?q?=D0=BE=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/server/HttpTaskServer.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/server/HttpTaskServer.java b/src/server/HttpTaskServer.java index d8ebe2b..dccb225 100644 --- a/src/server/HttpTaskServer.java +++ b/src/server/HttpTaskServer.java @@ -26,7 +26,6 @@ public class HttpTaskServer { private TaskManager taskManager; private Gson gson; - public static Gson getGson() { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.serializeNulls(); @@ -62,7 +61,7 @@ public static void main(String[] args) throws IOException, InterruptedException HttpTaskServer httpTaskServer = new HttpTaskServer(taskManager); HttpClient client = HttpClient.newHttpClient(); httpTaskServer.start(); - Task task = new Task(1,"Task1", "Description", Status.NEW,LocalDateTime.of(2024, 12, 12, 12, 12), + Task task = new Task(1, "Task1", "Description", Status.NEW, LocalDateTime.of(2024, 12, 12, 12, 12), Duration.ofMinutes(15)); URI url = URI.create("http://localhost:8081/tasks"); String body = getGson().toJson(task); @@ -70,12 +69,11 @@ public static void main(String[] args) throws IOException, InterruptedException HttpRequest request = HttpRequest.newBuilder().uri(url).POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8)).build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - System.out.println( response.statusCode()); + System.out.println(response.statusCode()); System.out.println(taskManager.getTasks()); httpTaskServer.stop(); - } }