begin switch to WSTO architecture

This commit is contained in:
2025-10-29 13:23:43 +01:00
parent f013ef8438
commit 4aa9cb5b34
8 changed files with 174 additions and 30 deletions

View File

@@ -1,21 +1,18 @@
package de.pnreichmuth.timekeep_backend.controllers;
import de.pnreichmuth.timekeep_backend.entities.Racer;
import de.pnreichmuth.timekeep_backend.entities.Team;
import de.pnreichmuth.timekeep_backend.services.RacerService;
import de.pnreichmuth.timekeep_backend.services.TeamService;
import de.pnreichmuth.timekeep_backend.wsto.RacerWSTO;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.UUID;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/racer")
@@ -24,10 +21,9 @@ import java.util.UUID;
public class RacerRestController {
private final RacerService racerService;
private final TeamService teamService;
@GetMapping("singleRacer")
public ResponseEntity<Racer> getSingleRacers(@RequestParam Racer requestRacer){
public ResponseEntity<@NonNull RacerWSTO> getSingleRacers(@RequestParam Racer requestRacer){
Racer actualRacer = racerService.getRacer(requestRacer.getFirstName(), requestRacer.getLastName());
if (actualRacer == null){
return ResponseEntity.of(
@@ -39,7 +35,7 @@ public class RacerRestController {
)
).build();
}
return ResponseEntity.ok(actualRacer);
return ResponseEntity.ok(RacerWSTO.of(actualRacer));
}
// @GetMapping("byTeam")

View File

@@ -4,17 +4,16 @@ import de.pnreichmuth.timekeep_backend.entities.Team;
import de.pnreichmuth.timekeep_backend.exceptions.TeamExistsException;
import de.pnreichmuth.timekeep_backend.exceptions.TeamNotFoundException;
import de.pnreichmuth.timekeep_backend.services.TeamService;
import de.pnreichmuth.timekeep_backend.wsto.TeamWSTO;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.antlr.v4.runtime.misc.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -27,36 +26,41 @@ public class TeamRestController {
private final TeamService teamService;
@PostMapping("createTeam")
public ResponseEntity<Team> createTeam(@RequestBody Team team){
public ResponseEntity<@NonNull TeamWSTO> createTeam(@RequestBody Team team){
try {
teamService.createTeam(team);
return new ResponseEntity<>(team, HttpStatus.CREATED);
return new ResponseEntity<>(TeamWSTO.of(team), HttpStatus.CREATED);
} catch (TeamExistsException e) {
return ResponseEntity.of(ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT,"This team already exists")).build();
}
}
@PostMapping("createTeamDebug")
public ResponseEntity<Team> createTeam(){
public ResponseEntity<@NonNull TeamWSTO> createTeam(){
try {
Team team = teamService.createTeam();
return new ResponseEntity<>(team, HttpStatus.CREATED);
team.setTeamName("DEBUG");
return new ResponseEntity<>(TeamWSTO.of(team), HttpStatus.CREATED);
} catch (TeamExistsException e) {
return ResponseEntity.of(ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT,"This team already exists")).build();
}
}
@GetMapping("all")
public ResponseEntity<@NonNull List<Team>> getAllTeams(){
public ResponseEntity<@NonNull List<TeamWSTO>> getAllTeams(){
List<Team> teams = teamService.getTeams();
List<TeamWSTO> teamWSTOs = new ArrayList<>();
if(teams.isEmpty()){
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(teams, HttpStatus.OK);
for(Team team : teams){
teamWSTOs.add(TeamWSTO.of(team));
}
return new ResponseEntity<>(teamWSTOs, HttpStatus.OK);
}
@GetMapping("single-team")
public ResponseEntity<@NonNull Team> getSingleTeam(@RequestBody Team reqTeam){
public ResponseEntity<@NonNull TeamWSTO> getSingleTeam(@RequestBody Team reqTeam){
UUID id = reqTeam.getId();
String name = reqTeam.getTeamName();
Team actualTeam;
@@ -68,7 +72,7 @@ public class TeamRestController {
actualTeam = teamService.getTeam(name);
}
else return ResponseEntity.of(ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, "Must provide either id or name")).build();
return new ResponseEntity<>(actualTeam, HttpStatus.OK);
return new ResponseEntity<>(TeamWSTO.of(actualTeam), HttpStatus.OK);
}
catch(TeamNotFoundException e){
if(id != null) return ResponseEntity.of(ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND,"Team with id "+ id +" not found")).build();

View File

@@ -18,4 +18,11 @@ public class Racer{
private String lastName;
private Boolean isFirstSemester;
private String phoneNumber;
public Racer(String firstName, String lastName, Boolean isFirstSemester, String phoneNumber){
this.firstName = firstName;
this.lastName = lastName;
this.isFirstSemester = isFirstSemester;
this.phoneNumber = phoneNumber;
}
}

View File

@@ -5,12 +5,13 @@ import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.UUID;
@Entity
@Getter
@NoArgsConstructor
public class Station {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@@ -19,4 +20,10 @@ public class Station {
private String name;
private String location;
private String passwordHash;
public Station(String name, String location){
this.name = name;
this.location = location;
this.passwordHash = null;
}
}

View File

@@ -1,9 +1,7 @@
package de.pnreichmuth.timekeep_backend.entities;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.*;
import java.util.HashMap;
@@ -36,7 +34,14 @@ public class Team {
this.passedStations = new HashMap<>();
}
public Team(String teamName, boolean firstSemesterTeam, Map<String, Racer> members, Map<String, Station> passedStations){
this.teamName = teamName;
this.firstSemesterTeam = firstSemesterTeam;
this.members = new HashMap<>(members.size());
this.members.putAll(members);
this.passedStations = new HashMap<>(passedStations.size());
this.passedStations.putAll(passedStations);
}
/**
* Treat this team as a team of first semester students, if at least 50% of its members are in the first semester
@@ -61,10 +66,15 @@ public class Team {
/**
* Removes a member from the team by name
* @param id the UUID of the member to be removed
* @param firstName the first name of the racer to be removed
* @param lastName the last name of the racer to be removed
*/
public void removeMember(UUID id){
this.members.remove(id);
public void removeMember(String firstName, String lastName){
this.members.remove(this.generateMapKeyFromName(firstName, lastName));
this.checkFirstSemesterTeam();
}
private String generateMapKeyFromName(String firstName, String lastName){
return String.format("%s, %s", firstName, lastName);
}
}

View File

@@ -0,0 +1,35 @@
package de.pnreichmuth.timekeep_backend.wsto;
import de.pnreichmuth.timekeep_backend.entities.Racer;
import java.util.Objects;
public record RacerWSTO(
String firstName,
String lastName,
boolean isFirstSemester,
String phoneNumber
) {
public RacerWSTO{
Objects.requireNonNull(firstName, "firstName must be set");
Objects.requireNonNull(lastName, "lastName must be set");
}
public static RacerWSTO of(Racer racer){
return new RacerWSTO(
racer.getFirstName(),
racer.getLastName(),
racer.getIsFirstSemester(),
racer.getPhoneNumber()
);
}
public static Racer toEntity(RacerWSTO racerWSTO){
return new Racer(
racerWSTO.firstName(),
racerWSTO.lastName(),
racerWSTO.isFirstSemester(),
racerWSTO.phoneNumber()
);
}
}

View File

@@ -0,0 +1,28 @@
package de.pnreichmuth.timekeep_backend.wsto;
import de.pnreichmuth.timekeep_backend.entities.Station;
import java.util.Objects;
public record StationWSTO(
String name,
String locationName
) {
public StationWSTO{
Objects.requireNonNull(locationName, "Station has to have a location");
}
public static StationWSTO of(Station station){
return new StationWSTO(
station.getName(),
station.getLocation()
);
}
public static Station toEntity(StationWSTO stationWSTO){
return new Station(
stationWSTO.name(),
stationWSTO.locationName()
);
}
}

View File

@@ -0,0 +1,57 @@
package de.pnreichmuth.timekeep_backend.wsto;
import de.pnreichmuth.timekeep_backend.entities.Racer;
import de.pnreichmuth.timekeep_backend.entities.Station;
import de.pnreichmuth.timekeep_backend.entities.Team;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public record TeamWSTO(String teamName,
boolean firstSemesterTeam,
Map<String, RacerWSTO> teamMembers,
Map<String, StationWSTO> passedStations) {
public TeamWSTO{
Objects.requireNonNull(teamName, "Cannot identify Team without a name");
teamMembers = Map.copyOf(teamMembers);
passedStations = Map.copyOf(passedStations);
}
public static TeamWSTO of(Team team){
Map<String, RacerWSTO> tmpMemberMap = new HashMap<>();
for(Map.Entry<String, Racer> member : team.getMembers().entrySet()){
tmpMemberMap.put(member.getKey(), RacerWSTO.of(member.getValue()));
}
Map<String, StationWSTO> tmpStationMap = new HashMap<>();
for(Map.Entry<String,Station> station : team.getPassedStations().entrySet()){
tmpStationMap.put(station.getKey(), StationWSTO.of(station.getValue()));
}
return new TeamWSTO(
team.getTeamName(),
team.isFirstSemesterTeam(),
Map.copyOf(tmpMemberMap),
Map.copyOf(tmpStationMap)
);
}
public static Team toEntity(TeamWSTO teamWSTO){
Map<String, Racer> tmpMemberMap = new HashMap<>();
for(Map.Entry<String, RacerWSTO> member : teamWSTO.teamMembers().entrySet()){
tmpMemberMap.put(member.getKey(), RacerWSTO.toEntity(member.getValue()));
}
Map<String, Station> tmpStationMap = new HashMap<>();
for (Map.Entry<String, StationWSTO> station : teamWSTO.passedStations().entrySet()) {
tmpStationMap.put(station.getKey(), StationWSTO.toEntity(station.getValue()));
}
return new Team(
teamWSTO.teamName(),
teamWSTO.firstSemesterTeam(),
tmpMemberMap,
tmpStationMap
);
}
}