Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
21b0505
Реализован HistoryManager с двусвязным списком
Darya346 Oct 7, 2025
5a78293
Исправлены ошибки Checkstyle в классе Subtask
Darya346 Oct 7, 2025
aae9e83
Исправлены ошибки Checkstyle: добавлены пустые строки между методами
Darya346 Oct 7, 2025
bda5077
Исправлены ошибки Checkstyle: форматирование фигурных скобок в услови…
Darya346 Oct 7, 2025
77008b5
Исправлены все ошибки Checkstyle в InMemoryTaskManager
Darya346 Oct 7, 2025
4fe829f
Исправлены ошибки в тестах
Darya346 Oct 7, 2025
4a2d137
Исправлены все ошибки в тестаъх
Darya346 Oct 7, 2025
4a7467c
Исправление тестов
Darya346 Oct 7, 2025
212dfb1
Исправление тестов
Darya346 Oct 7, 2025
b9f95fb
Исправление последних тестов с эпиками
Darya346 Oct 7, 2025
9a06217
исправлены длинные названия методов
Darya346 Oct 8, 2025
f840bb5
feat: реализация FileBackedTaskManager с сохранением в файл
Darya346 Oct 22, 2025
5df0d2e
Исправления FileBackedTaskManager
Darya346 Oct 22, 2025
a8eafb9
Исправления: более осмысленные переменные и String.format
Darya346 Oct 22, 2025
d9a3705
feat: добавление отслеживания времени, приоритизации и проверки перес…
Darya346 Nov 6, 2025
53b15b2
feat:Исправлено форматирование под checkstyle
Darya346 Nov 6, 2025
cfda499
Заменены System.out.println на String.format в FileBackedTaskManager
Darya346 Nov 7, 2025
9dec21f
feat: implement HTTP API for task manager
Darya346 Nov 20, 2025
0701bd1
feat: update HTTP API implementation
Darya346 Nov 20, 2025
4a8b411
Исправлены названия переменных
Darya346 Nov 21, 2025
611c754
refactor: use String.format consistently for all string formatting
Darya346 Nov 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 2 additions & 21 deletions java-kanban.iml
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$" dumb="true">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library" scope="TEST">
<library name="JUnit5.8.1">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/junit-jupiter-5.8.1.jar!/" />
<root url="jar://$MODULE_DIR$/lib/junit-jupiter-api-5.8.1.jar!/" />
<root url="jar://$MODULE_DIR$/lib/opentest4j-1.2.0.jar!/" />
<root url="jar://$MODULE_DIR$/lib/junit-platform-commons-1.8.1.jar!/" />
<root url="jar://$MODULE_DIR$/lib/apiguardian-api-1.1.2.jar!/" />
<root url="jar://$MODULE_DIR$/lib/junit-jupiter-params-5.8.1.jar!/" />
<root url="jar://$MODULE_DIR$/lib/junit-jupiter-engine-5.8.1.jar!/" />
<root url="jar://$MODULE_DIR$/lib/junit-platform-engine-1.8.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>
50 changes: 50 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>ru.yandex.practicum</groupId>
<artifactId>java-kanban</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</build>
</project>
62 changes: 62 additions & 0 deletions src/http/BaseHttpHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package http;

import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class BaseHttpHandler {

protected void sendText(HttpExchange exchange, String text) throws IOException {
byte[] response = text.getBytes(StandardCharsets.UTF_8);
exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8");
exchange.sendResponseHeaders(200, response.length);
exchange.getResponseBody().write(response);
exchange.close();
}

protected void sendSuccess(HttpExchange exchange) throws IOException {
exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8");
exchange.sendResponseHeaders(201, -1);
exchange.close();
}

protected void sendNotFound(HttpExchange exchange) throws IOException {
String response = String.format("{\"error\": \"%s\"}", "Объект не найден");
byte[] bytes = response.getBytes(StandardCharsets.UTF_8);
exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8");
exchange.sendResponseHeaders(404, bytes.length);
exchange.getResponseBody().write(bytes);
exchange.close();
}

protected void sendHasInteractions(HttpExchange exchange) throws IOException {
String response = String.format("{\"error\": \"%s\"}", "Задача пересекается с существующими");
byte[] bytes = response.getBytes(StandardCharsets.UTF_8);
exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8");
exchange.sendResponseHeaders(406, bytes.length);
exchange.getResponseBody().write(bytes);
exchange.close();
}

protected void sendInternalError(HttpExchange exchange) throws IOException {
String response = String.format("{\"error\": \"%s\"}", "Внутренняя ошибка сервера");
byte[] bytes = response.getBytes(StandardCharsets.UTF_8);
exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8");
exchange.sendResponseHeaders(500, bytes.length);
exchange.getResponseBody().write(bytes);
exchange.close();
}

protected void sendBadRequest(HttpExchange exchange, String message) throws IOException {
String response = String.format("{\"error\": \"%s\"}", message);
byte[] bytes = response.getBytes(StandardCharsets.UTF_8);
exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8");
exchange.sendResponseHeaders(400, bytes.length);
exchange.getResponseBody().write(bytes);
exchange.close();
}

protected String readRequestBody(HttpExchange exchange) throws IOException {
return new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
}
}
116 changes: 116 additions & 0 deletions src/http/EpicsHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package http;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import manager.TaskManager;
import model.Epic;
import model.Subtask;
import java.io.IOException;
import java.util.List;

