diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..6fea68f
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/files/Task.txt b/files/Task.txt
index 24a570a..4e38695 100644
--- a/files/Task.txt
+++ b/files/Task.txt
@@ -1,5 +1,4 @@
id,type,name,status,description,class,epicId,startTime,duration,endTime
-1,TASK,Task001,NEW,Description,Task,Null,2024-02-02T11:00,60,2024-02-02T12:00
-2,EPIC,Epic001,NEW,Description,Epic,2,2025-01-01T10:00,140,2025-01-01T12:30
-3,SUBTASK,Subtask001,NEW,Description,Subtask,2,2025-01-01T10:00,70,2025-01-01T11:10
-4,SUBTASK,Subtask002,NEW,Description,Subtask,2,2025-01-01T11:20,70,2025-01-01T12:30
+1,TASK,Task001,NEW,Description,Task,Null,Null,Null,Null
+2,EPIC,Epic001,NEW,Description,Epic,2,Null,Null,Null
+3,SUBTASK,Subtask001,NEW,Description,Subtask,2,Null,Null,Null
diff --git a/java-kanban.iml b/java-kanban.iml
index 66c15d2..595dea8 100644
--- a/java-kanban.iml
+++ b/java-kanban.iml
@@ -24,5 +24,14 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/http/HttpTaskServer.java b/src/http/HttpTaskServer.java
new file mode 100644
index 0000000..6cdb7c5
--- /dev/null
+++ b/src/http/HttpTaskServer.java
@@ -0,0 +1,68 @@
+package http;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.sun.net.httpserver.HttpServer;
+import http.adapters.DurationAdapter;
+import http.adapters.LocalDateTimeAdapter;
+import http.handlers.*;
+import managers.InMemoryTaskManager;
+import managers.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 kanbanServer;
+ private final TaskManager manager;
+
+
+ public HttpTaskServer(TaskManager manager) throws IOException {
+ this.manager = manager;
+
+ kanbanServer = HttpServer.create(new InetSocketAddress(PORT), 0);
+ kanbanServer.createContext("/tasks", new TaskHandler(manager));
+ kanbanServer.createContext("/subtasks", new SubtaskHandler(manager));
+ kanbanServer.createContext("/epics", new EpicHandler(manager));
+ kanbanServer.createContext("/history", new HistoryHandler(manager));
+ kanbanServer.createContext("/prioritized", new PrioritizedHandler(manager));
+ }
+
+ public static Gson getGson() {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter());
+ gsonBuilder.registerTypeAdapter(Duration.class, new DurationAdapter());
+ return gsonBuilder.create();
+ }
+
+ public void start() {
+ kanbanServer.start();
+ System.out.println("HTTP-сервер запущен на " + PORT + " порту!");
+ }
+
+ public void stop() {
+ kanbanServer.stop(3);
+ }
+
+ public static void main(String[] args) {
+ try {
+ TaskManager manager = new InMemoryTaskManager();
+ HttpTaskServer server = new HttpTaskServer(manager);
+ server.start();
+
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ System.out.println("\nОстанавливаем сервер...");
+ server.stop();
+ }));
+
+ System.out.println("Нажмите Ctrl+C для остановки сервера");
+
+ } catch (IOException e) {
+ System.err.println("Не удалось запустить сервер: " + e.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/http/adapters/DurationAdapter.java b/src/http/adapters/DurationAdapter.java
new file mode 100644
index 0000000..002c1d9
--- /dev/null
+++ b/src/http/adapters/DurationAdapter.java
@@ -0,0 +1,28 @@
+package http.adapters;
+
+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.nullValue();
+ } else {
+ jsonWriter.value(duration.toMinutes());
+ }
+ }
+
+ @Override
+ public Duration read(JsonReader jsonReader) throws IOException {
+ if (jsonReader.peek() == com.google.gson.stream.JsonToken.NULL) {
+ jsonReader.nextNull();
+ return null;
+ }
+ return Duration.ofMinutes(jsonReader.nextInt());
+ }
+}
\ No newline at end of file
diff --git a/src/http/adapters/LocalDateTimeAdapter.java b/src/http/adapters/LocalDateTimeAdapter.java
new file mode 100644
index 0000000..b0d3e5e
--- /dev/null
+++ b/src/http/adapters/LocalDateTimeAdapter.java
@@ -0,0 +1,29 @@
+package http.adapters;
+
+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 {
+ @Override
+ public void write(JsonWriter jsonWriter, LocalDateTime localDate) throws IOException {
+ if (localDate == null) {
+ jsonWriter.nullValue();
+ } else {
+ jsonWriter.value(localDate.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
+ }
+ }
+
+ @Override
+ public LocalDateTime read(JsonReader jsonReader) throws IOException {
+ if (jsonReader.peek() == com.google.gson.stream.JsonToken.NULL) {
+ jsonReader.nextNull();
+ return null;
+ }
+ return LocalDateTime.parse(jsonReader.nextString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME);
+ }
+}
\ No newline at end of file
diff --git a/src/http/handlers/BaseHttpHandler.java b/src/http/handlers/BaseHttpHandler.java
new file mode 100644
index 0000000..ee9b4b0
--- /dev/null
+++ b/src/http/handlers/BaseHttpHandler.java
@@ -0,0 +1,51 @@
+package http.handlers;
+
+import com.sun.net.httpserver.HttpExchange;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
+public class BaseHttpHandler {
+
+ protected void sendText(HttpExchange h, String responseString, int responseCode) throws IOException {
+ byte[] resp = responseString.getBytes(StandardCharsets.UTF_8);
+ h.getResponseHeaders().set("Content-Type", "application/json;charset=utf-8");
+ h.sendResponseHeaders(responseCode, resp.length);
+ try (OutputStream os = h.getResponseBody()) {
+ os.write(resp);
+ }
+ }
+
+ protected void sendNotFound(HttpExchange h) throws IOException {
+ byte[] resp = "Not Found".getBytes(StandardCharsets.UTF_8);
+ h.getResponseHeaders().add("Content-Type", "text/plain");
+ h.sendResponseHeaders(404, resp.length);
+ h.getResponseBody().write(resp);
+ h.close();
+ }
+
+ protected void sendHasOverlaps(HttpExchange h) throws IOException {
+ byte[] resp = "Not Acceptable".getBytes(StandardCharsets.UTF_8);
+ h.getResponseHeaders().add("Content-Type", "text/plain");
+ h.sendResponseHeaders(406, resp.length);
+ h.getResponseBody().write(resp);
+ h.close();
+ }
+
+ protected Integer getId(String path) {
+ try {
+ String[] parts = path.split("/");
+ if (parts.length >= 3) {
+ return Integer.parseInt(parts[2]);
+ }
+ } catch (Exception e) {
+ System.out.println("Cannot get ID from path: " + path);
+ }
+ return null;
+ }
+
+ protected String readText(HttpExchange h) throws IOException {
+ return new String(h.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
+ }
+}
\ No newline at end of file
diff --git a/src/http/handlers/EpicHandler.java b/src/http/handlers/EpicHandler.java
new file mode 100644
index 0000000..9e8d14d
--- /dev/null
+++ b/src/http/handlers/EpicHandler.java
@@ -0,0 +1,96 @@
+package http.handlers;
+
+import com.google.gson.Gson;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import exceptions.TaskValidationException;
+import http.HttpTaskServer;
+import managers.TaskManager;
+import tasks.Epic;
+import tasks.Subtask;
+
+import java.io.IOException;
+import java.util.List;
+
+public class EpicHandler extends BaseHttpHandler implements HttpHandler {
+
+ private Gson gson;
+ private TaskManager taskManager;
+
+ public EpicHandler(TaskManager taskManager) {
+ this.taskManager = taskManager;
+ this.gson = HttpTaskServer.getGson();
+ }
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ try {
+ String path = exchange.getRequestURI().getPath();
+ Integer idFromPath = getId(path);
+ String method = exchange.getRequestMethod();
+ System.out.println("Request: " + method + " " + path + " (id: " + idFromPath + ")");
+ switch (method) {
+ case "GET": {
+ if (idFromPath == null) {
+ List epicList = taskManager.getEpicList();
+ String response = gson.toJson(epicList);
+ System.out.println("Получили список эпиков");
+ sendText(exchange, response, 200);
+ break;
+ } else if ((path.split("/").length > 3) && "subtasks".equals(path.split("/")[3])) {
+ Epic epic = taskManager.getEpicForId(idFromPath);
+ if (epic != null) {
+ List epicSubList = taskManager.getEpicSubtask(idFromPath);
+ String response = gson.toJson(epicSubList);
+ System.out.println("Получили список подзадач эпика");
+ sendText(exchange, response, 200);
+ break;
+ } else {
+ sendNotFound(exchange);
+ }
+ } else {
+ Epic epic = taskManager.getEpicForId(idFromPath);
+ if (epic != null) {
+ String response = gson.toJson(epic);
+ System.out.println("Получили эпик по id " + idFromPath);
+ sendText(exchange, response, 200);
+ } else {
+ sendNotFound(exchange);
+ }
+ break;
+ }
+ }
+ case "POST": {
+ String body = readText(exchange);
+ Epic epic = gson.fromJson(body, Epic.class);
+ try {
+ taskManager.addEpic(epic);
+ int epicId = epic.getId();
+ System.out.println("Создали эпик с id: " + epicId);
+ String response = gson.toJson(epic);
+ sendText(exchange, response, 201);
+ } catch (TaskValidationException ex) {
+ sendHasOverlaps(exchange);
+ }
+ break;
+ }
+ case "DELETE": {
+ taskManager.removeEpicForId(idFromPath);
+ System.out.println("Удалили эпик по id " + idFromPath);
+ exchange.sendResponseHeaders(200, 0);
+ exchange.close();
+ break;
+ }
+ default: {
+ System.out.println("/epics получил: " + exchange.getRequestMethod());
+ exchange.sendResponseHeaders(405, 0);
+ exchange.close();
+ break;
+ }
+ }
+ } catch (Exception e) {
+ System.err.println("Ошибка обработки: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/http/handlers/HistoryHandler.java b/src/http/handlers/HistoryHandler.java
new file mode 100644
index 0000000..a8909f3
--- /dev/null
+++ b/src/http/handlers/HistoryHandler.java
@@ -0,0 +1,44 @@
+package http.handlers;
+
+import com.google.gson.Gson;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import http.HttpTaskServer;
+import managers.TaskManager;
+import tasks.Task;
+
+import java.io.IOException;
+import java.util.List;
+
+public class HistoryHandler extends BaseHttpHandler implements HttpHandler {
+
+ private Gson gson;
+ private TaskManager taskManager;
+
+ public HistoryHandler(TaskManager taskManager) {
+ this.taskManager = taskManager;
+ this.gson = HttpTaskServer.getGson();
+ }
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ String path = exchange.getRequestURI().getPath();
+ String method = exchange.getRequestMethod();
+ System.out.println("Request: " + method + " " + path);
+ switch (method) {
+ case "GET": {
+ List history = taskManager.getHistory();
+ String response = gson.toJson(history);
+ System.out.println("Получили историю");
+ sendText(exchange, response, 200);
+ return;
+ }
+ default: {
+ System.out.println("/history получил: " + exchange.getRequestMethod());
+ exchange.sendResponseHeaders(405, 0);
+ exchange.close();
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/http/handlers/PrioritizedHandler.java b/src/http/handlers/PrioritizedHandler.java
new file mode 100644
index 0000000..de10ba1
--- /dev/null
+++ b/src/http/handlers/PrioritizedHandler.java
@@ -0,0 +1,44 @@
+package http.handlers;
+
+import com.google.gson.Gson;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import http.HttpTaskServer;
+import managers.TaskManager;
+import tasks.Task;
+
+import java.io.IOException;
+import java.util.Set;
+
+public class PrioritizedHandler extends BaseHttpHandler implements HttpHandler {
+
+ private Gson gson;
+ private TaskManager taskManager;
+
+ public PrioritizedHandler(TaskManager taskManager) {
+ this.taskManager = taskManager;
+ this.gson = HttpTaskServer.getGson();
+ }
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ String path = exchange.getRequestURI().getPath();
+ String method = exchange.getRequestMethod();
+ System.out.println("Request: " + method + " " + path);
+ switch (method) {
+ case "GET": {
+ Set history = taskManager.getprioritizedTasks();
+ String response = gson.toJson(history);
+ System.out.println("Получили приоритетный список");
+ sendText(exchange, response, 200);
+ return;
+ }
+ default: {
+ System.out.println("/prioritized получил: " + exchange.getRequestMethod());
+ exchange.sendResponseHeaders(405, 0);
+ exchange.close();
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/http/handlers/SubtaskHandler.java b/src/http/handlers/SubtaskHandler.java
new file mode 100644
index 0000000..0ff1a90
--- /dev/null
+++ b/src/http/handlers/SubtaskHandler.java
@@ -0,0 +1,83 @@
+package http.handlers;
+
+import com.google.gson.Gson;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import exceptions.TaskValidationException;
+import http.HttpTaskServer;
+import managers.TaskManager;
+import tasks.Subtask;
+
+import java.io.IOException;
+import java.util.List;
+
+public class SubtaskHandler extends BaseHttpHandler implements HttpHandler {
+
+ private Gson gson;
+ private TaskManager taskManager;
+
+ public SubtaskHandler(TaskManager taskManager) {
+ this.taskManager = taskManager;
+ this.gson = HttpTaskServer.getGson();
+ }
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ try {
+ String path = exchange.getRequestURI().getPath();
+ Integer idFromPath = getId(path);
+ String method = exchange.getRequestMethod();
+ System.out.println("Request: " + method + " " + path + " (id: " + idFromPath + ")");
+ switch (method) {
+ case "GET": {
+ if (idFromPath == null) {
+ List subList = taskManager.getAllSubtask();
+ String response = gson.toJson(subList);
+ System.out.println("Получили список подзадач");
+ sendText(exchange, response, 200);
+ break;
+ }
+ Subtask subtask = taskManager.getSubtaskForId(idFromPath);
+ if (subtask != null) {
+ String response = gson.toJson(subtask);
+ System.out.println("Получили подзадачу по id " + idFromPath);
+ sendText(exchange, response, 200);
+ } else {
+ sendNotFound(exchange);
+ }
+ break;
+ }
+ case "POST": {
+ String body = readText(exchange);
+ Subtask subtask = gson.fromJson(body, Subtask.class);
+ try {
+ taskManager.addSubtask(subtask);
+ int addId = subtask.getId();
+ System.out.println("Создали подзадачу с id: " + addId);
+ String response = gson.toJson(subtask);
+ sendText(exchange, response, 201);
+ } catch (TaskValidationException ex) {
+ sendHasOverlaps(exchange);
+ }
+ break;
+ }
+ case "DELETE": {
+ taskManager.removeSubtaskForId(idFromPath);
+ System.out.println("Удалили подзадачу по id " + idFromPath);
+ exchange.sendResponseHeaders(200, 0);
+ exchange.close();
+ break;
+ }
+ default: {
+ System.out.println("/subtasks получил: " + exchange.getRequestMethod());
+ exchange.sendResponseHeaders(405, 0);
+ exchange.close();
+ break;
+ }
+ }
+ } catch (Exception e) {
+ System.err.println("Ошибка обработки: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/http/handlers/TaskHandler.java b/src/http/handlers/TaskHandler.java
new file mode 100644
index 0000000..840da95
--- /dev/null
+++ b/src/http/handlers/TaskHandler.java
@@ -0,0 +1,90 @@
+package http.handlers;
+
+import com.google.gson.Gson;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import exceptions.TaskValidationException;
+import http.HttpTaskServer;
+import managers.TaskManager;
+import tasks.Task;
+
+import java.io.IOException;
+import java.util.List;
+
+public class TaskHandler extends BaseHttpHandler implements HttpHandler {
+
+ private Gson gson;
+ private TaskManager taskManager;
+
+ public TaskHandler(TaskManager taskManager) {
+ this.taskManager = taskManager;
+ this.gson = HttpTaskServer.getGson();
+ }
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ try {
+ String path = exchange.getRequestURI().getPath();
+ Integer idFromPath = getId(path);
+ String method = exchange.getRequestMethod();
+ System.out.println("Request: " + method + " " + path + " (id: " + idFromPath + ")");
+ switch (method) {
+ case "GET": {
+ if (idFromPath == null) {
+ List tList = taskManager.getTaskList();
+ String response = gson.toJson(tList);
+ System.out.println("Получили список задач");
+ sendText(exchange, response, 200);
+ break;
+ }
+ Task task = taskManager.getTaskForId(idFromPath);
+ if (task != null) {
+ String response = gson.toJson(task);
+ System.out.println("Получили задачу по id " + idFromPath);
+ sendText(exchange, response, 200);
+ } else {
+ sendNotFound(exchange);
+ }
+ break;
+ }
+ case "POST": {
+ String body = readText(exchange);
+ Task task = gson.fromJson(body, Task.class);
+ int taskId = task.getId();
+ if (taskId > 0) {
+ taskManager.updateTask(task);
+ System.out.println("Обновили задачу с id: " + taskId);
+ exchange.sendResponseHeaders(200, -1);
+ } else {
+ try {
+ taskManager.addTask(task);
+ int addId = task.getId();
+ System.out.println("Создали задачу с id: " + addId);
+ String response = gson.toJson(task);
+ sendText(exchange, response, 201);
+ } catch (TaskValidationException ex) {
+ sendHasOverlaps(exchange);
+ }
+ }
+ break;
+ }
+ case "DELETE": {
+ taskManager.removeTaskForId(idFromPath);
+ System.out.println("Удалили задачу с id " + idFromPath);
+ exchange.sendResponseHeaders(200, 0);
+ exchange.close();
+ break;
+ }
+ default: {
+ System.out.println("/tasks получил: " + exchange.getRequestMethod());
+ exchange.sendResponseHeaders(405, 0);
+ exchange.close();
+ break;
+ }
+ }
+ } catch (Exception e) {
+ System.err.println("Ошибка обработки: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/managers/InMemoryTaskManager.java b/src/managers/InMemoryTaskManager.java
index bf4470a..1f33b7b 100644
--- a/src/managers/InMemoryTaskManager.java
+++ b/src/managers/InMemoryTaskManager.java
@@ -99,8 +99,8 @@ public void deleteEpicSubtask(Epic epic) { //удаление подзадача
@Override
public void removeTaskForId(Integer id) {
- taskList.remove(id);
delete(taskList.get(id));
+ taskList.remove(id);
historyManager.remove(id);
}
@@ -125,8 +125,8 @@ public void removeEpicForId(Integer id) {
@Override
public void removeSubtaskForId(Integer id) {
int epicId = subtaskList.get(id).getEpicId();
- subtaskList.remove(id);
delete(subtaskList.get(id));
+ subtaskList.remove(id);
checkStatus(epicList.get(epicId));//проверяем статус эпика из которого удалили подзадачу
historyManager.remove(id);
updateEpic(epicList.get(epicId));
@@ -154,8 +154,8 @@ public Subtask getSubtaskForId(Integer id) {
public void addTask(Task task) {
idCounter++;
task.setId(idCounter);
- taskList.put(task.getId(), task);
add(task);
+ taskList.put(task.getId(), task);
}
@Override
@@ -171,8 +171,8 @@ public void addSubtask(Subtask subtask) {
idCounter++;
subtask.setId(idCounter);
int currentEpicId = subtask.getEpicId();
- subtaskList.put(subtask.getId(), subtask);
add(subtask);
+ subtaskList.put(subtask.getId(), subtask);
updateEpic(epicList.get(currentEpicId));
}
@@ -302,4 +302,8 @@ private void add(Task newTask) {
private void delete(Task task) {
prioritizedTasks.remove(task);
}
+
+ public Set getprioritizedTasks() {
+ return prioritizedTasks;
+ }
}
\ No newline at end of file
diff --git a/src/managers/TaskManager.java b/src/managers/TaskManager.java
index 48f0b63..e73b0b5 100644
--- a/src/managers/TaskManager.java
+++ b/src/managers/TaskManager.java
@@ -4,6 +4,7 @@
import tasks.Subtask;
import tasks.Task;
import java.util.List;
+import java.util.Set;
public interface TaskManager {
List getTaskList();
@@ -45,4 +46,8 @@ public interface TaskManager {
void updateSubtask(Subtask subtask);
void updateEpic(Epic epic);
+
+ List getHistory();
+
+ Set getprioritizedTasks();
}
diff --git a/src/tasks/Epic.java b/src/tasks/Epic.java
index f4ac60e..fc7fa4f 100644
--- a/src/tasks/Epic.java
+++ b/src/tasks/Epic.java
@@ -1,5 +1,6 @@
package tasks;
+import java.time.Duration;
import java.time.LocalDateTime;
public class Epic extends Task {
@@ -9,6 +10,10 @@ public Epic(String title, String description, TaskStatus status) {
super(title, description, status);
}
+ public Epic(String title, String description, TaskStatus status, Duration duration, LocalDateTime startTime) {
+ super(title, description, status, duration, startTime);
+ }
+
@Override
public TaskType getType() {
return TaskType.EPIC;
diff --git a/test/httpTest/HttpHistoryTest.java b/test/httpTest/HttpHistoryTest.java
new file mode 100644
index 0000000..d442d20
--- /dev/null
+++ b/test/httpTest/HttpHistoryTest.java
@@ -0,0 +1,74 @@
+package httpTest;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import http.HttpTaskServer;
+import managers.InMemoryTaskManager;
+import managers.TaskManager;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import tasks.Task;
+import tasks.TaskStatus;
+
+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.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class HttpHistoryTest {
+
+ TaskManager manager = new InMemoryTaskManager();
+ HttpTaskServer taskServer = new HttpTaskServer(manager);
+ Gson gson = HttpTaskServer.getGson();
+
+ public HttpHistoryTest() throws IOException {
+ }
+
+ @BeforeEach
+ public void setUp() {
+ manager.deleteTaskList();
+ manager.deleteAllSubtask();
+ manager.deleteAllEpic();
+ taskServer.start();
+ }
+
+ @AfterEach
+ public void shutDown() {
+ taskServer.stop();
+ }
+
+ @Test
+ public void testGetHistory() throws IOException, InterruptedException {
+ Task task1 = new Task("Test 1", "Testing task 1",
+ TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.of(2025, 1, 1,
+ 10, 0));
+ manager.addTask(task1);
+ Task task2 = new Task("Test 2", "Testing task 2",
+ TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addTask(task2);
+ manager.getTaskForId(task1.getId());
+ manager.getTaskForId(task2.getId());
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/history");
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).GET().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ List tasksFromManager = gson.fromJson(response.body(), new TypeToken>(){}.getType());
+
+ assertNotNull(tasksFromManager, "Задачи не возвращаются");
+ assertEquals(2, tasksFromManager.size(), "Некорректное количество задач");
+ }
+}
\ No newline at end of file
diff --git a/test/httpTest/HttpPrioritizedTest.java b/test/httpTest/HttpPrioritizedTest.java
new file mode 100644
index 0000000..960f9e8
--- /dev/null
+++ b/test/httpTest/HttpPrioritizedTest.java
@@ -0,0 +1,70 @@
+package httpTest;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import http.HttpTaskServer;
+import managers.InMemoryTaskManager;
+import managers.TaskManager;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import tasks.Task;
+import tasks.TaskStatus;
+
+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.Set;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class HttpPrioritizedTest {
+ TaskManager manager = new InMemoryTaskManager();
+ HttpTaskServer taskServer = new HttpTaskServer(manager);
+ Gson gson = HttpTaskServer.getGson();
+
+ public HttpPrioritizedTest() throws IOException {
+ }
+
+ @BeforeEach
+ public void setUp() {
+ manager.deleteTaskList();
+ manager.deleteAllSubtask();
+ manager.deleteAllEpic();
+ taskServer.start();
+ }
+
+ @AfterEach
+ public void shutDown() {
+ taskServer.stop();
+ }
+
+ @Test
+ public void testGetPrioritized() throws IOException, InterruptedException {
+ Task task1 = new Task("Test 1", "Testing task 1",
+ TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.of(2025, 1, 1,
+ 10, 0));
+ manager.addTask(task1);
+ Task task2 = new Task("Test 2", "Testing task 2",
+ TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addTask(task2);
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/prioritized");
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).GET().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ Set tasksFromManager = gson.fromJson(response.body(), new TypeToken>(){}.getType());
+
+ assertNotNull(tasksFromManager, "Задачи не возвращаются");
+ assertEquals(2, tasksFromManager.size(), "Некорректное количество задач");
+ }
+}
\ No newline at end of file
diff --git a/test/httpTest/HttpTaskManagerEpicsTest.java b/test/httpTest/HttpTaskManagerEpicsTest.java
new file mode 100644
index 0000000..c4f9868
--- /dev/null
+++ b/test/httpTest/HttpTaskManagerEpicsTest.java
@@ -0,0 +1,159 @@
+package httpTest;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import http.HttpTaskServer;
+import managers.InMemoryTaskManager;
+import managers.TaskManager;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import tasks.Epic;
+import tasks.Subtask;
+import tasks.TaskStatus;
+
+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.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class HttpTaskManagerEpicsTest {
+
+ TaskManager manager = new InMemoryTaskManager();
+ HttpTaskServer taskServer = new HttpTaskServer(manager);
+ Gson gson = HttpTaskServer.getGson();
+
+ public HttpTaskManagerEpicsTest() throws IOException {
+ }
+
+ @BeforeEach
+ public void setUp() {
+ manager.deleteTaskList();
+ manager.deleteAllSubtask();
+ manager.deleteAllEpic();
+ taskServer.start();
+ }
+
+ @AfterEach
+ public void shutDown() {
+ taskServer.stop();
+ }
+
+ @Test
+ public void testAddEpic() throws IOException, InterruptedException {
+ Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW, null, null);
+ String taskJson = gson.toJson(epic1);
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/epics");
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).POST(HttpRequest.BodyPublishers.ofString(taskJson)).build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(201, response.statusCode());
+
+ List tasksFromManager = manager.getEpicList();
+
+ assertNotNull(tasksFromManager, "Задачи не возвращаются");
+ assertEquals(1, tasksFromManager.size(), "Некорректное количество задач");
+ assertEquals("Эпик1", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи");
+ }
+
+ @Test
+ public void testGetAllEpics() throws IOException, InterruptedException {
+ Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW);
+ manager.addEpic(epic1);
+ Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW,
+ Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addSubtask(subtask);
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/epics");
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).GET().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ List tasksFromManager = gson.fromJson(response.body(), new TypeToken>(){}.getType());
+
+ assertNotNull(tasksFromManager, "Задачи не возвращаются");
+ assertEquals(1, tasksFromManager.size(), "Некорректное количество задач");
+ assertEquals("Эпик1", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи");
+ }
+
+ @Test
+ public void testGetEpicForId() throws IOException, InterruptedException {
+ Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW);
+ manager.addEpic(epic1);
+ Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW,
+ Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addSubtask(subtask);
+ int epicId = epic1.getId();
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/epics" + "/" + epicId);
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).GET().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ Epic taskFromManager = gson.fromJson(response.body(), new TypeToken() {}.getType());
+
+ assertEquals(epicId, taskFromManager.getId(), "Некорректный id");
+ assertEquals("Эпик1", taskFromManager.getTitle(), "Некорректное имя задачи");
+ }
+
+ @Test
+ public void testDeleteEpicForId() throws IOException, InterruptedException {
+ Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW);
+ manager.addEpic(epic1);
+ Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW,
+ Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addSubtask(subtask);
+ int epicId = epic1.getId();
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/epics" + "/" + epicId);
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).DELETE().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ Epic taskFromManager = manager.getEpicForId(epicId);
+
+ assertNull(taskFromManager, "Задача не удалена");
+ }
+
+ @Test
+ public void testGetEpicSubtask() throws IOException, InterruptedException {
+ Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW);
+ manager.addEpic(epic1);
+ Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW,
+ Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addSubtask(subtask);
+ int epicId = epic1.getId();
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/epics" + "/" + epicId + "/subtasks");
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).GET().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ List tasksFromManager = gson.fromJson(response.body(),
+ new TypeToken>() {}.getType());
+
+ assertEquals(1, tasksFromManager.size(), "Некорректный id");
+ }
+}
\ No newline at end of file
diff --git a/test/httpTest/HttpTaskManagerSubtasksTest.java b/test/httpTest/HttpTaskManagerSubtasksTest.java
new file mode 100644
index 0000000..8f5f23b
--- /dev/null
+++ b/test/httpTest/HttpTaskManagerSubtasksTest.java
@@ -0,0 +1,139 @@
+package httpTest;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import http.HttpTaskServer;
+import managers.InMemoryTaskManager;
+import managers.TaskManager;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import tasks.Epic;
+import tasks.Subtask;
+import tasks.TaskStatus;
+
+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.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class HttpTaskManagerSubtasksTest {
+ TaskManager manager = new InMemoryTaskManager();
+ HttpTaskServer taskServer = new HttpTaskServer(manager);
+ Gson gson = HttpTaskServer.getGson();
+
+ public HttpTaskManagerSubtasksTest() throws IOException {
+ }
+
+ @BeforeEach
+ public void setUp() {
+ manager.deleteTaskList();
+ manager.deleteAllSubtask();
+ manager.deleteAllEpic();
+ taskServer.start();
+ }
+
+ @AfterEach
+ public void shutDown() {
+ taskServer.stop();
+ }
+
+ @Test
+ public void testAddSubtask() throws IOException, InterruptedException {
+ Epic epic1 = new Epic("Эпик1", "Описание 1", TaskStatus.NEW, null, null);
+ manager.addEpic(epic1);
+ Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW,
+ Duration.ofMinutes(5), LocalDateTime.now());
+ String taskJson = gson.toJson(subtask);
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/subtasks");
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).POST(HttpRequest.BodyPublishers.ofString(taskJson)).build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(201, response.statusCode());
+
+ List tasksFromManager = manager.getAllSubtask();
+
+ assertNotNull(tasksFromManager, "Задачи не возвращаются");
+ assertEquals(1, tasksFromManager.size(), "Некорректное количество задач");
+ assertEquals("подзадача", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи");
+ }
+
+ @Test
+ public void testGetAllSubtasks() throws IOException, InterruptedException {
+ Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW);
+ manager.addEpic(epic1);
+ Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW,
+ Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addSubtask(subtask);
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/subtasks");
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).GET().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ List tasksFromManager = gson.fromJson(response.body(),
+ new TypeToken>(){}.getType());
+
+ assertNotNull(tasksFromManager, "Задачи не возвращаются");
+ assertEquals(1, tasksFromManager.size(), "Некорректное количество задач");
+ assertEquals("подзадача", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи");
+ }
+
+ @Test
+ public void testGetSubtaskForId() throws IOException, InterruptedException {
+ Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW);
+ manager.addEpic(epic1);
+ Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW,
+ Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addSubtask(subtask);
+ int subId = subtask.getId();
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/subtasks" + "/" + subId);
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).GET().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ Subtask taskFromManager = gson.fromJson(response.body(), new TypeToken() {}.getType());
+
+ assertEquals(subId, taskFromManager.getId(), "Некорректный id");
+ assertEquals("подзадача", taskFromManager.getTitle(), "Некорректное имя задачи");
+ }
+
+ @Test
+ public void testDeleteSubtaskForId() throws IOException, InterruptedException {
+ Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW);
+ manager.addEpic(epic1);
+ Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW,
+ Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addSubtask(subtask);
+ int subId = subtask.getId();
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/subtasks" + "/" + subId);
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).DELETE().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ Subtask taskFromManager = manager.getSubtaskForId(subId);
+
+ assertNull(taskFromManager, "Задача не удалена");
+ }
+}
\ No newline at end of file
diff --git a/test/httpTest/HttpTaskManagerTasksTest.java b/test/httpTest/HttpTaskManagerTasksTest.java
new file mode 100644
index 0000000..4e95bf5
--- /dev/null
+++ b/test/httpTest/HttpTaskManagerTasksTest.java
@@ -0,0 +1,130 @@
+package httpTest;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import http.HttpTaskServer;
+import managers.InMemoryTaskManager;
+import managers.TaskManager;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+import tasks.Task;
+import tasks.TaskStatus;
+
+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.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class HttpTaskManagerTasksTest {
+
+ TaskManager manager = new InMemoryTaskManager();
+ HttpTaskServer taskServer = new HttpTaskServer(manager);
+ Gson gson = HttpTaskServer.getGson();
+
+ public HttpTaskManagerTasksTest() throws IOException {
+ }
+
+ @BeforeEach
+ public void setUp() {
+ manager.deleteTaskList();
+ manager.deleteAllSubtask();
+ manager.deleteAllEpic();
+ taskServer.start();
+ }
+
+ @AfterEach
+ public void shutDown() {
+ taskServer.stop();
+ }
+
+ @Test
+ public void testAddTask() throws IOException, InterruptedException {
+ Task task = new Task("Test 1", "Testing task 1",
+ TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now());
+ String taskJson = gson.toJson(task);
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/tasks");
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).POST(HttpRequest.BodyPublishers.ofString(taskJson)).build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(201, response.statusCode());
+
+ List tasksFromManager = manager.getTaskList();
+
+ assertNotNull(tasksFromManager, "Задачи не возвращаются");
+ assertEquals(1, tasksFromManager.size(), "Некорректное количество задач");
+ assertEquals("Test 1", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи");
+ }
+
+ @Test
+ public void testGetAllTasks() throws IOException, InterruptedException {
+ Task task = new Task("Test 1", "Testing task 1",
+ TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addTask(task);
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/tasks");
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).GET().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ List tasksFromManager = gson.fromJson(response.body(), new TypeToken>(){}.getType());
+
+ assertNotNull(tasksFromManager, "Задачи не возвращаются");
+ assertEquals(1, tasksFromManager.size(), "Некорректное количество задач");
+ assertEquals("Test 1", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи");
+ }
+
+ @Test
+ public void testGetTaskForId() throws IOException, InterruptedException {
+ Task task = new Task("Test 1", "Testing task 1",
+ TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addTask(task);
+ int taskId = task.getId();
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/tasks" + "/" + taskId);
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).GET().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ Task taskFromManager = gson.fromJson(response.body(), new TypeToken() {}.getType());
+
+ assertEquals(taskId, taskFromManager.getId(), "Некорректный id");
+ assertEquals("Test 1", taskFromManager.getTitle(), "Некорректное имя задачи");
+ }
+
+ @Test
+ public void testDeleteTaskForId() throws IOException, InterruptedException {
+ Task task = new Task("Test 1", "Testing task 1",
+ TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now());
+ manager.addTask(task);
+ int taskId = task.getId();
+
+ HttpClient client = HttpClient.newHttpClient();
+ URI url = URI.create("http://localhost:8080/tasks" + "/" + taskId);
+ HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1)
+ .uri(url).DELETE().build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ assertEquals(200, response.statusCode());
+
+ Task taskFromManager = manager.getTaskForId(taskId);
+
+ assertNull(taskFromManager, "Задача не удалена");
+ }
+}
\ No newline at end of file