Skip to content
6 changes: 6 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ plugins {
id("java")
}

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(25))
}
}

group = "org.lab"
version = "1.0-SNAPSHOT"

Expand Down
150 changes: 147 additions & 3 deletions src/main/java/org/lab/Main.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,148 @@
void main() {
IO.println("Hello and welcome!");
}
package org.lab;

import java.time.LocalDate;
import java.util.stream.Collectors;

import org.lab.model.BugReport.BugReportRole;
import org.lab.model.BugReport.BugReportStatus;
import org.lab.model.MilestoneModel.MilestoneStatus;
import org.lab.model.ProjectModel.ProjectRole;
import org.lab.model.TaskModel.TaskRole;
import org.lab.model.TaskModel.TaskStatus;
import org.lab.repositories.BugReportRepo.InMemoryBugReportRepo;
import org.lab.repositories.MilestoneRepo.InMemoryMilestoneRepo;
import org.lab.repositories.ProjectRepo.InMemoryProjectRepo;
import org.lab.repositories.TaskRepo.InMemoryTaskRepo;
import org.lab.repositories.UserRepo.InMemoryUserRepo;
import org.lab.services.BugReportService;
import org.lab.services.MilestoneService;
import org.lab.services.ProjectService;
import org.lab.services.TaskService;
import org.lab.services.UserService;

public class Main {
void main() {
var userRepo = new InMemoryUserRepo();
var projectRepo = new InMemoryProjectRepo();
var milestoneRepo = new InMemoryMilestoneRepo();
var taskRepo = new InMemoryTaskRepo();
var bugReportRepo = new InMemoryBugReportRepo();

var userService = new UserService(userRepo, projectRepo, taskRepo, bugReportRepo);
var projectService = new ProjectService(userRepo, projectRepo, milestoneRepo, taskRepo, bugReportRepo);
var milestoneService = new MilestoneService(userRepo, projectRepo, milestoneRepo, taskRepo, bugReportRepo);
var taskService = new TaskService(userRepo, projectRepo, milestoneRepo, taskRepo, bugReportRepo);
var bugReportService = new BugReportService(userRepo, projectRepo, milestoneRepo, taskRepo, bugReportRepo);

var aliceManagerId = userService.registerUser("Alice Manager", "alice@example.com");
var bobDevId = userService.registerUser("Bob Dev", "bob@example.com");
var grokTesterId = userService.registerUser("Grok Tester", "grok@example.com");
var zigLeadId = userService.registerUser("Zig Lead", "zig@example.com");

var projectId = projectService.createProject("Project", aliceManagerId);
projectService.updateLead(aliceManagerId, projectId, zigLeadId);
projectService.addMember(aliceManagerId, projectId, bobDevId, ProjectRole.DEV);
projectService.addMember(aliceManagerId, projectId, grokTesterId, ProjectRole.TESTER);

projectRepo.getProjectById(projectId).ifPresent((project) -> {
IO.println("Project " + project.getId() + " team");
project.getMembers().stream().forEach((member) -> {
IO.println(member.user().name() + " " + member.role().name());
});
IO.println();
});

var milestoneStart = LocalDate.of(2025, 10, 1);
var milestoneEnd = LocalDate.of(2025, 11, 1);
var milestoneId = milestoneService.createMilestone(aliceManagerId, projectId, "MVP Release", milestoneStart,
milestoneEnd);

milestoneRepo.getMilestoneById(milestoneId).ifPresent((milestone) -> {
IO.println("Milestone " + milestoneId + " data");
IO.println(milestone.getName() + " " + milestone.getStatus().name());
IO.println();
});
milestoneService.updateMilestoneStatus(aliceManagerId, milestoneId, MilestoneStatus.ACTIVE);
milestoneRepo.getMilestoneById(milestoneId).ifPresent((milestone) -> {
IO.println("Milestone " + milestoneId + " data");
IO.println(milestone.getName() + " " + milestone.getStatus().name());
IO.println();
});

var taskId = taskService.createTask(aliceManagerId, milestoneId, "task", "task desc");
taskRepo.getTaskById(taskId).ifPresent((task) -> {
IO.println("Task " + taskId + " data");
IO.println(task.getName() + " " + task.getDescription() + " " + task.getStatus().name());
IO.println();
});

var taskStatus = taskService.getTaskStatus(taskId);
IO.println("Task status " + taskStatus.name());
IO.println();

taskRepo.getTaskById(taskId).ifPresent((task) -> {
IO.println("Task " + taskId + " members");
task.getTicketMembers().entrySet().stream().forEach((memberEntry) -> {
var membersString = memberEntry.getValue().stream().map((member) -> member.user().name())
.collect(Collectors.joining(", "));
IO.print("Role " + memberEntry.getKey().name() + ": " + membersString);
});
IO.println();
});
taskService.addMemberToTask(zigLeadId, taskId, bobDevId, TaskRole.DEV);
taskRepo.getTaskById(taskId).ifPresent((task) -> {
IO.println("Task " + taskId + " members");
task.getTicketMembers().entrySet().stream().forEach((memberEntry) -> {
var membersString = memberEntry.getValue().stream().map((member) -> member.user().name())
.collect(Collectors.joining(", "));
IO.print("Role " + memberEntry.getKey().name() + ": " + membersString);
});
IO.println();
});

taskService.updateTaskStatus(bobDevId, taskId, TaskStatus.IN_PROGESS);
taskRepo.getTaskById(taskId).ifPresent((task) -> {
IO.println("Task " + taskId + " data");
IO.println(task.getName() + " " + task.getDescription() + " " + task.getStatus().name());
IO.println();
});

var reportId = bugReportService.createBugReport(grokTesterId, projectId, "report", "report desc");
bugReportRepo.getBugReportById(reportId).ifPresent((report) -> {
IO.println("Report " + reportId + " data");
IO.println(report.getName() + " " + report.getDescription() + " " + report.getStatus().name());
IO.println();
});

var bugReportStatus = bugReportService.getBugReportStatus(reportId);
IO.println("Report status " + bugReportStatus.name());
IO.println();

bugReportRepo.getBugReportById(reportId).ifPresent((report) -> {
IO.println("Report " + reportId + " members");
report.getTicketMembers().entrySet().stream().forEach((memberEntry) -> {
var membersString = memberEntry.getValue().stream().map((member) -> member.user().name())
.collect(Collectors.joining(", "));
IO.print("Role " + memberEntry.getKey().name() + ": " + membersString);
});
IO.println();
});
bugReportService.addMemberToBugReport(zigLeadId, reportId, bobDevId, BugReportRole.DEV);
bugReportRepo.getBugReportById(reportId).ifPresent((task) -> {
IO.println("Report " + reportId + " members");
task.getTicketMembers().entrySet().stream().forEach((memberEntry) -> {
var membersString = memberEntry.getValue().stream().map((member) -> member.user().name())
.collect(Collectors.joining(", "));
IO.print("Role " + memberEntry.getKey().name() + ": " + membersString);
});
IO.println();
});

bugReportService.updateBugReportStatus(bobDevId, reportId, BugReportStatus.FIXED);
bugReportRepo.getBugReportById(reportId).ifPresent((task) -> {
IO.println("Report " + reportId + " data");
IO.println(task.getName() + " " + task.getDescription() + " " + task.getStatus().name());
IO.println();
});
}
}
6 changes: 6 additions & 0 deletions src/main/java/org/lab/dto/BugReportDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.lab.dto;