public class EpicsHandler extends BaseHttpHandler implements HttpHandler {
private final TaskManager taskManager;

public EpicsHandler(TaskManager taskManager) {
this.taskManager = taskManager;
}

@Override
public void handle(HttpExchange exchange) throws IOException {
try {
String method = exchange.getRequestMethod();
String path = exchange.getRequestURI().getPath();

switch (method) {
case "GET":
handleGet(exchange, path);
break;
case "POST":
handlePost(exchange);
break;
case "DELETE":
handleDelete(exchange, path);
break;
default:
sendBadRequest(exchange, "Метод не поддерживается");
}
} catch (Exception e) {
sendInternalError(exchange);
}
}

private void handleGet(HttpExchange exchange, String path) throws IOException {
if (path.equals("/epics")) {
List<Epic> epics = taskManager.getAllEpics();
String response = JsonConverter.epicsToJson(epics);
sendText(exchange, response);
} else if (path.matches("/epics/\\d+")) {
String[] pathParts = path.split("/");
int id = Integer.parseInt(pathParts[2]);

Epic epic = taskManager.getEpicById(id);
if (epic != null) {
String response = JsonConverter.epicToJson(epic);
sendText(exchange, response);
} else {
sendNotFound(exchange);
}
} else if (path.matches("/epics/\\d+/subtasks")) {
String[] pathParts = path.split("/");
int epicId = Integer.parseInt(pathParts[2]);

Epic epic = taskManager.getEpicById(epicId);
if (epic != null) {
List<Subtask> subtasks = taskManager.getSubtasksByEpicId(epicId);
String response = JsonConverter.subtasksToJson(subtasks);
sendText(exchange, response);
} else {
sendNotFound(exchange);
}
} else {
sendNotFound(exchange);
}
}

private void handlePost(HttpExchange exchange) throws IOException {
String body = readRequestBody(exchange);
Epic epic = JsonConverter.epicFromJson(body);

if (epic == null) {
sendBadRequest(exchange, "Неверный формат эпика");
return;
}

if (epic.getId() == 0) {
Epic created = taskManager.createEpic(epic);
if (created != null) {
sendSuccess(exchange);
} else {
sendInternalError(exchange);
}
} else {
taskManager.updateEpic(epic);
sendSuccess(exchange);
}
}

private void handleDelete(HttpExchange exchange, String path) throws IOException {
if (path.equals("/epics")) {
taskManager.deleteAllEpics();
sendSuccess(exchange);
} else if (path.matches("/epics/\\d+")) {
String[] pathParts = path.split("/");
int id = Integer.parseInt(pathParts[2]);

Epic epic = taskManager.getEpicById(id);
if (epic != null) {
taskManager.deleteEpicById(id);
sendSuccess(exchange);
} else {
sendNotFound(exchange);
}
} else {
sendNotFound(exchange);
}
}
}
31 changes: 31 additions & 0 deletions src/http/HistoryHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package http;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import manager.TaskManager;
import model.Task;
import java.io.IOException;
import java.util.List;

public class HistoryHandler extends BaseHttpHandler implements HttpHandler {
private final TaskManager taskManager;

public HistoryHandler(TaskManager taskManager) {
this.taskManager = taskManager;
}

@Override
public void handle(HttpExchange exchange) throws IOException {
try {
if ("GET".equals(exchange.getRequestMethod())) {
List<Task> history = taskManager.getHistory();
String response = JsonConverter.tasksToJson(history);
sendText(exchange, response);
} else {
sendBadRequest(exchange, "Метод не поддерживается");
}
} catch (Exception e) {
sendInternalError(exchange);
}
}
}
Loading