!refactored models, repositories, services and controllers
This commit is contained in:
parent
8767654f12
commit
5c0b157414
@ -11,7 +11,7 @@ configurations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":client-api")
|
//implementation project(":client-api")
|
||||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-aop'
|
implementation 'org.springframework.boot:spring-boot-starter-aop'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||||
|
|||||||
@ -57,30 +57,30 @@ public class UserMetricsAspect {
|
|||||||
|
|
||||||
@After(value = "execution(void ru.dragonestia.picker.repository.InstanceRepository.create(ru.dragonestia.picker.model.instance.Instance)) && args(instance)", argNames = "instance")
|
@After(value = "execution(void ru.dragonestia.picker.repository.InstanceRepository.create(ru.dragonestia.picker.model.instance.Instance)) && args(instance)", argNames = "instance")
|
||||||
void onCreateNode(Instance instance) {
|
void onCreateNode(Instance instance) {
|
||||||
var nodeId = instance.getIdentifier();
|
var nodeId = instance.getId();
|
||||||
var gauge = Gauge.builder("roompicker_node_users_total", () -> data.get(nodeId).users())
|
var gauge = Gauge.builder("roompicker_node_users_total", () -> data.get(nodeId.getValue()).users())
|
||||||
.tag("nodeId", nodeId)
|
.tag("nodeId", nodeId.getValue())
|
||||||
.register(meterRegistry);
|
.register(meterRegistry);
|
||||||
|
|
||||||
var counter = Counter.builder("roompicker_picks")
|
var counter = Counter.builder("roompicker_picks")
|
||||||
.tag("nodeId", nodeId)
|
.tag("nodeId", nodeId.getValue())
|
||||||
.baseUnit("1s")
|
.baseUnit("1s")
|
||||||
.register(meterRegistry);
|
.register(meterRegistry);
|
||||||
|
|
||||||
var lockedGauge = Gauge.builder("roompicker_locked_rooms", () -> data.get(nodeId).locked())
|
var lockedGauge = Gauge.builder("roompicker_locked_rooms", () -> data.get(nodeId.getValue()).locked())
|
||||||
.tag("nodeId", nodeId)
|
.tag("nodeId", nodeId.getValue())
|
||||||
.register(meterRegistry);
|
.register(meterRegistry);
|
||||||
|
|
||||||
var roomsGauge = Gauge.builder("roompicker_rooms", () -> roomRepository.all(instance).size())
|
var roomsGauge = Gauge.builder("roompicker_rooms", () -> roomRepository.all(instance.getId()).size())
|
||||||
.tag("nodeId", nodeId)
|
.tag("nodeId", nodeId.getValue())
|
||||||
.register(meterRegistry);
|
.register(meterRegistry);
|
||||||
|
|
||||||
data.put(nodeId, new NodeData(gauge, new AtomicInteger(0), counter, new AtomicInteger(0), lockedGauge, roomsGauge));
|
data.put(nodeId.getValue(), new NodeData(gauge, new AtomicInteger(0), counter, new AtomicInteger(0), lockedGauge, roomsGauge));
|
||||||
}
|
}
|
||||||
|
|
||||||
@After(value = "execution(* ru.dragonestia.picker.repository.InstanceRepository.delete(ru.dragonestia.picker.model.instance.Instance)) && args(instance)", argNames = "instance")
|
@After(value = "execution(* ru.dragonestia.picker.repository.InstanceRepository.delete(ru.dragonestia.picker.model.instance.Instance)) && args(instance)", argNames = "instance")
|
||||||
void onDeleteNode(Instance instance) {
|
void onDeleteNode(Instance instance) {
|
||||||
var data = this.data.remove(instance.getIdentifier());
|
var data = this.data.remove(instance.getId().getValue());
|
||||||
|
|
||||||
meterRegistry.remove(data.usersGauge());
|
meterRegistry.remove(data.usersGauge());
|
||||||
meterRegistry.remove(data.picksPerMinute());
|
meterRegistry.remove(data.picksPerMinute());
|
||||||
@ -90,17 +90,17 @@ public class UserMetricsAspect {
|
|||||||
|
|
||||||
@AfterReturning(value = "execution(* ru.dragonestia.picker.repository.RoomRepository.pick(ru.dragonestia.picker.model.instance.Instance, *)) && args(instance, ..)", argNames = "instance")
|
@AfterReturning(value = "execution(* ru.dragonestia.picker.repository.RoomRepository.pick(ru.dragonestia.picker.model.instance.Instance, *)) && args(instance, ..)", argNames = "instance")
|
||||||
void onPickRoom(Instance instance) {
|
void onPickRoom(Instance instance) {
|
||||||
data.get(instance.getIdentifier()).picksPerMinute().increment();
|
data.get(instance.getId().getValue()).picksPerMinute().increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 3_000)
|
@Scheduled(fixedDelay = 3_000)
|
||||||
void updateUserMetrics() {
|
void updateUserMetrics() {
|
||||||
entityRepository.countEntitiesForNodes().forEach((nodeId, users) -> {
|
entityRepository.countEntitiesForInstances().forEach((nodeId, users) -> {
|
||||||
Optional.ofNullable(data.get(nodeId)).ifPresent(node -> node.users().set(users));
|
Optional.ofNullable(data.get(nodeId)).ifPresent(node -> node.users().set(users));
|
||||||
});
|
});
|
||||||
|
|
||||||
containerRepository.all().forEach(nodeContainer -> {
|
containerRepository.all().forEach(nodeContainer -> {
|
||||||
var locked = data.get(nodeContainer.getInstance().getIdentifier()).locked();
|
var locked = data.get(nodeContainer.getInstance().getId().getValue()).locked();
|
||||||
locked.set(0);
|
locked.set(0);
|
||||||
|
|
||||||
nodeContainer.allRooms().forEach(roomContainer -> {
|
nodeContainer.allRooms().forEach(roomContainer -> {
|
||||||
|
|||||||
@ -10,15 +10,14 @@ import org.springframework.context.annotation.Profile;
|
|||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
import ru.dragonestia.picker.api.model.node.PickingMethod;
|
|
||||||
import ru.dragonestia.picker.api.model.room.IRoom;
|
|
||||||
import ru.dragonestia.picker.api.repository.type.NodeIdentifier;
|
|
||||||
import ru.dragonestia.picker.api.repository.type.RoomIdentifier;
|
|
||||||
import ru.dragonestia.picker.api.repository.type.EntityIdentifier;
|
|
||||||
import ru.dragonestia.picker.interceptor.DebugInterceptor;
|
import ru.dragonestia.picker.interceptor.DebugInterceptor;
|
||||||
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
import ru.dragonestia.picker.model.factory.RoomFactory;
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
|
import ru.dragonestia.picker.model.instance.type.PickingMethod;
|
||||||
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
|
import ru.dragonestia.picker.model.room.factory.RoomFactory;
|
||||||
import ru.dragonestia.picker.repository.RoomRepository;
|
import ru.dragonestia.picker.repository.RoomRepository;
|
||||||
import ru.dragonestia.picker.repository.InstanceRepository;
|
import ru.dragonestia.picker.repository.InstanceRepository;
|
||||||
import ru.dragonestia.picker.repository.EntityRepository;
|
import ru.dragonestia.picker.repository.EntityRepository;
|
||||||
@ -46,9 +45,9 @@ public class TestConfig implements WebMvcConfigurer {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
void createInstances() {
|
void createInstances() {
|
||||||
createInstanceWithContent(new Instance(NodeIdentifier.of("game-servers"), PickingMethod.ROUND_ROBIN, false));
|
createInstanceWithContent(new Instance(InstanceId.of("game-servers"), PickingMethod.ROUND_ROBIN, false));
|
||||||
createInstanceWithContent(new Instance(NodeIdentifier.of("game-lobbies"), PickingMethod.LEAST_PICKED, false));
|
createInstanceWithContent(new Instance(InstanceId.of("game-lobbies"), PickingMethod.LEAST_PICKED, false));
|
||||||
createInstanceWithContent(new Instance(NodeIdentifier.of("hub"), PickingMethod.SEQUENTIAL_FILLING, false));
|
createInstanceWithContent(new Instance(InstanceId.of("hub"), PickingMethod.SEQUENTIAL_FILLING, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@ -58,17 +57,17 @@ public class TestConfig implements WebMvcConfigurer {
|
|||||||
|
|
||||||
for (int i = 1; i <= 5; i++) {
|
for (int i = 1; i <= 5; i++) {
|
||||||
var slots = 5 * i;
|
var slots = 5 * i;
|
||||||
var room = roomFactory.create(RoomIdentifier.of("test-" + i), instance, slots, json.writeValueAsString(generatePayload()), false);
|
var room = roomFactory.create(RoomId.of("test-" + i), instance, slots, json.writeValueAsString(generatePayload()), false);
|
||||||
roomRepository.create(room);
|
roomRepository.create(room);
|
||||||
|
|
||||||
for (int j = 0, n = rand.nextInt(slots + 1); j < n; j++) {
|
for (int j = 0, n = rand.nextInt(slots + 1); j < n; j++) {
|
||||||
var user = new Entity(EntityIdentifier.of("test-user-" + rand.nextInt(20)));
|
var user = EntityId.of("test-user-" + rand.nextInt(20));
|
||||||
entityRepository.linkWithRoom(room, List.of(user), false);
|
entityRepository.linkWithRoom(room, List.of(user), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
var room = roomFactory.create(RoomIdentifier.of(randomUUID().toString()), instance, IRoom.UNLIMITED_SLOTS, json.writeValueAsString(generatePayload()), false);
|
var room = roomFactory.create(RoomId.random(), instance, -1, json.writeValueAsString(generatePayload()), false);
|
||||||
room.setLocked((i & 1) == 0);
|
room.setLocked((i & 1) == 0);
|
||||||
roomRepository.create(room);
|
roomRepository.create(room);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,52 +1,59 @@
|
|||||||
package ru.dragonestia.picker.controller;
|
package ru.dragonestia.picker.controller;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import ru.dragonestia.picker.api.model.account.ResponseAccount;
|
import ru.dragonestia.picker.controller.response.ResponseObject;
|
||||||
import ru.dragonestia.picker.api.repository.response.AllAccountsResponse;
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Log4j2
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/accounts")
|
@RequestMapping("/accounts")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AccountsController {
|
public class AccountsController {
|
||||||
|
|
||||||
@GetMapping("/current")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
ResponseAccount currentAccount() {
|
@GetMapping
|
||||||
|
List<String> listAccounts() {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
@GetMapping("/{accountId}")
|
@GetMapping("/target/{accountId}")
|
||||||
ResponseEntity<ResponseAccount> findAccount(@PathVariable String accountId) {
|
ResponseObject.Account targetAccountDetails(@PathVariable String accountId) {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
AllAccountsResponse allAccounts() {
|
@GetMapping("/list")
|
||||||
|
ResponseObject.Account listAccountsDetails(@RequestParam List<String> id) {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
@PostMapping
|
@PostMapping
|
||||||
ResponseAccount registerAccount(@RequestParam String username, @RequestParam String password, @RequestParam(defaultValue = "") String permissions) {
|
ResponseEntity<Void> createAccount(@RequestParam String username,
|
||||||
|
@RequestParam String password,
|
||||||
|
@RequestParam List<String> permissions) {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{accountId}")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
ResponseEntity<?> updatePermissions(@PathVariable String accountId, @RequestParam(defaultValue = "") String permissions) {
|
@DeleteMapping("/target/{accountId}")
|
||||||
|
ResponseEntity<Void> removeAccount(@PathVariable String accountId) {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{accountId}")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
ResponseEntity<?> removeAccount(@PathVariable String accountId) {
|
@PutMapping("/target/{accountId}/permissions")
|
||||||
|
ResponseEntity<Void> setPermissions(@PathVariable String accountId,
|
||||||
|
@RequestParam List<String> permissions) {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasRole('ADMIN') || principal.username.equals(accountId)")
|
@PreAuthorize("hasRole('ADMIN') || principal.username.equals(accountId)")
|
||||||
@PutMapping("/{accountId}/password")
|
@PutMapping("/target/{accountId}/password")
|
||||||
ResponseEntity<?> changePassword(@PathVariable String accountId, @RequestParam String newPassword) {
|
ResponseEntity<?> changePassword(@PathVariable String accountId, @RequestParam String newPassword) {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,41 +1,28 @@
|
|||||||
package ru.dragonestia.picker.controller;
|
package ru.dragonestia.picker.controller;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import ru.dragonestia.picker.api.repository.response.LinkedRoomsWithUserResponse;
|
|
||||||
import ru.dragonestia.picker.api.repository.response.SearchUserResponse;
|
|
||||||
import ru.dragonestia.picker.api.repository.response.UserDetailsResponse;
|
|
||||||
|
|
||||||
@Tag(name = "Users", description = "Entity management")
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/users")
|
@RequestMapping("/entities")
|
||||||
public class EntityController {
|
public class EntityController {
|
||||||
|
|
||||||
@Operation(summary = "Search user by identifier")
|
|
||||||
@GetMapping("/search")
|
@GetMapping("/search")
|
||||||
SearchUserResponse search(
|
List<String> search(@RequestParam String input) {
|
||||||
@Parameter(description = "Entity identifier input") @RequestParam(name = "input") String input
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Get user info")
|
@GetMapping("/target/rooms")
|
||||||
@GetMapping("/{userId}")
|
List<String> find(@RequestParam String id) {
|
||||||
UserDetailsResponse find(
|
|
||||||
@Parameter(description = "Entity identifier") @PathVariable(value = "userId") String userId
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Get rooms linked with user")
|
@GetMapping("/list/rooms")
|
||||||
@GetMapping("/{userId}/rooms")
|
Map<String, List<String>> roomsOf(@RequestParam List<String> id) {
|
||||||
LinkedRoomsWithUserResponse roomsOf(
|
|
||||||
@Parameter(description = "Entity identifier") @PathVariable(value = "userId") String userId
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,47 +1,33 @@
|
|||||||
package ru.dragonestia.picker.controller;
|
package ru.dragonestia.picker.controller;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import ru.dragonestia.picker.api.repository.response.LinkUsersWithRoomResponse;
|
|
||||||
import ru.dragonestia.picker.api.repository.response.RoomUserListResponse;
|
|
||||||
|
|
||||||
@Tag(name = "Users", description = "Entity management")
|
import java.util.List;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/instances/{instanceId}/rooms/{roomId}/users")
|
@RequestMapping("/instances/{instanceId}/rooms/{roomId}/users")
|
||||||
public class EntityRoomController {
|
public class EntityRoomController {
|
||||||
|
|
||||||
@Operation(summary = "Get users inside room")
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
ResponseEntity<RoomUserListResponse> usersInsideRoom(
|
List<String> entitiesInsideRoom(@PathVariable String instanceId, @PathVariable String roomId) {
|
||||||
@Parameter(description = "Instance identifier") @PathVariable(name = "instanceId") String instanceId,
|
|
||||||
@Parameter(description = "Room identifier") @PathVariable(name = "roomId") String roomId
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Link users with room")
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
ResponseEntity<LinkUsersWithRoomResponse> linkUserWithRoom(
|
ResponseEntity<Void> linkEntitiesWithRoom(@PathVariable String instanceId,
|
||||||
@Parameter(description = "Instance identifier") @PathVariable(name = "instanceId") String instanceId,
|
@PathVariable String roomId,
|
||||||
@Parameter(description = "Room identifier") @PathVariable(name = "roomId") String roomId,
|
@RequestParam List<String> entities,
|
||||||
@Parameter(description = "Entity identifiers", example = "user1,user2,user3") @RequestParam(name = "userIds") String userIds,
|
@RequestParam(defaultValue = "false") boolean force) {
|
||||||
@Parameter(description = "Ignore slot limitation") @RequestParam(name = "force") boolean force
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Unlink users from room")
|
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
ResponseEntity<?> unlinkUsersForBucket(
|
ResponseEntity<Void> unlinkEntitiesForBucket(@PathVariable String instanceId,
|
||||||
@Parameter(description = "Instance identifier") @PathVariable(name = "instanceId") String instanceId,
|
@PathVariable String roomId,
|
||||||
@Parameter(description = "Room identifier") @PathVariable(name = "roomId") String roomId,
|
@RequestParam List<String> entities) {
|
||||||
@Parameter(description = "Entity identifiers", example = "user1,user2,user3") @RequestParam(name = "userIds") String userIds
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,85 +1,9 @@
|
|||||||
package ru.dragonestia.picker.controller;
|
package ru.dragonestia.picker.controller;
|
||||||
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
import ru.dragonestia.picker.api.exception.*;
|
|
||||||
import ru.dragonestia.picker.api.repository.response.ErrorResponse;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
public class ExceptionHandlerController {
|
public class ExceptionHandlerController {
|
||||||
|
|
||||||
@ExceptionHandler(InstanceNotFoundException.class)
|
// TODO
|
||||||
ResponseEntity<?> nodeNotFound(InstanceNotFoundException ex) {
|
|
||||||
return create(404, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(RoomNotFoundException.class)
|
|
||||||
ResponseEntity<?> roomNotFound(RoomNotFoundException ex) {
|
|
||||||
return create(404, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(InvalidUsernamesException.class)
|
|
||||||
ResponseEntity<?> invalidUsernames(InvalidUsernamesException ex) {
|
|
||||||
return create(400, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(InvalidInstanceIdentifierException.class)
|
|
||||||
ResponseEntity<?> invalidNodeIdentifier(InvalidInstanceIdentifierException ex) {
|
|
||||||
return create(400, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(InvalidRoomIdentifierException.class)
|
|
||||||
ResponseEntity<?> invalidRoomIdentifier(InvalidRoomIdentifierException ex) {
|
|
||||||
return create(400, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(InstanceAlreadyExistException.class)
|
|
||||||
ResponseEntity<?> nodeAlreadyExists(InstanceAlreadyExistException ex) {
|
|
||||||
return create(400, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(RoomAlreadyExistException.class)
|
|
||||||
ResponseEntity<?> roomAlreadyExists(RoomAlreadyExistException ex) {
|
|
||||||
return create(400, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(RoomAreFullException.class)
|
|
||||||
ResponseEntity<?> roomAreFull(RoomAreFullException ex) {
|
|
||||||
return create(400, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(NoRoomsAvailableException.class)
|
|
||||||
ResponseEntity<?> noRoomsAvailable(NoRoomsAvailableException ex) {
|
|
||||||
return create(400, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(NotPersistedNodeException.class)
|
|
||||||
ResponseEntity<?> notPersistedNode(NotPersistedNodeException ex) {
|
|
||||||
return create(400, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(AccountDoesNotExistsException.class)
|
|
||||||
ResponseEntity<?> accountDoesNotExists(AccountDoesNotExistsException ex) {
|
|
||||||
return create(404, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler({PermissionNotFoundException.class})
|
|
||||||
ResponseEntity<?> permissionNotFound(PermissionNotFoundException ex) {
|
|
||||||
return create(400, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler({ConstantAdminParamsException.class})
|
|
||||||
ResponseEntity<?> constantAdminParams(ConstantAdminParamsException ex) {
|
|
||||||
return create(401, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResponseEntity<ErrorResponse> create(int code, ApiException ex) {
|
|
||||||
var details = new HashMap<String, String>();
|
|
||||||
ex.appendDetailsToErrorResponse(details);
|
|
||||||
|
|
||||||
return ResponseEntity.status(code).body(new ErrorResponse(ex.getErrorId(), ex.getMessage(), details));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,60 +1,52 @@
|
|||||||
package ru.dragonestia.picker.controller;
|
package ru.dragonestia.picker.controller;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import ru.dragonestia.picker.api.model.node.PickingMethod;
|
import ru.dragonestia.picker.controller.response.ResponseObject;
|
||||||
import ru.dragonestia.picker.api.repository.response.NodeDetailsResponse;
|
import ru.dragonestia.picker.model.instance.type.PickingMethod;
|
||||||
import ru.dragonestia.picker.api.repository.response.NodeListResponse;
|
|
||||||
import ru.dragonestia.picker.api.repository.response.PickedRoomResponse;
|
import java.util.List;
|
||||||
|
|
||||||
@Tag(name = "Nodes", description = "Instance management")
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/instances")
|
@RequestMapping("/instances")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class InstanceController {
|
public class InstanceController {
|
||||||
|
|
||||||
@Operation(summary = "Get all nodes")
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
NodeListResponse allInstances() {
|
List<String> listInstances() {
|
||||||
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/target/{instanceId}")
|
||||||
|
ResponseObject.Instance targetInstanceDetails(@PathVariable String instanceId) {
|
||||||
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
List<ResponseObject.Instance> listInstancesDetails(@RequestParam List<String> id) {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Register new node")
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
ResponseEntity<?> registerInstance(
|
ResponseEntity<Void> createInstance(@RequestParam String instanceId,
|
||||||
@Parameter(description = "Instance identifier") @RequestParam(name = "instanceId") String instanceId,
|
@RequestParam PickingMethod method,
|
||||||
@Parameter(description = "Picking method method") @RequestParam(name = "method") PickingMethod method,
|
@RequestParam(defaultValue = "false") boolean persist) {
|
||||||
@Parameter(description = "Save node") @RequestParam(name = "persist", required = false, defaultValue = "false") boolean persist
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Get node details")
|
@DeleteMapping("/target/{instanceId}")
|
||||||
@GetMapping("/{instanceId}")
|
ResponseEntity<Void> deleteInstance(@PathVariable String instanceId) {
|
||||||
ResponseEntity<NodeDetailsResponse> instanceDetails(
|
|
||||||
@Parameter(description = "Instance identifier") @PathVariable("instanceId") String instanceId
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Unregister node")
|
@DeleteMapping("/list")
|
||||||
@DeleteMapping("/{instanceId}")
|
ResponseEntity<Void> deleteInstances(@RequestParam List<String> id) {
|
||||||
ResponseEntity<?> removeInstance(
|
|
||||||
@Parameter(description = "Instance identifier") @PathVariable("instanceId") String instanceId
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Pick node for users")
|
@PostMapping("/target/{instanceId}/pick")
|
||||||
@PostMapping("/{instanceId}/pick")
|
ResponseObject.PickedRoom pickRoom(@PathVariable String instanceId, @RequestBody List<String> entities) {
|
||||||
ResponseEntity<PickedRoomResponse> pickRoom(
|
|
||||||
@Parameter(description = "Instance identifier") @PathVariable("instanceId") String instanceId,
|
|
||||||
@RequestBody String userIds
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,68 +1,54 @@
|
|||||||
package ru.dragonestia.picker.controller;
|
package ru.dragonestia.picker.controller;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import ru.dragonestia.picker.api.repository.response.RoomInfoResponse;
|
import ru.dragonestia.picker.controller.response.ResponseObject;
|
||||||
import ru.dragonestia.picker.api.repository.response.RoomListResponse;
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Tag(name = "Rooms", description = "Room management")
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/instances/{instanceId}/rooms")
|
@RequestMapping("/instances/target/{instanceId}/rooms")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class RoomController {
|
public class RoomController {
|
||||||
|
|
||||||
@Operation(summary = "Get all rooms from node")
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
ResponseEntity<RoomListResponse> all(
|
List<String> listRooms(@PathVariable String instanceId) {
|
||||||
@Parameter(description = "Instance identifier") @PathVariable(name = "instanceId") String instanceId
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
) {
|
}
|
||||||
|
|
||||||
|
@GetMapping("/target/{roomId}")
|
||||||
|
ResponseObject.Room targetRoomDetails(@PathVariable String instanceId, @PathVariable String roomId) {
|
||||||
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
List<ResponseObject.Room> listRoomDetails(@PathVariable String instanceId, @RequestParam List<String> id) {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Register new room")
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
ResponseEntity<?> register(
|
ResponseEntity<Void> createRoom(@PathVariable String instanceId,
|
||||||
@Parameter(description = "Instance identifier") @PathVariable(name = "instanceId") String instanceId,
|
@RequestParam String id,
|
||||||
@Parameter(description = "Room identifier") @RequestParam(name = "roomId") String roomId,
|
@RequestParam int slots,
|
||||||
@Parameter(description = "Maximum users count in room") @RequestParam(name = "slots") int slots,
|
@RequestParam String payload,
|
||||||
@Parameter(description = "Payload. Some data") @RequestParam(name = "payload") String payload,
|
@RequestParam(defaultValue = "false") boolean locked,
|
||||||
@Parameter(description = "Lock for picking") @RequestParam(name = "locked", required = false, defaultValue = "false") boolean locked,
|
@RequestParam(defaultValue = "false") boolean persist) {
|
||||||
@Parameter(description = "Save room") @RequestParam(name = "persist", required = false, defaultValue = "false") boolean persist
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Unregister room")
|
@DeleteMapping("/target/{roomId}")
|
||||||
@DeleteMapping("/{roomId}")
|
ResponseEntity<Void> deleteRoom(@PathVariable String instanceId, @PathVariable String roomId) {
|
||||||
ResponseEntity<?> remove(
|
|
||||||
@Parameter(description = "Instance identifier") @PathVariable("instanceId") String instanceId,
|
|
||||||
@Parameter(description = "Room identifier") @PathVariable("roomId") String roomId
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Get room details")
|
@DeleteMapping("/list")
|
||||||
@GetMapping("/{roomId}")
|
ResponseEntity<Void> deleteRooms(@PathVariable String instanceId, @RequestParam List<String> id) {
|
||||||
ResponseEntity<RoomInfoResponse> info(
|
|
||||||
@Parameter(description = "Instance identifier") @PathVariable("instanceId") String instanceId,
|
|
||||||
@Parameter(description = "Room identifier") @PathVariable("roomId") String roomId
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "Lock/unlock room")
|
@PutMapping("/target/{roomId}/lock")
|
||||||
@ApiResponse(description = "New lock state")
|
ResponseEntity<Void> lockRoom(@PathVariable String instanceId, @PathVariable String roomId, @RequestParam boolean newState) {
|
||||||
@PutMapping("/{roomId}/lock")
|
|
||||||
ResponseEntity<Boolean> lockRoom(
|
|
||||||
@Parameter(description = "Instance identifier") @PathVariable("instanceId") String instanceId,
|
|
||||||
@Parameter(description = "Room identifier") @PathVariable("roomId") String roomId,
|
|
||||||
@Parameter(description = "New state for Lock property") @RequestParam(name = "newState") boolean value
|
|
||||||
) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,12 @@
|
|||||||
package ru.dragonestia.picker.controller;
|
package ru.dragonestia.picker.controller;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import ru.dragonestia.picker.api.repository.response.RoomPickerInfoResponse;
|
import ru.dragonestia.picker.controller.response.RoomPickerInfoResponse;
|
||||||
|
|
||||||
@Tag(name = "RoomPicker")
|
|
||||||
@RestController
|
@RestController
|
||||||
public class RoomPickerController {
|
public class RoomPickerController {
|
||||||
|
|
||||||
@Operation(summary = "Server info")
|
|
||||||
@GetMapping("/info")
|
@GetMapping("/info")
|
||||||
RoomPickerInfoResponse info() {
|
RoomPickerInfoResponse info() {
|
||||||
return new RoomPickerInfoResponse("v0.0.1");
|
return new RoomPickerInfoResponse("v0.0.1");
|
||||||
|
|||||||
@ -4,12 +4,14 @@ import jakarta.validation.constraints.NotNull;
|
|||||||
import org.springframework.graphql.data.method.annotation.Argument;
|
import org.springframework.graphql.data.method.annotation.Argument;
|
||||||
import org.springframework.graphql.data.method.annotation.QueryMapping;
|
import org.springframework.graphql.data.method.annotation.QueryMapping;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import ru.dragonestia.picker.api.repository.type.EntityIdentifier;
|
|
||||||
import ru.dragonestia.picker.controller.graphql.object.ObjectInstance;
|
import ru.dragonestia.picker.controller.graphql.object.ObjectInstance;
|
||||||
import ru.dragonestia.picker.controller.graphql.object.ObjectRoom;
|
import ru.dragonestia.picker.controller.graphql.object.ObjectRoom;
|
||||||
import ru.dragonestia.picker.controller.graphql.object.ObjectEntity;
|
import ru.dragonestia.picker.controller.graphql.object.ObjectEntity;
|
||||||
import ru.dragonestia.picker.controller.graphql.object.type.DataProvider;
|
import ru.dragonestia.picker.controller.graphql.object.type.DataProvider;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
import ru.dragonestia.picker.service.InstanceService;
|
import ru.dragonestia.picker.service.InstanceService;
|
||||||
import ru.dragonestia.picker.service.RoomService;
|
import ru.dragonestia.picker.service.RoomService;
|
||||||
import ru.dragonestia.picker.service.EntityService;
|
import ru.dragonestia.picker.service.EntityService;
|
||||||
@ -40,40 +42,40 @@ public class GraphqlController {
|
|||||||
|
|
||||||
@QueryMapping
|
@QueryMapping
|
||||||
ObjectInstance instanceById(@Argument String id) {
|
ObjectInstance instanceById(@Argument String id) {
|
||||||
return instanceService.find(id)
|
return instanceService.find(InstanceId.of(id))
|
||||||
.map(node -> new ObjectInstance(node, dataProvider))
|
.map(node -> new ObjectInstance(node, dataProvider))
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@QueryMapping
|
@QueryMapping
|
||||||
List<ObjectRoom> allRooms(@NotNull String nodeId) {
|
List<ObjectRoom> allRooms(@NotNull String nodeId) {
|
||||||
var node = instanceService.find(nodeId).orElse(null);
|
var node = instanceService.find(InstanceId.of(nodeId)).orElse(null);
|
||||||
if (node == null) return null;
|
if (node == null) return null;
|
||||||
|
|
||||||
return roomService.all(node).stream()
|
return roomService.all(node.getId()).stream()
|
||||||
.map(room -> new ObjectRoom(room, dataProvider))
|
.map(room -> new ObjectRoom(room, dataProvider))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@QueryMapping
|
@QueryMapping
|
||||||
ObjectRoom roomById(@Argument String nodeId, @NotNull String roomId) {
|
ObjectRoom roomById(@Argument String nodeId, @NotNull String roomId) {
|
||||||
var node = instanceService.find(nodeId).orElse(null);
|
var node = instanceService.find(InstanceId.of(nodeId)).orElse(null);
|
||||||
if (node == null) return null;
|
if (node == null) return null;
|
||||||
|
|
||||||
return roomService.find(node, roomId)
|
return roomService.find(node.getId(), RoomId.of(roomId))
|
||||||
.map(room -> new ObjectRoom(room, dataProvider))
|
.map(room -> new ObjectRoom(room, dataProvider))
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@QueryMapping
|
@QueryMapping
|
||||||
ObjectEntity entityById(@Argument String id) {
|
ObjectEntity entityById(@Argument String id) {
|
||||||
return new ObjectEntity(new Entity(EntityIdentifier.of(id)), dataProvider);
|
return new ObjectEntity(new Entity(EntityId.of(id)), dataProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@QueryMapping
|
@QueryMapping
|
||||||
List<ObjectEntity> searchEntity(@Argument String input) {
|
List<ObjectEntity> searchEntity(@Argument String input) {
|
||||||
return entityService.searchEntities(input).stream()
|
return entityService.searchEntities(EntityId.of(input)).stream()
|
||||||
.map(user -> new ObjectEntity(new Entity(user.getIdentifierObject()), dataProvider))
|
.map(user -> new ObjectEntity(new Entity(user.getId()), dataProvider))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ public class ObjectEntity {
|
|||||||
private List<ObjectRoom> cachedRooms = null;
|
private List<ObjectRoom> cachedRooms = null;
|
||||||
|
|
||||||
public @NotNull String getId() {
|
public @NotNull String getId() {
|
||||||
return entity.getIdentifier();
|
return entity.getId().getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ObjectRoom> getRooms() {
|
public List<ObjectRoom> getRooms() {
|
||||||
@ -23,7 +23,7 @@ public class ObjectEntity {
|
|||||||
return cachedRooms;
|
return cachedRooms;
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedRooms = dataProvider.entityService().getEntityRooms(entity).stream()
|
cachedRooms = dataProvider.entityService().getEntityRooms(entity.getId()).stream()
|
||||||
.map(room -> new ObjectRoom(room, dataProvider))
|
.map(room -> new ObjectRoom(room, dataProvider))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ public class ObjectInstance {
|
|||||||
private List<ObjectRoom> cachedRooms = null;
|
private List<ObjectRoom> cachedRooms = null;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return instance.getIdentifier();
|
return instance.getId().getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMethod() {
|
public String getMethod() {
|
||||||
@ -26,7 +26,7 @@ public class ObjectInstance {
|
|||||||
return cachedRooms;
|
return cachedRooms;
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedRooms = dataProvider.roomService().all(instance).stream()
|
cachedRooms = dataProvider.roomService().all(instance.getId()).stream()
|
||||||
.map(room -> new ObjectRoom(room, dataProvider))
|
.map(room -> new ObjectRoom(room, dataProvider))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
|||||||
@ -14,21 +14,21 @@ public class ObjectRoom {
|
|||||||
private List<ObjectEntity> cachedUsers = null;
|
private List<ObjectEntity> cachedUsers = null;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return room.getIdentifier();
|
return room.getId().getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getInstanceId() {
|
public String getInstanceId() {
|
||||||
return room.getInstanceIdentifier();
|
return room.getInstance().getId().getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectInstance getInstance() {
|
public ObjectInstance getInstance() {
|
||||||
return dataProvider.instanceService().find(room.getInstanceIdentifier())
|
return dataProvider.instanceService().find(room.getInstance().getId())
|
||||||
.map(node -> new ObjectInstance(node, dataProvider))
|
.map(node -> new ObjectInstance(node, dataProvider))
|
||||||
.orElseThrow();
|
.orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSlots() {
|
public int getSlots() {
|
||||||
return room.getMaxSlots();
|
return room.getSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPayload() {
|
public String getPayload() {
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
package ru.dragonestia.picker.controller.response;
|
||||||
|
|
||||||
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
|
import ru.dragonestia.picker.model.instance.type.PickingMethod;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class ResponseObject {
|
||||||
|
|
||||||
|
private ResponseObject() {}
|
||||||
|
|
||||||
|
public record Instance(String id, PickingMethod method, boolean persist) {}
|
||||||
|
|
||||||
|
public record Room(String id, String nodeId, int slots, boolean locked, boolean persist, String payload) {}
|
||||||
|
|
||||||
|
public record PickedRoom(Room room, List<EntityId> entities) {}
|
||||||
|
|
||||||
|
public record Account(String id, List<String> permissions, boolean locked) {}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
package ru.dragonestia.picker.controller.response;
|
||||||
|
|
||||||
|
public record RoomPickerInfoResponse(String version) {}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package ru.dragonestia.picker.exception;
|
||||||
|
|
||||||
|
public class AdminAccountMutationException extends RuntimeException {
|
||||||
|
|
||||||
|
public AdminAccountMutationException() {
|
||||||
|
super("Cannot mutate admin account");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package ru.dragonestia.picker.exception;
|
||||||
|
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
|
|
||||||
|
public class AlreadyExistsException extends RuntimeException {
|
||||||
|
|
||||||
|
public AlreadyExistsException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AlreadyExistsException forInstance(InstanceId instanceId) {
|
||||||
|
return new AlreadyExistsException("Instance with id '%s' already created".formatted(instanceId.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AlreadyExistsException forRoom(InstanceId instanceId, RoomId roomId) {
|
||||||
|
return new AlreadyExistsException("Room with id '%s' already exists in instance '%s".formatted(roomId.getValue(), instanceId.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package ru.dragonestia.picker.exception;
|
||||||
|
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
|
|
||||||
|
public class ConflictingPersistParametersException extends RuntimeException {
|
||||||
|
|
||||||
|
public ConflictingPersistParametersException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConflictingPersistParametersException forRoom(InstanceId instanceId, RoomId roomId) {
|
||||||
|
return new ConflictingPersistParametersException("Tried create persisted room '%s' for not persisted instance '%s'"
|
||||||
|
.formatted(
|
||||||
|
roomId.getValue(),
|
||||||
|
instanceId.getValue()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package ru.dragonestia.picker.exception;
|
||||||
|
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
|
|
||||||
|
public class DoesNotExistsException extends RuntimeException {
|
||||||
|
|
||||||
|
public DoesNotExistsException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DoesNotExistsException forInstance(InstanceId id) {
|
||||||
|
return new DoesNotExistsException("Does not exists instance with id '%s'".formatted(id.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DoesNotExistsException forRoom(RoomId id) {
|
||||||
|
return new DoesNotExistsException("Does not exists room with id '%s'".formatted(id.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package ru.dragonestia.picker.exception;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class InvalidIdentifierException extends RuntimeException {
|
||||||
|
|
||||||
|
public InvalidIdentifierException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InvalidIdentifierException taken(@Nullable String input) {
|
||||||
|
return new InvalidIdentifierException("Taken identifier: " + input);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package ru.dragonestia.picker.exception;
|
||||||
|
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
|
|
||||||
|
public class NoRoomsAvailableException extends RuntimeException {
|
||||||
|
|
||||||
|
public NoRoomsAvailableException(InstanceId instanceId) {
|
||||||
|
super("There are no rooms available in instance '" + instanceId.getValue() + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package ru.dragonestia.picker.exception;
|
||||||
|
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
|
|
||||||
|
public class RoomAreFullException extends RuntimeException {
|
||||||
|
|
||||||
|
public RoomAreFullException(InstanceId instanceId, RoomId roomId) {
|
||||||
|
super("Room '%s' in instance '%s' are full".formatted(roomId.getValue(), instanceId.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,66 +1,37 @@
|
|||||||
package ru.dragonestia.picker.model.account;
|
package ru.dragonestia.picker.model.account;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Contract;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import lombok.Setter;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import ru.dragonestia.picker.api.model.account.IAccount;
|
|
||||||
import ru.dragonestia.picker.api.model.account.ResponseAccount;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class Account implements IAccount, UserDetails {
|
public class Account implements UserDetails {
|
||||||
|
|
||||||
private final String username;
|
@Getter private final AccountId id;
|
||||||
|
@Getter private final String username;
|
||||||
private final String lowerUsername;
|
private final String lowerUsername;
|
||||||
private String password;
|
@Getter @Setter private String password;
|
||||||
private Set<Permission> permissions = new HashSet<>();
|
private Set<Permission> permissions = new HashSet<>();
|
||||||
private boolean locked = false;
|
@Getter @Setter private boolean locked = false;
|
||||||
private boolean enabled = true;
|
@Getter @Setter private boolean enabled = true;
|
||||||
|
|
||||||
public Account(@NotNull String username, @NotNull String password) {
|
public Account(AccountId id, String password) {
|
||||||
this.username = username;
|
this.id = id;
|
||||||
|
this.username = id.getValue();
|
||||||
this.lowerUsername = username.toLowerCase();
|
this.lowerUsername = username.toLowerCase();
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Collection<Permission> getAuthorities() {
|
public Collection<Permission> getAuthorities() {
|
||||||
return permissions;
|
return permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setAuthorities(Set<Permission> permissions) {
|
||||||
public boolean isLocked() {
|
|
||||||
return locked;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Contract("_ -> this")
|
|
||||||
public @NotNull Account setAuthorities(@NotNull Set<Permission> permissions) {
|
|
||||||
this.permissions = permissions;
|
this.permissions = permissions;
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Set<String> getPermissions() {
|
|
||||||
return getAuthorities().stream().map(Enum::name).collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Contract("_ -> this")
|
|
||||||
public @NotNull Account setPassword(String value) {
|
|
||||||
password = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -73,28 +44,11 @@ public class Account implements IAccount, UserDetails {
|
|||||||
return !locked;
|
return !locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_ -> this")
|
|
||||||
public @NotNull Account setLocked(boolean value) {
|
|
||||||
locked = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCredentialsNonExpired() {
|
public boolean isCredentialsNonExpired() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Contract("_ -> this")
|
|
||||||
public @NotNull Account setEnabled(boolean value) {
|
|
||||||
enabled = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return lowerUsername.hashCode();
|
return lowerUsername.hashCode();
|
||||||
@ -109,8 +63,4 @@ public class Account implements IAccount, UserDetails {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ResponseAccount toResponseObject() {
|
|
||||||
return new ResponseAccount(username, password, getPermissions(), locked);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
package ru.dragonestia.picker.model.account;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import ru.dragonestia.picker.exception.InvalidIdentifierException;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public final class AccountId {
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private AccountId(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return value.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
AccountId accountId = (AccountId) o;
|
||||||
|
return Objects.equals(value, accountId.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AccountId of(String identifier) throws InvalidIdentifierException {
|
||||||
|
if (identifier.matches("^[aA-zZ\\d]{3,32}$")) {
|
||||||
|
return new AccountId(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw InvalidIdentifierException.taken(identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,42 +1,24 @@
|
|||||||
package ru.dragonestia.picker.model.entity;
|
package ru.dragonestia.picker.model.entity;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import ru.dragonestia.picker.api.model.user.IUser;
|
|
||||||
import ru.dragonestia.picker.api.model.user.ResponseUser;
|
|
||||||
import ru.dragonestia.picker.api.model.user.UserDetails;
|
|
||||||
import ru.dragonestia.picker.api.repository.type.EntityIdentifier;
|
|
||||||
|
|
||||||
public class Entity implements IUser {
|
@Getter
|
||||||
|
public class Entity {
|
||||||
|
|
||||||
private final String identifier;
|
private final EntityId id;
|
||||||
|
|
||||||
public Entity(@NotNull EntityIdentifier identifier) {
|
public Entity(EntityId id) {
|
||||||
this.identifier = identifier.getValue();
|
this.id = id;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getIdentifier() {
|
|
||||||
return identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable String getDetail(@NotNull UserDetails detail) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull ResponseUser toResponseObject() {
|
|
||||||
return new ResponseUser(identifier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return identifier;
|
return id.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return identifier.hashCode();
|
return id.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -44,7 +26,7 @@ public class Entity implements IUser {
|
|||||||
if (object == this) return true;
|
if (object == this) return true;
|
||||||
if (object == null) return false;
|
if (object == null) return false;
|
||||||
if (object instanceof Entity other) {
|
if (object instanceof Entity other) {
|
||||||
return identifier.equals(other.identifier);
|
return id.equals(other.id);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
package ru.dragonestia.picker.model.entity;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import ru.dragonestia.picker.exception.InvalidIdentifierException;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public final class EntityId {
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private EntityId(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return value.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
EntityId entityId = (EntityId) o;
|
||||||
|
return Objects.equals(value, entityId.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EntityId of(String identifier) throws InvalidIdentifierException {
|
||||||
|
if (identifier.matches("^[aA-zZ\\d-.\\s:@_;]{1,64}$")) {
|
||||||
|
return new EntityId(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw InvalidIdentifierException.taken(identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,19 +0,0 @@
|
|||||||
package ru.dragonestia.picker.model.factory;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.jetbrains.annotations.Contract;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import ru.dragonestia.picker.api.repository.type.RoomIdentifier;
|
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class RoomFactory {
|
|
||||||
|
|
||||||
@Contract("_, _, _, _, _ -> new")
|
|
||||||
public @NotNull Room create(@NotNull RoomIdentifier identifier, @NotNull Instance instance, int slots, @NotNull String payload, boolean persist) {
|
|
||||||
return new Room(identifier, instance, slots, payload, persist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,52 +1,24 @@
|
|||||||
package ru.dragonestia.picker.model.instance;
|
package ru.dragonestia.picker.model.instance;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import ru.dragonestia.picker.model.instance.type.PickingMethod;
|
||||||
import ru.dragonestia.picker.api.model.node.INode;
|
|
||||||
import ru.dragonestia.picker.api.model.node.NodeDetails;
|
|
||||||
import ru.dragonestia.picker.api.model.node.PickingMethod;
|
|
||||||
import ru.dragonestia.picker.api.model.node.ResponseNode;
|
|
||||||
import ru.dragonestia.picker.api.repository.type.NodeIdentifier;
|
|
||||||
|
|
||||||
public class Instance implements INode {
|
@Getter
|
||||||
|
public class Instance {
|
||||||
|
|
||||||
private final String identifier;
|
private final InstanceId id;
|
||||||
private final PickingMethod pickingMethod;
|
private final PickingMethod pickingMethod;
|
||||||
private final boolean persist;
|
private final boolean persist;
|
||||||
|
|
||||||
public Instance(@NotNull NodeIdentifier identifier, @NotNull PickingMethod pickingMethod, boolean persist) {
|
public Instance(InstanceId id, PickingMethod pickingMethod, boolean persist) {
|
||||||
this.identifier = identifier.getValue();
|
this.id = id;
|
||||||
this.pickingMethod = pickingMethod;
|
this.pickingMethod = pickingMethod;
|
||||||
this.persist = persist;
|
this.persist = persist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getIdentifier() {
|
|
||||||
return identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull PickingMethod getPickingMethod() {
|
|
||||||
return pickingMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Boolean isPersist() {
|
|
||||||
return persist;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable String getDetail(@NotNull NodeDetails detail) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull ResponseNode toResponseObject() {
|
|
||||||
return new ResponseNode(identifier, pickingMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return identifier.hashCode();
|
return id.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -54,13 +26,13 @@ public class Instance implements INode {
|
|||||||
if (object == this) return true;
|
if (object == this) return true;
|
||||||
if (object == null) return false;
|
if (object == null) return false;
|
||||||
if (object instanceof Instance other) {
|
if (object instanceof Instance other) {
|
||||||
return identifier.equals(other.identifier);
|
return id.equals(other.id);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "{Instance id='%s'}".formatted(identifier);
|
return "{Instance id='%s'}".formatted(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,53 @@
|
|||||||
|
package ru.dragonestia.picker.model.instance;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import ru.dragonestia.picker.exception.InvalidIdentifierException;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public final class InstanceId {
|
||||||
|
|
||||||
|
private static final Random random = new Random();
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private InstanceId(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return value.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
InstanceId that = (InstanceId) o;
|
||||||
|
return Objects.equals(value, that.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InstanceId of(String identifier) throws InvalidIdentifierException {
|
||||||
|
if (identifier.matches("^(?!-)[a-z\\d-]{0,31}[a-z\\d](?!-)$")) {
|
||||||
|
return new InstanceId(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw InvalidIdentifierException.taken(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InstanceId random() {
|
||||||
|
char[] chars = new char[32];
|
||||||
|
for (int i = 0; i < chars.length; i++) {
|
||||||
|
chars[i] = (char) ('a' + random.nextInt('z' - 'a'));
|
||||||
|
}
|
||||||
|
return new InstanceId(new String(chars));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package ru.dragonestia.picker.model.instance.type;
|
||||||
|
|
||||||
|
public enum PickingMethod {
|
||||||
|
SEQUENTIAL_FILLING,
|
||||||
|
ROUND_ROBIN,
|
||||||
|
LEAST_PICKED
|
||||||
|
}
|
||||||
@ -1,89 +1,32 @@
|
|||||||
package ru.dragonestia.picker.model.room;
|
package ru.dragonestia.picker.model.room;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import lombok.Setter;
|
||||||
import ru.dragonestia.picker.api.model.room.IRoom;
|
|
||||||
import ru.dragonestia.picker.api.model.room.ResponseRoom;
|
|
||||||
import ru.dragonestia.picker.api.model.room.RoomDetails;
|
|
||||||
import ru.dragonestia.picker.api.model.room.ShortResponseRoom;
|
|
||||||
import ru.dragonestia.picker.api.repository.type.RoomIdentifier;
|
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Room implements IRoom {
|
@Getter
|
||||||
|
public class Room {
|
||||||
|
|
||||||
private final String identifier;
|
private final RoomId id;
|
||||||
private final String instanceIdentifier;
|
private final Instance instance;
|
||||||
private final int slots;
|
private final int slots;
|
||||||
private final String payload;
|
private final String payload;
|
||||||
private final boolean persist;
|
private final boolean persist;
|
||||||
private boolean locked = false;
|
@Setter private boolean locked = false;
|
||||||
|
|
||||||
public Room(@NotNull RoomIdentifier identifier, @NotNull Instance instance, int slots, @NotNull String payload, boolean persist) {
|
public Room(RoomId id, Instance instance, int slots, String payload, boolean persist) {
|
||||||
this.identifier = identifier.getValue();
|
this.id = id;
|
||||||
this.instanceIdentifier = instance.getIdentifier();
|
this.instance = instance;
|
||||||
this.slots = slots;
|
this.slots = slots;
|
||||||
this.payload = payload;
|
this.payload = payload;
|
||||||
this.persist = persist;
|
this.persist = persist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getIdentifier() {
|
|
||||||
return identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getInstanceIdentifier() {
|
|
||||||
return instanceIdentifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMaxSlots() {
|
|
||||||
return slots;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLocked() {
|
|
||||||
return locked;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLocked(boolean value) {
|
|
||||||
locked = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Boolean isPersist() {
|
|
||||||
return persist;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getPayload() {
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable String getDetail(@NotNull RoomDetails detail) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAvailable(int usedSlots, int requiredSlots) {
|
|
||||||
if (locked) return false;
|
|
||||||
if (hasUnlimitedSlots()) return true;
|
|
||||||
return slots >= usedSlots + requiredSlots;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull ResponseRoom toResponseObject() {
|
|
||||||
return new ResponseRoom(identifier, instanceIdentifier, slots, locked, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull ShortResponseRoom toShortResponseObject() {
|
|
||||||
return new ShortResponseRoom(identifier, instanceIdentifier, slots, locked);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(identifier, instanceIdentifier);
|
return Objects.hash(id, instance.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -91,7 +34,7 @@ public class Room implements IRoom {
|
|||||||
if (object == this) return true;
|
if (object == this) return true;
|
||||||
if (object == null) return false;
|
if (object == null) return false;
|
||||||
if (object instanceof Room other) {
|
if (object instanceof Room other) {
|
||||||
return identifier.equals(other.identifier) && instanceIdentifier.equals(other.instanceIdentifier);
|
return id.equals(other.id) && instance.getId().equals(other.instance.getId());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,54 @@
|
|||||||
|
package ru.dragonestia.picker.model.room;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import ru.dragonestia.picker.exception.InvalidIdentifierException;
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public final class RoomId {
|
||||||
|
|
||||||
|
private final static Random random = new Random();
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private RoomId(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return value.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
RoomId roomId = (RoomId) o;
|
||||||
|
return Objects.equals(value, roomId.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RoomId of(String identifier) throws InvalidIdentifierException {
|
||||||
|
if (identifier.matches("^(?!-)[a-z\\d-]{0,31}[a-z\\d](?!-)$")) {
|
||||||
|
return new RoomId(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw InvalidIdentifierException.taken(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RoomId random() {
|
||||||
|
char[] chars = new char[32];
|
||||||
|
for (int i = 0; i < chars.length; i++) {
|
||||||
|
chars[i] = (char) ('a' + random.nextInt('z' - 'a'));
|
||||||
|
}
|
||||||
|
return new RoomId(new String(chars));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package ru.dragonestia.picker.model.room.factory;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RoomFactory {
|
||||||
|
|
||||||
|
public Room create(RoomId identifier, Instance instance, int slots, String payload, boolean persist) {
|
||||||
|
return new Room(identifier, instance, slots, payload, persist);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package ru.dragonestia.picker.repository;
|
package ru.dragonestia.picker.repository;
|
||||||
|
|
||||||
import ru.dragonestia.picker.api.exception.RoomAreFullException;
|
import ru.dragonestia.picker.exception.RoomAreFullException;
|
||||||
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
|
|
||||||
@ -9,17 +10,17 @@ import java.util.Map;
|
|||||||
|
|
||||||
public interface EntityRepository {
|
public interface EntityRepository {
|
||||||
|
|
||||||
void linkWithRoom(Room room, Collection<Entity> entities, boolean force) throws RoomAreFullException;
|
void linkWithRoom(Room room, Collection<EntityId> entities, boolean force) throws RoomAreFullException;
|
||||||
|
|
||||||
void unlinkWithRoom(Room room, Collection<Entity> entities);
|
void unlinkWithRoom(Room room, Collection<EntityId> entities);
|
||||||
|
|
||||||
Collection<Room> findAllLinkedEntityRooms(Entity entity);
|
Collection<Room> findAllLinkedEntityRooms(EntityId entity);
|
||||||
|
|
||||||
Collection<Entity> entitiesOf(Room room);
|
Collection<Entity> entitiesOf(Room room);
|
||||||
|
|
||||||
Collection<Entity> search(String input);
|
Collection<Entity> search(EntityId input);
|
||||||
|
|
||||||
int countAllEntities();
|
int countAllEntities();
|
||||||
|
|
||||||
Map<String, Integer> countEntitiesForNodes();
|
Map<String, Integer> countEntitiesForInstances();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
package ru.dragonestia.picker.repository;
|
package ru.dragonestia.picker.repository;
|
||||||
|
|
||||||
import ru.dragonestia.picker.api.exception.InstanceAlreadyExistException;
|
import ru.dragonestia.picker.exception.AlreadyExistsException;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface InstanceRepository {
|
public interface InstanceRepository {
|
||||||
|
|
||||||
void create(Instance instance) throws InstanceAlreadyExistException;
|
void create(Instance instance) throws AlreadyExistsException;
|
||||||
|
|
||||||
void delete(Instance instance);
|
void delete(InstanceId id);
|
||||||
|
|
||||||
Optional<Instance> findById(String nodeId);
|
Optional<Instance> findById(InstanceId id);
|
||||||
|
|
||||||
List<Instance> all();
|
List<Instance> all();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
package ru.dragonestia.picker.repository;
|
package ru.dragonestia.picker.repository;
|
||||||
|
|
||||||
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
|
import ru.dragonestia.picker.exception.AlreadyExistsException;
|
||||||
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
|
import ru.dragonestia.picker.exception.NoRoomsAvailableException;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -12,13 +13,13 @@ import java.util.Set;
|
|||||||
|
|
||||||
public interface RoomRepository {
|
public interface RoomRepository {
|
||||||
|
|
||||||
void create(Room room) throws RoomAlreadyExistException;
|
void create(Room room) throws AlreadyExistsException;
|
||||||
|
|
||||||
void remove(Room room);
|
void remove(InstanceId instanceId, RoomId roomId);
|
||||||
|
|
||||||
Optional<Room> find(Instance instance, String identifier);
|
Optional<Room> find(InstanceId instanceId, RoomId roomId);
|
||||||
|
|
||||||
Collection<Room> all(Instance instance);
|
Collection<Room> all(InstanceId instanceId);
|
||||||
|
|
||||||
Room pick(Instance instance, Set<Entity> entities) throws NoRoomsAvailableException;
|
Room pick(InstanceId instanceId, Set<EntityId> entities) throws NoRoomsAvailableException;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,9 @@ package ru.dragonestia.picker.repository.impl;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import ru.dragonestia.picker.api.exception.InstanceAlreadyExistException;
|
import ru.dragonestia.picker.exception.AlreadyExistsException;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
|
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
|
||||||
import ru.dragonestia.picker.repository.impl.type.EntityTransaction;
|
import ru.dragonestia.picker.repository.impl.type.EntityTransaction;
|
||||||
|
|
||||||
@ -15,25 +16,25 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
@Component
|
@Component
|
||||||
public class ContainerRepository {
|
public class ContainerRepository {
|
||||||
|
|
||||||
private final Map<String, InstanceContainer> containers = new ConcurrentHashMap<>();
|
private final Map<InstanceId, InstanceContainer> containers = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private EntityTransaction.Listener transactionListener = transaction -> {};
|
private EntityTransaction.Listener transactionListener = transaction -> {};
|
||||||
|
|
||||||
public void create(Instance instance) throws InstanceAlreadyExistException {
|
public void create(Instance instance) throws AlreadyExistsException {
|
||||||
if (containers.containsKey(instance.getIdentifier())) {
|
if (containers.containsKey(instance.getId())) {
|
||||||
throw new InstanceAlreadyExistException(instance.getIdentifier());
|
throw AlreadyExistsException.forInstance(instance.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
var container = new InstanceContainer(instance, transactionListener);
|
var container = new InstanceContainer(instance, transactionListener);
|
||||||
containers.put(instance.getIdentifier(), container);
|
containers.put(instance.getId(), container);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(@NotNull String instanceId) {
|
public void remove(InstanceId id) {
|
||||||
containers.remove(instanceId);
|
containers.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Optional<InstanceContainer> findById(@NotNull String instanceId) {
|
public @NotNull Optional<InstanceContainer> findById(InstanceId id) {
|
||||||
return Optional.ofNullable(containers.get(instanceId));
|
return Optional.ofNullable(containers.get(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Collection<InstanceContainer> all() {
|
public @NotNull Collection<InstanceContainer> all() {
|
||||||
|
|||||||
@ -3,9 +3,9 @@ package ru.dragonestia.picker.repository.impl;
|
|||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import ru.dragonestia.picker.api.exception.InstanceNotFoundException;
|
import ru.dragonestia.picker.exception.DoesNotExistsException;
|
||||||
import ru.dragonestia.picker.api.exception.RoomAreFullException;
|
import ru.dragonestia.picker.exception.RoomAreFullException;
|
||||||
import ru.dragonestia.picker.api.exception.RoomNotFoundException;
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
import ru.dragonestia.picker.repository.EntityRepository;
|
import ru.dragonestia.picker.repository.EntityRepository;
|
||||||
@ -20,14 +20,14 @@ public class EntityRepositoryImpl implements EntityRepository {
|
|||||||
|
|
||||||
private final ContainerRepository containerRepository;
|
private final ContainerRepository containerRepository;
|
||||||
|
|
||||||
private final Map<Entity, Set<Room>> entityRooms = new ConcurrentHashMap<>();
|
private final Map<EntityId, Set<Room>> entityRooms = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
void init() {
|
void init() {
|
||||||
containerRepository.setTransactionListener(transaction -> {
|
containerRepository.setTransactionListener(transaction -> {
|
||||||
synchronized (entityRooms) {
|
synchronized (entityRooms) {
|
||||||
for (var entity: transaction.target()) {
|
for (var entity: transaction.target()) {
|
||||||
var set = entityRooms.computeIfAbsent(entity, k -> new HashSet<>());
|
var set = entityRooms.computeIfAbsent(entity.getId(), k -> new HashSet<>());
|
||||||
set.add(transaction.room());
|
set.add(transaction.room());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,9 +35,9 @@ public class EntityRepositoryImpl implements EntityRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void linkWithRoom(Room room, Collection<Entity> entities, boolean force) throws RoomAreFullException {
|
public void linkWithRoom(Room room, Collection<EntityId> entities, boolean force) throws RoomAreFullException {
|
||||||
synchronized (entityRooms) {
|
synchronized (entityRooms) {
|
||||||
getRoomContainer(room).addEntities(entities, force);
|
getRoomContainer(room).addEntities(entities.stream().map(Entity::new).toList(), force);
|
||||||
|
|
||||||
for (var entity: entities) {
|
for (var entity: entities) {
|
||||||
var set = entityRooms.computeIfAbsent(entity, k -> new HashSet<>());
|
var set = entityRooms.computeIfAbsent(entity, k -> new HashSet<>());
|
||||||
@ -47,9 +47,9 @@ public class EntityRepositoryImpl implements EntityRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unlinkWithRoom(Room room, Collection<Entity> entities) {
|
public void unlinkWithRoom(Room room, Collection<EntityId> entities) {
|
||||||
synchronized (entityRooms) {
|
synchronized (entityRooms) {
|
||||||
getRoomContainer(room).removeEntities(entities);
|
getRoomContainer(room).removeEntities(entities.stream().map(Entity::new).toList());
|
||||||
|
|
||||||
for (var entity: entities) {
|
for (var entity: entities) {
|
||||||
var set = entityRooms.get(entity);
|
var set = entityRooms.get(entity);
|
||||||
@ -61,7 +61,7 @@ public class EntityRepositoryImpl implements EntityRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Room> findAllLinkedEntityRooms(Entity entity) {
|
public Collection<Room> findAllLinkedEntityRooms(EntityId entity) {
|
||||||
var result = entityRooms.get(entity);
|
var result = entityRooms.get(entity);
|
||||||
return Collections.unmodifiableSet(result == null? new HashSet<>() : result);
|
return Collections.unmodifiableSet(result == null? new HashSet<>() : result);
|
||||||
}
|
}
|
||||||
@ -72,8 +72,12 @@ public class EntityRepositoryImpl implements EntityRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Entity> search(String input) {
|
public Collection<Entity> search(EntityId input) {
|
||||||
return entityRooms.keySet().stream().filter(entity -> entity.getIdentifier().startsWith(input)).toList();
|
var inputStr = input.getValue();
|
||||||
|
return entityRooms.keySet().stream()
|
||||||
|
.filter(entity -> entity.getValue().startsWith(inputStr))
|
||||||
|
.map(Entity::new)
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -82,14 +86,14 @@ public class EntityRepositoryImpl implements EntityRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Integer> countEntitiesForNodes() {
|
public Map<String, Integer> countEntitiesForInstances() {
|
||||||
var result = new HashMap<String, Integer>();
|
var result = new HashMap<String, Integer>();
|
||||||
|
|
||||||
containerRepository.all().forEach(nodeContainer -> {
|
containerRepository.all().forEach(nodeContainer -> {
|
||||||
var nodeId = nodeContainer.getInstance().getIdentifier();
|
var nodeId = nodeContainer.getInstance().getId();
|
||||||
|
|
||||||
nodeContainer.allRooms().forEach(roomContainer -> {
|
nodeContainer.allRooms().forEach(roomContainer -> {
|
||||||
result.put(nodeId, result.getOrDefault(nodeId, 0) + roomContainer.countEntities());
|
result.put(nodeId.getValue(), result.getOrDefault(nodeId.getValue(), 0) + roomContainer.countEntities());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -97,9 +101,9 @@ public class EntityRepositoryImpl implements EntityRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private RoomContainer getRoomContainer(Room room) {
|
private RoomContainer getRoomContainer(Room room) {
|
||||||
return containerRepository.findById(room.getInstanceIdentifier())
|
return containerRepository.findById(room.getInstance().getId())
|
||||||
.orElseThrow(() -> new InstanceNotFoundException(room.getInstanceIdentifier()))
|
.orElseThrow(() -> DoesNotExistsException.forInstance(room.getInstance().getId()))
|
||||||
.findRoomById(room.getIdentifier())
|
.findRoomById(room.getId())
|
||||||
.orElseThrow(() -> new RoomNotFoundException(room.getInstanceIdentifier(), room.getIdentifier()));
|
.orElseThrow(() -> DoesNotExistsException.forRoom(room.getId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,9 @@ package ru.dragonestia.picker.repository.impl;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import ru.dragonestia.picker.api.exception.InstanceAlreadyExistException;
|
import ru.dragonestia.picker.exception.AlreadyExistsException;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
import ru.dragonestia.picker.repository.InstanceRepository;
|
import ru.dragonestia.picker.repository.InstanceRepository;
|
||||||
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
|
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
|
||||||
|
|
||||||
@ -17,18 +18,18 @@ public class InstanceRepositoryImpl implements InstanceRepository {
|
|||||||
private final ContainerRepository containerRepository;
|
private final ContainerRepository containerRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(Instance instance) throws InstanceAlreadyExistException {
|
public void create(Instance instance) throws AlreadyExistsException {
|
||||||
containerRepository.create(instance);
|
containerRepository.create(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(Instance instance) {
|
public void delete(InstanceId instanceId) {
|
||||||
containerRepository.remove(instance.getIdentifier());
|
containerRepository.remove(instanceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Instance> findById(String nodeId) {
|
public Optional<Instance> findById(InstanceId id) {
|
||||||
return containerRepository.findById(nodeId).map(InstanceContainer::getInstance);
|
return containerRepository.findById(id).map(InstanceContainer::getInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -2,12 +2,13 @@ package ru.dragonestia.picker.repository.impl;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
|
import ru.dragonestia.picker.exception.AlreadyExistsException;
|
||||||
import ru.dragonestia.picker.api.exception.InstanceNotFoundException;
|
import ru.dragonestia.picker.exception.DoesNotExistsException;
|
||||||
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
|
import ru.dragonestia.picker.exception.NoRoomsAvailableException;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
import ru.dragonestia.picker.repository.RoomRepository;
|
import ru.dragonestia.picker.repository.RoomRepository;
|
||||||
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
|
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
|
||||||
|
|
||||||
@ -22,39 +23,39 @@ public class RoomRepositoryImpl implements RoomRepository {
|
|||||||
private final ContainerRepository containerRepository;
|
private final ContainerRepository containerRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(Room room) throws RoomAlreadyExistException {
|
public void create(Room room) throws AlreadyExistsException {
|
||||||
containerRepository.findById(room.getInstanceIdentifier())
|
containerRepository.findById(room.getInstance().getId())
|
||||||
.orElseThrow(() -> new InstanceNotFoundException(room.getInstanceIdentifier()))
|
.orElseThrow(() -> DoesNotExistsException.forInstance(room.getInstance().getId()))
|
||||||
.addRoom(room);
|
.addRoom(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(Room room) {
|
public void remove(InstanceId instanceId, RoomId roomId) {
|
||||||
containerRepository.findById(room.getInstanceIdentifier())
|
containerRepository.findById(instanceId)
|
||||||
.orElseThrow(() -> new InstanceNotFoundException(room.getInstanceIdentifier()))
|
.orElseThrow(() -> DoesNotExistsException.forInstance(instanceId))
|
||||||
.removeRoom(room);
|
.removeRoom(roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Room> find(Instance instance, String identifier) {
|
public Optional<Room> find(InstanceId instanceId, RoomId roomId) {
|
||||||
return containerRepository.findById(instance.getIdentifier())
|
return containerRepository.findById(instanceId)
|
||||||
.orElseThrow(() -> new InstanceNotFoundException(instance.getIdentifier()))
|
.orElseThrow(() -> DoesNotExistsException.forInstance(instanceId))
|
||||||
.findRoomById(identifier)
|
.findRoomById(roomId)
|
||||||
.map(RoomContainer::getRoom);
|
.map(RoomContainer::getRoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Room> all(Instance instance) {
|
public Collection<Room> all(InstanceId instanceId) {
|
||||||
return containerRepository.findById(instance.getIdentifier())
|
return containerRepository.findById(instanceId)
|
||||||
.orElseThrow(() -> new InstanceNotFoundException(instance.getIdentifier()))
|
.orElseThrow(() -> DoesNotExistsException.forInstance(instanceId))
|
||||||
.allRooms()
|
.allRooms()
|
||||||
.stream().map(RoomContainer::getRoom).toList();
|
.stream().map(RoomContainer::getRoom).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Room pick(Instance instance, Set<Entity> entities) throws NoRoomsAvailableException {
|
public Room pick(InstanceId instanceId, Set<EntityId> entities) throws NoRoomsAvailableException {
|
||||||
return containerRepository.findById(instance.getIdentifier())
|
return containerRepository.findById(instanceId)
|
||||||
.orElseThrow(() -> new InstanceNotFoundException(instance.getIdentifier()))
|
.orElseThrow(() -> DoesNotExistsException.forInstance(instanceId))
|
||||||
.pick(entities);
|
.pick(entities);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
package ru.dragonestia.picker.repository.impl.container;
|
package ru.dragonestia.picker.repository.impl.container;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import ru.dragonestia.picker.exception.AlreadyExistsException;
|
||||||
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
import ru.dragonestia.picker.repository.impl.picker.LeastPickedPicker;
|
import ru.dragonestia.picker.repository.impl.picker.LeastPickedPicker;
|
||||||
import ru.dragonestia.picker.repository.impl.picker.RoomPicker;
|
import ru.dragonestia.picker.repository.impl.picker.RoomPicker;
|
||||||
import ru.dragonestia.picker.repository.impl.picker.RoundRobinPicker;
|
import ru.dragonestia.picker.repository.impl.picker.RoundRobinPicker;
|
||||||
@ -19,21 +20,20 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||||||
|
|
||||||
public class InstanceContainer {
|
public class InstanceContainer {
|
||||||
|
|
||||||
@Getter
|
@Getter private final Instance instance;
|
||||||
private final Instance instance;
|
|
||||||
private final EntityTransaction.Listener transactionListener;
|
private final EntityTransaction.Listener transactionListener;
|
||||||
private final RoomPicker picker;
|
@Getter private final RoomPicker picker;
|
||||||
|
|
||||||
private final ReadWriteLock roomLock = new ReentrantReadWriteLock();
|
private final ReadWriteLock roomLock = new ReentrantReadWriteLock();
|
||||||
private final Map<String, RoomContainer> rooms = new ConcurrentHashMap<>();
|
private final Map<RoomId, RoomContainer> rooms = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public InstanceContainer(@NotNull Instance instance, @NotNull EntityTransaction.Listener transactionListener) {
|
public InstanceContainer(Instance instance, EntityTransaction.Listener transactionListener) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.transactionListener = transactionListener;
|
this.transactionListener = transactionListener;
|
||||||
this.picker = initPicker();
|
this.picker = initPicker();
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull RoomPicker initPicker() {
|
private RoomPicker initPicker() {
|
||||||
return switch (instance.getPickingMethod()) {
|
return switch (instance.getPickingMethod()) {
|
||||||
case SEQUENTIAL_FILLING -> new SequentialFillingPicker(this);
|
case SEQUENTIAL_FILLING -> new SequentialFillingPicker(this);
|
||||||
case ROUND_ROBIN -> new RoundRobinPicker(this);
|
case ROUND_ROBIN -> new RoundRobinPicker(this);
|
||||||
@ -41,31 +41,31 @@ public class InstanceContainer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addRoom(Room room) throws RoomAlreadyExistException {
|
public void addRoom(Room room) throws AlreadyExistsException {
|
||||||
roomLock.writeLock().lock();
|
roomLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
if (rooms.containsKey(room.getIdentifier())) {
|
if (rooms.containsKey(room.getId())) {
|
||||||
throw new RoomAlreadyExistException(instance.getIdentifier(), room.getIdentifier());
|
throw AlreadyExistsException.forRoom(instance.getId(), room.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
var container = new RoomContainer(room, this);
|
var container = new RoomContainer(room, this);
|
||||||
rooms.put(room.getIdentifier(), container);
|
rooms.put(room.getId(), container);
|
||||||
picker.add(container);
|
picker.add(container);
|
||||||
} finally {
|
} finally {
|
||||||
roomLock.writeLock().unlock();
|
roomLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeRoom(@NotNull Room room) {
|
public void removeRoom(RoomId roomId) {
|
||||||
roomLock.writeLock().lock();
|
roomLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
picker.remove(rooms.remove(room.getIdentifier()));
|
picker.remove(rooms.remove(roomId));
|
||||||
} finally {
|
} finally {
|
||||||
roomLock.writeLock().unlock();
|
roomLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeRoomsByIds(@NotNull Collection<String> roomIds) {
|
public void removeRoomsByIds(Collection<RoomId> roomIds) {
|
||||||
roomLock.writeLock().lock();
|
roomLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
roomIds.forEach(roomId -> picker.remove(rooms.remove(roomId)));
|
roomIds.forEach(roomId -> picker.remove(rooms.remove(roomId)));
|
||||||
@ -74,7 +74,7 @@ public class InstanceContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Optional<RoomContainer> findRoomById(@NotNull String roomId) {
|
public Optional<RoomContainer> findRoomById(RoomId roomId) {
|
||||||
roomLock.readLock().lock();
|
roomLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
return Optional.ofNullable(rooms.get(roomId));
|
return Optional.ofNullable(rooms.get(roomId));
|
||||||
@ -83,7 +83,7 @@ public class InstanceContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Collection<RoomContainer> allRooms() {
|
public Collection<RoomContainer> allRooms() {
|
||||||
roomLock.readLock().lock();
|
roomLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
return rooms.values();
|
return rooms.values();
|
||||||
@ -92,16 +92,16 @@ public class InstanceContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Room pick(@NotNull Set<Entity> entities) {
|
public Room pick(Set<EntityId> entities) {
|
||||||
|
var entitiesObj = entities.stream()
|
||||||
|
.map(Entity::new)
|
||||||
|
.toList(); // TODO: find entities
|
||||||
|
|
||||||
synchronized (picker) {
|
synchronized (picker) {
|
||||||
var room = picker.pick(entities);
|
var room = picker.pick(entitiesObj);
|
||||||
room.addEntities(entities, false);
|
room.addEntities(entitiesObj, false);
|
||||||
transactionListener.accept(new EntityTransaction(room.getRoom(), entities));
|
transactionListener.accept(new EntityTransaction(room.getRoom(), entitiesObj));
|
||||||
return room.getRoom();
|
return room.getRoom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull RoomPicker getPicker() {
|
|
||||||
return picker;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package ru.dragonestia.picker.repository.impl.container;
|
|||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import ru.dragonestia.picker.api.exception.RoomAreFullException;
|
import ru.dragonestia.picker.exception.RoomAreFullException;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
import ru.dragonestia.picker.repository.impl.picker.LeastPickedPicker;
|
import ru.dragonestia.picker.repository.impl.picker.LeastPickedPicker;
|
||||||
@ -32,7 +32,7 @@ public class RoomContainer {
|
|||||||
entities.addAll(toAdd);
|
entities.addAll(toAdd);
|
||||||
noticePickersAboutEntityNumberUpdate();
|
noticePickersAboutEntityNumberUpdate();
|
||||||
} else {
|
} else {
|
||||||
throw new RoomAreFullException(room.getInstanceIdentifier(), room.getIdentifier());
|
throw new RoomAreFullException(room.getInstance().getId(), room.getId());
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
entityLock.writeLock().unlock();
|
entityLock.writeLock().unlock();
|
||||||
@ -75,7 +75,7 @@ public class RoomContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean canAdd0(int entities) {
|
private boolean canAdd0(int entities) {
|
||||||
return room.hasUnlimitedSlots() || entities + countEntities() <= room.getMaxSlots();
|
return room.getSlots() == -1 || entities + countEntities() <= room.getSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canAdd(int entities) {
|
public boolean canAdd(int entities) {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
package ru.dragonestia.picker.repository.impl.picker;
|
package ru.dragonestia.picker.repository.impl.picker;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
|
import ru.dragonestia.picker.exception.NoRoomsAvailableException;
|
||||||
import ru.dragonestia.picker.api.model.node.PickingMethod;
|
import ru.dragonestia.picker.model.instance.type.PickingMethod;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
import ru.dragonestia.picker.repository.impl.collection.DynamicSortedMap;
|
import ru.dragonestia.picker.repository.impl.collection.DynamicSortedMap;
|
||||||
@ -27,7 +27,7 @@ public class LeastPickedPicker implements RoomPicker {
|
|||||||
@Override
|
@Override
|
||||||
public void remove(RoomContainer container) {
|
public void remove(RoomContainer container) {
|
||||||
synchronized (map) {
|
synchronized (map) {
|
||||||
map.removeById(container.getRoom().getIdentifier());
|
map.removeById(container.getRoom().getId().getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ public class LeastPickedPicker implements RoomPicker {
|
|||||||
|
|
||||||
if (!wrapper.canAddUnits(entities.size())) throw new RuntimeException();
|
if (!wrapper.canAddUnits(entities.size())) throw new RuntimeException();
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw new NoRoomsAvailableException(container.getInstance().getIdentifier());
|
throw new NoRoomsAvailableException(container.getInstance().getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ public class LeastPickedPicker implements RoomPicker {
|
|||||||
|
|
||||||
public void updateEntitiesAmount(Room room, int users) {
|
public void updateEntitiesAmount(Room room, int users) {
|
||||||
synchronized (map) {
|
synchronized (map) {
|
||||||
map.updateItem(room.getIdentifier(), prevValue -> users);
|
map.updateItem(room.getId().getValue(), prevValue -> users);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package ru.dragonestia.picker.repository.impl.picker;
|
package ru.dragonestia.picker.repository.impl.picker;
|
||||||
|
|
||||||
import ru.dragonestia.picker.api.model.node.PickingMethod;
|
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
|
import ru.dragonestia.picker.model.instance.type.PickingMethod;
|
||||||
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
|
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
|
||||||
|
|
||||||
public interface RoomPicker extends Picker<RoomContainer, Entity> {
|
public interface RoomPicker extends Picker<RoomContainer, Entity> {
|
||||||
|
|||||||
@ -17,7 +17,7 @@ public class RoomWrapper implements ItemWrapper<RoomContainer>, QueuedLinkedList
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return container.getRoom().getIdentifier();
|
return container.getRoom().getId().getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -27,7 +27,7 @@ public class RoomWrapper implements ItemWrapper<RoomContainer>, QueuedLinkedList
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int maxUnits() {
|
public int maxUnits() {
|
||||||
return container.getRoom().getMaxSlots();
|
return container.getRoom().getSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
package ru.dragonestia.picker.repository.impl.picker;
|
package ru.dragonestia.picker.repository.impl.picker;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
|
import ru.dragonestia.picker.exception.NoRoomsAvailableException;
|
||||||
import ru.dragonestia.picker.api.model.node.PickingMethod;
|
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
|
import ru.dragonestia.picker.model.instance.type.PickingMethod;
|
||||||
import ru.dragonestia.picker.repository.impl.collection.QueuedLinkedList;
|
import ru.dragonestia.picker.repository.impl.collection.QueuedLinkedList;
|
||||||
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
|
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
|
||||||
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
|
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
|
||||||
@ -28,7 +28,7 @@ public class RoundRobinPicker implements RoomPicker {
|
|||||||
@Override
|
@Override
|
||||||
public void remove(RoomContainer container) {
|
public void remove(RoomContainer container) {
|
||||||
synchronized (list) {
|
synchronized (list) {
|
||||||
list.removeById(container.getRoom().getIdentifier());
|
list.removeById(container.getRoom().getId().getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ public class RoundRobinPicker implements RoomPicker {
|
|||||||
addition.set(amount);
|
addition.set(amount);
|
||||||
wrapper = list.pick();
|
wrapper = list.pick();
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw new NoRoomsAvailableException(container.getInstance().getIdentifier());
|
throw new NoRoomsAvailableException(container.getInstance().getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
package ru.dragonestia.picker.repository.impl.picker;
|
package ru.dragonestia.picker.repository.impl.picker;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
|
import ru.dragonestia.picker.exception.NoRoomsAvailableException;
|
||||||
import ru.dragonestia.picker.api.model.node.PickingMethod;
|
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
|
import ru.dragonestia.picker.model.instance.type.PickingMethod;
|
||||||
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
|
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
|
||||||
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
|
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
|
||||||
|
|
||||||
@ -20,14 +20,14 @@ public class SequentialFillingPicker implements RoomPicker {
|
|||||||
@Override
|
@Override
|
||||||
public void add(RoomContainer container) {
|
public void add(RoomContainer container) {
|
||||||
synchronized (wrappers) {
|
synchronized (wrappers) {
|
||||||
wrappers.put(container.getRoom().getIdentifier(), new RoomWrapper(container));
|
wrappers.put(container.getRoom().getId().getValue(), new RoomWrapper(container));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(RoomContainer container) {
|
public void remove(RoomContainer container) {
|
||||||
synchronized (wrappers) {
|
synchronized (wrappers) {
|
||||||
wrappers.remove(container.getRoom().getIdentifier());
|
wrappers.remove(container.getRoom().getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ public class SequentialFillingPicker implements RoomPicker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NoRoomsAvailableException(container.getInstance().getIdentifier());
|
throw new NoRoomsAvailableException(container.getInstance().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package ru.dragonestia.picker.service;
|
package ru.dragonestia.picker.service;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import ru.dragonestia.picker.model.account.Account;
|
import ru.dragonestia.picker.model.account.Account;
|
||||||
|
import ru.dragonestia.picker.model.account.AccountId;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -12,18 +12,18 @@ import java.util.Optional;
|
|||||||
public interface AccountService extends UserDetailsService {
|
public interface AccountService extends UserDetailsService {
|
||||||
|
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
@NotNull Account createNewAccount(@NotNull String username, @NotNull String password);
|
Account createNewAccount(AccountId id, String password);
|
||||||
|
|
||||||
@NotNull Optional<Account> findAccount(@NotNull String accountId);
|
Optional<Account> findAccount(String accountId);
|
||||||
|
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
@NotNull Collection<Account> allAccounts();
|
Collection<Account> allAccounts();
|
||||||
|
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
void removeAccount(@NotNull Account account);
|
void removeAccount(Account account);
|
||||||
|
|
||||||
@PreAuthorize("hasRole('ADMIN') || principal.username.equals(account.username)")
|
@PreAuthorize("hasRole('ADMIN') || principal.username.equals(account.username)")
|
||||||
void updateState(@NotNull Account account);
|
void updateState(Account account);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Account loadUserByUsername(String username) throws UsernameNotFoundException;
|
Account loadUserByUsername(String username) throws UsernameNotFoundException;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package ru.dragonestia.picker.service;
|
package ru.dragonestia.picker.service;
|
||||||
|
|
||||||
import ru.dragonestia.picker.api.exception.RoomAreFullException;
|
import ru.dragonestia.picker.exception.RoomAreFullException;
|
||||||
import ru.dragonestia.picker.api.model.user.ResponseUser;
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
|
|
||||||
@ -10,15 +10,13 @@ import java.util.List;
|
|||||||
|
|
||||||
public interface EntityService {
|
public interface EntityService {
|
||||||
|
|
||||||
Collection<Room> getEntityRooms(Entity entity);
|
Collection<Room> getEntityRooms(EntityId id);
|
||||||
|
|
||||||
void linkEntitiesWithRoom(Room room, Collection<Entity> entities, boolean force) throws RoomAreFullException;
|
void linkEntitiesWithRoom(Room room, Collection<EntityId> entities, boolean force) throws RoomAreFullException;
|
||||||
|
|
||||||
void unlinkEntitiesFromRoom(Room room, Collection<Entity> entities);
|
void unlinkEntitiesFromRoom(Room room, Collection<EntityId> entities);
|
||||||
|
|
||||||
Collection<Entity> getRoomEntities(Room room);
|
Collection<Entity> getRoomEntities(Room room);
|
||||||
|
|
||||||
List<ResponseUser> searchEntities(String input);
|
List<Entity> searchEntities(EntityId input);
|
||||||
|
|
||||||
ResponseUser getEntityDetails(String userId);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
package ru.dragonestia.picker.service;
|
package ru.dragonestia.picker.service;
|
||||||
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import ru.dragonestia.picker.api.exception.InvalidInstanceIdentifierException;
|
import ru.dragonestia.picker.exception.AlreadyExistsException;
|
||||||
import ru.dragonestia.picker.api.exception.InstanceAlreadyExistException;
|
import ru.dragonestia.picker.exception.InvalidIdentifierException;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -11,12 +12,12 @@ import java.util.Optional;
|
|||||||
public interface InstanceService {
|
public interface InstanceService {
|
||||||
|
|
||||||
@PreAuthorize("hasRole('NODE_MANAGEMENT')")
|
@PreAuthorize("hasRole('NODE_MANAGEMENT')")
|
||||||
void create(Instance instance) throws InvalidInstanceIdentifierException, InstanceAlreadyExistException;
|
void create(Instance instance) throws InvalidIdentifierException, AlreadyExistsException;
|
||||||
|
|
||||||
@PreAuthorize("hasRole('NODE_MANAGEMENT')")
|
@PreAuthorize("hasRole('NODE_MANAGEMENT')")
|
||||||
void remove(Instance instance);
|
void remove(Instance instance);
|
||||||
|
|
||||||
List<Instance> all();
|
List<Instance> all();
|
||||||
|
|
||||||
Optional<Instance> find(String nodeId);
|
Optional<Instance> find(InstanceId id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
package ru.dragonestia.picker.service;
|
package ru.dragonestia.picker.service;
|
||||||
|
|
||||||
import ru.dragonestia.picker.api.exception.InvalidRoomIdentifierException;
|
import ru.dragonestia.picker.exception.AlreadyExistsException;
|
||||||
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
|
import ru.dragonestia.picker.exception.InvalidIdentifierException;
|
||||||
import ru.dragonestia.picker.api.repository.response.PickedRoomResponse;
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -13,15 +13,15 @@ import java.util.Set;
|
|||||||
|
|
||||||
public interface RoomService {
|
public interface RoomService {
|
||||||
|
|
||||||
void create(Room room) throws InvalidRoomIdentifierException, RoomAlreadyExistException;
|
void create(Room room) throws InvalidIdentifierException, AlreadyExistsException;
|
||||||
|
|
||||||
void remove(Room room);
|
void remove(Room room);
|
||||||
|
|
||||||
Optional<Room> find(Instance instance, String roomId);
|
Optional<Room> find(InstanceId instanceId, RoomId roomId);
|
||||||
|
|
||||||
Collection<Room> all(Instance instance);
|
Collection<Room> all(InstanceId instanceId);
|
||||||
|
|
||||||
PickedRoomResponse pickAvailable(Instance instance, Set<Entity> entities);
|
Room pick(InstanceId instanceId, Set<EntityId> entities);
|
||||||
|
|
||||||
void updateState(Room room);
|
void updateState(Room room);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,13 +2,13 @@ package ru.dragonestia.picker.service.impl;
|
|||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.dragonestia.picker.api.exception.ConstantAdminParamsException;
|
|
||||||
import ru.dragonestia.picker.config.RoomPickerServerConfig;
|
import ru.dragonestia.picker.config.RoomPickerServerConfig;
|
||||||
|
import ru.dragonestia.picker.exception.AdminAccountMutationException;
|
||||||
import ru.dragonestia.picker.model.account.Account;
|
import ru.dragonestia.picker.model.account.Account;
|
||||||
|
import ru.dragonestia.picker.model.account.AccountId;
|
||||||
import ru.dragonestia.picker.model.account.Permission;
|
import ru.dragonestia.picker.model.account.Permission;
|
||||||
import ru.dragonestia.picker.service.AccountService;
|
import ru.dragonestia.picker.service.AccountService;
|
||||||
|
|
||||||
@ -30,39 +30,39 @@ public class AccountServiceImpl implements AccountService {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
void init() {
|
void init() {
|
||||||
var account = createNewAccount(adminCredentials.username(), adminCredentials.password());
|
var account = createNewAccount(AccountId.of(adminCredentials.username()), adminCredentials.password());
|
||||||
account.setAuthorities(Arrays.stream(Permission.values()).collect(Collectors.toSet()));
|
account.setAuthorities(Arrays.stream(Permission.values()).collect(Collectors.toSet()));
|
||||||
|
|
||||||
createNewAccount("test", "qwerty123");
|
createNewAccount(AccountId.of("test"), "qwerty123");
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Account createNewAccount(@NotNull String username, @NotNull String password) {
|
public Account createNewAccount(AccountId id, String password) {
|
||||||
var account = new Account(username, passwordEncoder.encode(password));
|
var account = new Account(id, passwordEncoder.encode(password));
|
||||||
accounts.put(account.getUsername().toLowerCase(), account);
|
accounts.put(account.getUsername().toLowerCase(), account);
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Optional<Account> findAccount(@NotNull String accountId) {
|
public Optional<Account> findAccount(String accountId) {
|
||||||
return Optional.ofNullable(accounts.getOrDefault(accountId, null));
|
return Optional.ofNullable(accounts.getOrDefault(accountId, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Collection<Account> allAccounts() {
|
public Collection<Account> allAccounts() {
|
||||||
return accounts.values().stream()
|
return accounts.values().stream()
|
||||||
.filter(account -> !adminCredentials.username().equals(account.getUsername()))
|
.filter(account -> !adminCredentials.username().equals(account.getUsername()))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAccount(@NotNull Account account) {
|
public void removeAccount(Account account) {
|
||||||
checkAdmin(account.getUsername());
|
checkAdmin(account.getUsername());
|
||||||
accounts.remove(account.getUsername());
|
accounts.remove(account.getUsername());
|
||||||
account.setEnabled(false);
|
account.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateState(@NotNull Account account) {
|
public void updateState(Account account) {
|
||||||
checkAdmin(account.getUsername());
|
checkAdmin(account.getUsername());
|
||||||
// TODO: save data to local storage
|
// TODO: save data to local storage
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ public class AccountServiceImpl implements AccountService {
|
|||||||
|
|
||||||
private void checkAdmin(String accountId) {
|
private void checkAdmin(String accountId) {
|
||||||
if (adminCredentials.username().equals(accountId)) {
|
if (adminCredentials.username().equals(accountId)) {
|
||||||
throw new ConstantAdminParamsException();
|
throw new AdminAccountMutationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package ru.dragonestia.picker.service.impl;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.dragonestia.picker.api.model.user.ResponseUser;
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
import ru.dragonestia.picker.repository.EntityRepository;
|
import ru.dragonestia.picker.repository.EntityRepository;
|
||||||
@ -17,17 +17,17 @@ public class EntityServiceImpl implements EntityService {
|
|||||||
private final EntityRepository entityRepository;
|
private final EntityRepository entityRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Room> getEntityRooms(Entity entity) {
|
public Collection<Room> getEntityRooms(EntityId id) {
|
||||||
return entityRepository.findAllLinkedEntityRooms(entity);
|
return entityRepository.findAllLinkedEntityRooms(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void linkEntitiesWithRoom(Room room, Collection<Entity> entities, boolean force) {
|
public void linkEntitiesWithRoom(Room room, Collection<EntityId> entities, boolean force) {
|
||||||
entityRepository.linkWithRoom(room, entities, force);
|
entityRepository.linkWithRoom(room, entities, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unlinkEntitiesFromRoom(Room room, Collection<Entity> entities) {
|
public void unlinkEntitiesFromRoom(Room room, Collection<EntityId> entities) {
|
||||||
entityRepository.unlinkWithRoom(room, entities);
|
entityRepository.unlinkWithRoom(room, entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,12 +37,7 @@ public class EntityServiceImpl implements EntityService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ResponseUser> searchEntities(String input) {
|
public List<Entity> searchEntities(EntityId input) {
|
||||||
return entityRepository.search(input).stream().map(Entity::toResponseObject).toList();
|
return entityRepository.search(input).stream().toList();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResponseUser getEntityDetails(String userId) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,10 @@ package ru.dragonestia.picker.service.impl;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.dragonestia.picker.api.exception.InvalidInstanceIdentifierException;
|
import ru.dragonestia.picker.exception.AlreadyExistsException;
|
||||||
import ru.dragonestia.picker.api.exception.InstanceAlreadyExistException;
|
import ru.dragonestia.picker.exception.InvalidIdentifierException;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
import ru.dragonestia.picker.repository.InstanceRepository;
|
import ru.dragonestia.picker.repository.InstanceRepository;
|
||||||
import ru.dragonestia.picker.repository.RoomRepository;
|
import ru.dragonestia.picker.repository.RoomRepository;
|
||||||
import ru.dragonestia.picker.service.InstanceService;
|
import ru.dragonestia.picker.service.InstanceService;
|
||||||
@ -22,18 +23,18 @@ public class InstanceServiceImpl implements InstanceService {
|
|||||||
private final InstanceAndRoomStorage storage;
|
private final InstanceAndRoomStorage storage;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(Instance instance) throws InvalidInstanceIdentifierException, InstanceAlreadyExistException {
|
public void create(Instance instance) throws InvalidIdentifierException, AlreadyExistsException {
|
||||||
instanceRepository.create(instance);
|
instanceRepository.create(instance);
|
||||||
storage.saveInstance(instance);
|
storage.saveInstance(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(Instance instance) {
|
public void remove(Instance instance) {
|
||||||
for (var room: roomRepository.all(instance)) {
|
for (var room: roomRepository.all(instance.getId())) {
|
||||||
storage.removeRoom(room);
|
storage.removeRoom(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceRepository.delete(instance);
|
instanceRepository.delete(instance.getId());
|
||||||
storage.removeInstance(instance);
|
storage.removeInstance(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ public class InstanceServiceImpl implements InstanceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Instance> find(String nodeId) {
|
public Optional<Instance> find(InstanceId id) {
|
||||||
return instanceRepository.findById(nodeId);
|
return instanceRepository.findById(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,14 +3,14 @@ package ru.dragonestia.picker.service.impl;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.dragonestia.picker.api.exception.InvalidRoomIdentifierException;
|
import ru.dragonestia.picker.exception.AlreadyExistsException;
|
||||||
import ru.dragonestia.picker.api.exception.InstanceNotFoundException;
|
import ru.dragonestia.picker.exception.ConflictingPersistParametersException;
|
||||||
import ru.dragonestia.picker.api.exception.NotPersistedNodeException;
|
import ru.dragonestia.picker.exception.DoesNotExistsException;
|
||||||
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
|
import ru.dragonestia.picker.exception.InvalidIdentifierException;
|
||||||
import ru.dragonestia.picker.api.repository.response.PickedRoomResponse;
|
import ru.dragonestia.picker.model.entity.EntityId;
|
||||||
|
import ru.dragonestia.picker.model.instance.InstanceId;
|
||||||
import ru.dragonestia.picker.model.room.Room;
|
import ru.dragonestia.picker.model.room.Room;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.room.RoomId;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
|
||||||
import ru.dragonestia.picker.repository.InstanceRepository;
|
import ru.dragonestia.picker.repository.InstanceRepository;
|
||||||
import ru.dragonestia.picker.repository.RoomRepository;
|
import ru.dragonestia.picker.repository.RoomRepository;
|
||||||
import ru.dragonestia.picker.repository.EntityRepository;
|
import ru.dragonestia.picker.repository.EntityRepository;
|
||||||
@ -18,7 +18,6 @@ import ru.dragonestia.picker.service.RoomService;
|
|||||||
import ru.dragonestia.picker.storage.InstanceAndRoomStorage;
|
import ru.dragonestia.picker.storage.InstanceAndRoomStorage;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
@Service
|
@Service
|
||||||
@ -31,10 +30,12 @@ public class RoomServiceImpl implements RoomService {
|
|||||||
private final InstanceAndRoomStorage storage;
|
private final InstanceAndRoomStorage storage;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(Room room) throws InvalidRoomIdentifierException, RoomAlreadyExistException, NotPersistedNodeException {
|
public void create(Room room) throws InvalidIdentifierException, AlreadyExistsException, ConflictingPersistParametersException {
|
||||||
var node = instanceRepository.findById(room.getInstanceIdentifier()).orElseThrow(() -> new InstanceNotFoundException(room.getInstanceIdentifier()));
|
var instance = instanceRepository.findById(room.getInstance().getId())
|
||||||
if (!node.isPersist() && room.isPersist()) {
|
.orElseThrow(() -> DoesNotExistsException.forInstance(room.getInstance().getId()));
|
||||||
throw new NotPersistedNodeException(node.getIdentifier(), room.getIdentifier());
|
|
||||||
|
if (!instance.isPersist() && room.isPersist()) {
|
||||||
|
throw ConflictingPersistParametersException.forRoom(instance.getId(), room.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
roomRepository.create(room);
|
roomRepository.create(room);
|
||||||
@ -43,34 +44,23 @@ public class RoomServiceImpl implements RoomService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(Room room) {
|
public void remove(Room room) {
|
||||||
roomRepository.remove(room);
|
roomRepository.remove(room.getInstance().getId(), room.getId());
|
||||||
storage.removeRoom(room);
|
storage.removeRoom(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Room> find(Instance instance, String roomId) {
|
public Optional<Room> find(InstanceId instanceId, RoomId roomId) {
|
||||||
return roomRepository.find(instance, roomId);
|
return roomRepository.find(instanceId, roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Room> all(Instance instance) {
|
public Collection<Room> all(InstanceId instanceId) {
|
||||||
return roomRepository.all(instance);
|
return roomRepository.all(instanceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PickedRoomResponse pickAvailable(Instance instance, Set<Entity> entities) {
|
public Room pick(InstanceId instanceId, Set<EntityId> entities) {
|
||||||
var room = roomRepository.pick(instance, entities);
|
return roomRepository.pick(instanceId, entities);
|
||||||
var roomUsers = entityRepository.entitiesOf(room);
|
|
||||||
|
|
||||||
return new PickedRoomResponse(
|
|
||||||
room.getInstanceIdentifier(),
|
|
||||||
room.getIdentifier(),
|
|
||||||
room.getPayload(),
|
|
||||||
room.getMaxSlots(),
|
|
||||||
roomUsers.size(),
|
|
||||||
room.isLocked(),
|
|
||||||
roomUsers.stream().map(Entity::getIdentifier).collect(Collectors.toSet())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -66,7 +66,7 @@ public class FileStorageImpl implements InstanceAndRoomStorage {
|
|||||||
@Override
|
@Override
|
||||||
public void saveInstance(Instance instance) {
|
public void saveInstance(Instance instance) {
|
||||||
if (!instance.isPersist()) return;
|
if (!instance.isPersist()) return;
|
||||||
var instanceFile = new File(path + "/instances/" + instance.getIdentifier() + ".json");
|
var instanceFile = new File(path + "/instances/" + instance.getId() + ".json");
|
||||||
var writer = objectMapper.writer();
|
var writer = objectMapper.writer();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -79,16 +79,16 @@ public class FileStorageImpl implements InstanceAndRoomStorage {
|
|||||||
@Override
|
@Override
|
||||||
public void removeInstance(Instance instance) {
|
public void removeInstance(Instance instance) {
|
||||||
if (!instance.isPersist()) return;
|
if (!instance.isPersist()) return;
|
||||||
new File(path + "/nodes/" + instance.getIdentifier() + ".json").delete();
|
new File(path + "/nodes/" + instance.getId() + ".json").delete();
|
||||||
|
|
||||||
log.info("Removed instance '%s' from disk storage".formatted(instance.getIdentifier()));
|
log.info("Removed instance '%s' from disk storage".formatted(instance.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Override
|
@Override
|
||||||
public void saveRoom(Room room) {
|
public void saveRoom(Room room) {
|
||||||
if (!room.isPersist()) return;
|
if (!room.isPersist()) return;
|
||||||
var roomFile = new File("%s/rooms/%s.%s.json".formatted(path, room.getInstanceIdentifier(), room.getIdentifier()));
|
var roomFile = new File("%s/rooms/%s.%s.json".formatted(path, room.getInstance().getId(), room.getId()));
|
||||||
var writer = objectMapper.writer();
|
var writer = objectMapper.writer();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -101,8 +101,8 @@ public class FileStorageImpl implements InstanceAndRoomStorage {
|
|||||||
@Override
|
@Override
|
||||||
public void removeRoom(Room room) {
|
public void removeRoom(Room room) {
|
||||||
if (!room.isPersist()) return;
|
if (!room.isPersist()) return;
|
||||||
new File("%s/rooms/%s.%s.json".formatted(path, room.getInstanceIdentifier(), room.getIdentifier())).delete();
|
new File("%s/rooms/%s.%s.json".formatted(path, room.getInstance().getId(), room.getId())).delete();
|
||||||
|
|
||||||
log.info("Removed room '%s/%s' from disk storage".formatted(room.getInstanceIdentifier(), room.getIdentifier()));
|
log.info("Removed room '%s/%s' from disk storage".formatted(room.getInstance().getId(), room.getId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import ru.dragonestia.picker.api.repository.type.RoomIdentifier;
|
|||||||
import ru.dragonestia.picker.api.repository.type.EntityIdentifier;
|
import ru.dragonestia.picker.api.repository.type.EntityIdentifier;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
import ru.dragonestia.picker.model.factory.RoomFactory;
|
import ru.dragonestia.picker.model.room.factory.RoomFactory;
|
||||||
import ru.dragonestia.picker.repository.InstanceRepository;
|
import ru.dragonestia.picker.repository.InstanceRepository;
|
||||||
import ru.dragonestia.picker.repository.RoomRepository;
|
import ru.dragonestia.picker.repository.RoomRepository;
|
||||||
import ru.dragonestia.picker.repository.EntityRepository;
|
import ru.dragonestia.picker.repository.EntityRepository;
|
||||||
|
|||||||
@ -48,8 +48,8 @@ public class LeastPickedTests {
|
|||||||
var users = entityRepository.entitiesOf(room);
|
var users = entityRepository.entitiesOf(room);
|
||||||
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
|
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
|
||||||
|
|
||||||
System.out.printf("Room(%s) has %s/%s users. Expected: %s(%s), added: %s%n", room.getIdentifier(), users.size(), slots, expectedRoomId, expectedRoomUsers, usersAmount);
|
System.out.printf("Room(%s) has %s/%s users. Expected: %s(%s), added: %s%n", room.getId(), users.size(), slots, expectedRoomId, expectedRoomUsers, usersAmount);
|
||||||
Assertions.assertEquals(expectedRoomId, room.getIdentifier());
|
Assertions.assertEquals(expectedRoomId, room.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PickingArgumentProvider implements ArgumentsProvider {
|
public static class PickingArgumentProvider implements ArgumentsProvider {
|
||||||
|
|||||||
@ -44,7 +44,7 @@ public class RoundRobinTests {
|
|||||||
var users = entityRepository.entitiesOf(room);
|
var users = entityRepository.entitiesOf(room);
|
||||||
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
|
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
|
||||||
|
|
||||||
Assertions.assertEquals(expectedRoomId, room.getIdentifier());
|
Assertions.assertEquals(expectedRoomId, room.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PickingArgumentProvider implements ArgumentsProvider {
|
public static class PickingArgumentProvider implements ArgumentsProvider {
|
||||||
|
|||||||
@ -48,8 +48,8 @@ public class SequentialFillingTests {
|
|||||||
var users = entityRepository.entitiesOf(room);
|
var users = entityRepository.entitiesOf(room);
|
||||||
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
|
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
|
||||||
|
|
||||||
System.out.printf("Room(%s) has %s/%s users. Expected: %s(%s), added: %s%n", room.getIdentifier(), users.size(), slots, expectedRoomId, expectedRoomUsers, usersAmount);
|
System.out.printf("Room(%s) has %s/%s users. Expected: %s(%s), added: %s%n", room.getId(), users.size(), slots, expectedRoomId, expectedRoomUsers, usersAmount);
|
||||||
Assertions.assertEquals(expectedRoomId, room.getIdentifier());
|
Assertions.assertEquals(expectedRoomId, room.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PickingArgumentProvider implements ArgumentsProvider {
|
public static class PickingArgumentProvider implements ArgumentsProvider {
|
||||||
|
|||||||
@ -24,12 +24,12 @@ public class InstanceServiceTests {
|
|||||||
var node = new Instance(NodeIdentifier.of("test"), PickingMethod.SEQUENTIAL_FILLING, false);
|
var node = new Instance(NodeIdentifier.of("test"), PickingMethod.SEQUENTIAL_FILLING, false);
|
||||||
|
|
||||||
Assertions.assertDoesNotThrow(() -> instanceService.create(node));
|
Assertions.assertDoesNotThrow(() -> instanceService.create(node));
|
||||||
Assertions.assertTrue(instanceService.find(node.getIdentifier()).isPresent());
|
Assertions.assertTrue(instanceService.find(node.getId()).isPresent());
|
||||||
Assertions.assertThrows(InstanceAlreadyExistException.class, () -> instanceService.create(node));
|
Assertions.assertThrows(InstanceAlreadyExistException.class, () -> instanceService.create(node));
|
||||||
|
|
||||||
instanceService.remove(node);
|
instanceService.remove(node);
|
||||||
|
|
||||||
Assertions.assertFalse(() -> instanceService.find(node.getIdentifier()).isPresent());
|
Assertions.assertFalse(() -> instanceService.find(node.getId()).isPresent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@WithMockUser(roles = {"NODE_MANAGEMENT"})
|
@WithMockUser(roles = {"NODE_MANAGEMENT"})
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import ru.dragonestia.picker.api.repository.type.RoomIdentifier;
|
|||||||
import ru.dragonestia.picker.api.repository.type.EntityIdentifier;
|
import ru.dragonestia.picker.api.repository.type.EntityIdentifier;
|
||||||
import ru.dragonestia.picker.model.instance.Instance;
|
import ru.dragonestia.picker.model.instance.Instance;
|
||||||
import ru.dragonestia.picker.model.entity.Entity;
|
import ru.dragonestia.picker.model.entity.Entity;
|
||||||
import ru.dragonestia.picker.model.factory.RoomFactory;
|
import ru.dragonestia.picker.model.room.factory.RoomFactory;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -51,12 +51,12 @@ public class RoomServiceTests {
|
|||||||
var room = roomFactory.create(RoomIdentifier.of("test-room"), instance, IRoom.UNLIMITED_SLOTS, "", false);
|
var room = roomFactory.create(RoomIdentifier.of("test-room"), instance, IRoom.UNLIMITED_SLOTS, "", false);
|
||||||
roomService.create(room);
|
roomService.create(room);
|
||||||
|
|
||||||
Assertions.assertTrue(roomService.find(instance, room.getIdentifier()).isPresent());
|
Assertions.assertTrue(roomService.find(instance, room.getId()).isPresent());
|
||||||
Assertions.assertThrows(RoomAlreadyExistException.class, () -> roomService.create(room));
|
Assertions.assertThrows(RoomAlreadyExistException.class, () -> roomService.create(room));
|
||||||
|
|
||||||
roomService.remove(room);
|
roomService.remove(room);
|
||||||
|
|
||||||
Assertions.assertFalse(roomService.find(instance, room.getIdentifier()).isPresent());
|
Assertions.assertFalse(roomService.find(instance, room.getId()).isPresent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@WithMockUser(roles = {"NODE_MANAGEMENT"})
|
@WithMockUser(roles = {"NODE_MANAGEMENT"})
|
||||||
@ -107,7 +107,7 @@ public class RoomServiceTests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
Assertions.assertEquals("test-room4", roomService.pickAvailable(instance, users).roomId());
|
Assertions.assertEquals("test-room4", roomService.pick(instance, users).roomId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@WithMockUser(roles = {"NODE_MANAGEMENT"})
|
@WithMockUser(roles = {"NODE_MANAGEMENT"})
|
||||||
@ -127,6 +127,6 @@ public class RoomServiceTests {
|
|||||||
Assertions.assertThrows(InstanceNotFoundException.class, () -> roomService.create(room));
|
Assertions.assertThrows(InstanceNotFoundException.class, () -> roomService.create(room));
|
||||||
Assertions.assertThrows(InstanceNotFoundException.class, () -> roomService.remove(room));
|
Assertions.assertThrows(InstanceNotFoundException.class, () -> roomService.remove(room));
|
||||||
Assertions.assertThrows(InstanceNotFoundException.class, () -> roomService.find(node, "Bruh"));
|
Assertions.assertThrows(InstanceNotFoundException.class, () -> roomService.find(node, "Bruh"));
|
||||||
Assertions.assertThrows(InstanceNotFoundException.class, () -> roomService.pickAvailable(node, Set.of(new Entity(EntityIdentifier.of("1")))));
|
Assertions.assertThrows(InstanceNotFoundException.class, () -> roomService.pick(node, Set.of(new Entity(EntityIdentifier.of("1")))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user