import org.lab.model.ProjectModel.Project;

public record BugReportDTO(Project project, String name, String description) {
}
8 changes: 8 additions & 0 deletions src/main/java/org/lab/dto/MilestoneDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.lab.dto;

import java.time.LocalDate;

import org.lab.model.ProjectModel.Project;

public record MilestoneDTO(Project project, String name, LocalDate start, LocalDate end) {
}
6 changes: 6 additions & 0 deletions src/main/java/org/lab/dto/ProjectDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.lab.dto;

import org.lab.model.ProjectModel.ProjectMember;

public record ProjectDTO(String name, ProjectMember manager) {
}
6 changes: 6 additions & 0 deletions src/main/java/org/lab/dto/TaskDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.lab.dto;

import org.lab.model.MilestoneModel.Milestone;

public record TaskDTO(Milestone milestone, String name, String description) {
}
4 changes: 4 additions & 0 deletions src/main/java/org/lab/dto/UserDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.lab.dto;

public record UserDTO(String email, String name) {
}
18 changes: 18 additions & 0 deletions src/main/java/org/lab/model/BugReport/BugReport.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.lab.model.BugReport;

import org.lab.model.ProjectModel.Project;
import org.lab.model.TicketModel.Ticket;

public final class BugReport extends Ticket<BugReportStatus, BugReportRole> {
private final Project project;

public BugReport(String id, Project project, String name, String description) {
super(id, name, description, BugReportStatus.OPEN);

this.project = project;
}

public Project getProject() {
return project;
}
}
7 changes: 7 additions & 0 deletions src/main/java/org/lab/model/BugReport/BugReportRole.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.lab.model.BugReport;

public enum BugReportRole {
DEV,
TESTER,
REPORTER,
}
8 changes: 8 additions & 0 deletions src/main/java/org/lab/model/BugReport/BugReportStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.lab.model.BugReport;

public enum BugReportStatus {
OPEN,
FIXED,
TESTED,
CLOSED
}
79 changes: 79 additions & 0 deletions src/main/java/org/lab/model/MilestoneModel/Milestone.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package org.lab.model.MilestoneModel;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import org.lab.model.ProjectModel.Project;
import org.lab.model.TaskModel.Task;

public class Milestone {
private final String id;
private final Project project;
private String name;
private LocalDate start;
private LocalDate end;
private MilestoneStatus status;

private final List<Task> tasks;

public Milestone(String id, Project project, String name, LocalDate start, LocalDate end) {
this.id = Objects.requireNonNull(id);
this.project = project;
this.name = Objects.requireNonNull(name);
this.start = Objects.requireNonNull(start);
this.end = Objects.requireNonNull(end);
status = MilestoneStatus.OPEN;
tasks = new ArrayList<>();
}

public String getId() {
return id;
}

public Project getProject() {
return project;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = Objects.requireNonNull(name);
}

public LocalDate getStart() {
return start;
}

public void setStart(LocalDate start) {
this.start = Objects.requireNonNull(start);
}

public LocalDate getEnd() {
return end;
}

public void setEnd(LocalDate end) {
this.end = Objects.requireNonNull(end);
}

public MilestoneStatus getStatus() {
return status;
}

public void setStatus(MilestoneStatus status) {
this.status = Objects.requireNonNull(status);
}

public void addTask(Task task) {
tasks.add(Objects.requireNonNull(task));
}

public List<Task> getTasks() {
return Collections.unmodifiableList(tasks);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.lab.model.MilestoneModel;

public enum MilestoneStatus {
OPEN,
ACTIVE,
CLOSED,
}
Loading