Add Game UI logic #255
@@ -0,0 +1,16 @@
|
|||||||
|
## Milestone Achievement
|
||||||
|
<!-- The recommended type is: Task -->
|
||||||
|
|
||||||
|
### Category
|
||||||
|
<!-- Category of the milestone (Process, Product, Presentation) -->
|
||||||
|
|
||||||
|
### Title
|
||||||
|
<!-- Title of the milestone (equal to the title in the milestone catalog (https://p9.dmi.unibas.ch/cs108/2026) -->
|
||||||
|
|
||||||
|
### Rewarded points on completion
|
||||||
|
<!-- Number of points rewarded on completion of the milestone -->
|
||||||
|
|
||||||
|
### Description of milestone
|
||||||
|
<!-- Description of the milestone (equal to the description in the milestone catalog (https://p9.dmi.unibas.ch/cs108/2026) -->
|
||||||
|
|
||||||
|
/label ~achievement
|
||||||
@@ -12,6 +12,7 @@ Since this project is part of a course at the University of Basel, the [Code of
|
|||||||
- [Creating an issue](#creating-an-issue)
|
- [Creating an issue](#creating-an-issue)
|
||||||
- [During implementation](#during-implementation)
|
- [During implementation](#during-implementation)
|
||||||
- [Collaborative work](#collaborative-work)
|
- [Collaborative work](#collaborative-work)
|
||||||
|
- [Milestone Achievements](#milestone-achievements)
|
||||||
- [Git Workflow](#git-workflow)
|
- [Git Workflow](#git-workflow)
|
||||||
- [Creating a branch](#creating-a-branch)
|
- [Creating a branch](#creating-a-branch)
|
||||||
- [Working on a branch](#working-on-a-branch)
|
- [Working on a branch](#working-on-a-branch)
|
||||||
@@ -49,6 +50,20 @@ Issue or Task in GitLab **before** any implementation begins.
|
|||||||
centrally visible and searchable.
|
centrally visible and searchable.
|
||||||
- Before starting work that overlaps with an existing issue, check its comment thread first to avoid duplicating effort.
|
- Before starting work that overlaps with an existing issue, check its comment thread first to avoid duplicating effort.
|
||||||
|
|
||||||
|
### Milestone Achievements
|
||||||
|
For every process and product-related milestone achievement, there is a dedicated milestone task.
|
||||||
|
|
||||||
|
- **Do not create a branch directly from a milestone task.**
|
||||||
|
- Instead, create a normal implementation task (using the regular task template) and reference the milestone task there.
|
||||||
|
- In the merge request, reference the milestone task again.
|
||||||
|
- If the milestone condition is fully met, you may use `Closing #<id>` to close the milestone task.
|
||||||
|
- If it is only partially addressed, use `Relates to #<id>` or `Contributes to #<id>` so the milestone task stays open.
|
||||||
|
|
||||||
|
Milestone tasks may, but do not have to, be assigned to a specific person.
|
||||||
|
|
||||||
|
- If multiple people are involved, contribution is tracked through linked tasks that reference the milestone task.
|
||||||
|
- For small topics, a Milestone Achievement may be assigned to one person. Others should only contribute on request and should not modify components introduced under that achievement without coordination.
|
||||||
|
|
||||||
|
|
||||||
## Git Workflow
|
## Git Workflow
|
||||||
We use a **feature branch -> main** strategy. The `main` branch is always in a releasable state.
|
We use a **feature branch -> main** strategy. The `main` branch is always in a releasable state.
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ The concrete implementations for each command live in `app/commands/` and are wi
|
|||||||
- [Command Infrastructure](./commands-deep-dive.md) -
|
- [Command Infrastructure](./commands-deep-dive.md) -
|
||||||
Technical deep-dive into the `CommandParser`, `CommandParserDispatcher`, `CommandHandler`, `CommandRouter`, `Request`, and the response hierarchy.
|
Technical deep-dive into the `CommandParser`, `CommandParserDispatcher`, `CommandHandler`, `CommandRouter`, `Request`, and the response hierarchy.
|
||||||
|
|
||||||
|
### Protocol document
|
||||||
|
- [Protocol Document](./protocol-document.md) -
|
||||||
|
List of all supported commands by the server, along with descriptions, required pre-execution checks, and an example for both request and response.
|
||||||
|
|
||||||
## Key Concepts
|
## Key Concepts
|
||||||
**Each command is self-contained.**
|
**Each command is self-contained.**
|
||||||
A command's Parser, Request, Handler, and Response all live in the same package under `app/commands/<name>/`.
|
A command's Parser, Request, Handler, and Response all live in the same package under `app/commands/<name>/`.
|
||||||
|
|||||||
@@ -0,0 +1,344 @@
|
|||||||
|
# Protocol Document
|
||||||
|
This document describes the protocol for client-server communication in our application. It defines the structure of requests and responses, the supported commands along with their request parameters, response formats, and possible errors.
|
||||||
|
|
||||||
|
|
||||||
|
# Table of Contents
|
||||||
|
- [Protocol Document](#protocol-document)
|
||||||
|
- [Table of Contents](#table-of-contents)
|
||||||
|
- [General structure of requests](#general-structure-of-requests)
|
||||||
|
- [Preconditions](#preconditions)
|
||||||
|
- [Parsing](#parsing)
|
||||||
|
- [Error Response](#error-response)
|
||||||
|
- [Command dispatching](#command-dispatching)
|
||||||
|
- [Error Response](#error-response-1)
|
||||||
|
- [Command parsing](#command-parsing)
|
||||||
|
- [Error Response](#error-response-2)
|
||||||
|
- [Pre-execution checks](#pre-execution-checks)
|
||||||
|
- [UserLoggedInCheck](#userloggedincheck)
|
||||||
|
- [Error Response](#error-response-3)
|
||||||
|
- [Commands](#commands)
|
||||||
|
- [PING command](#ping-command)
|
||||||
|
- [Required pre-execution checks](#required-pre-execution-checks)
|
||||||
|
- [Request Parameters](#request-parameters)
|
||||||
|
- [Success Response](#success-response)
|
||||||
|
- [Example Request](#example-request)
|
||||||
|
- [Example Response](#example-response)
|
||||||
|
- [CHECK\_USERNAME command](#check_username-command)
|
||||||
|
- [Required pre-execution checks](#required-pre-execution-checks-1)
|
||||||
|
- [Request Parameters](#request-parameters-1)
|
||||||
|
- [Success Response](#success-response-1)
|
||||||
|
- [Example Request](#example-request-1)
|
||||||
|
- [Example Response](#example-response-1)
|
||||||
|
- [LOGIN command](#login-command)
|
||||||
|
- [Required pre-execution checks](#required-pre-execution-checks-2)
|
||||||
|
- [Request Parameters](#request-parameters-2)
|
||||||
|
- [Success Response](#success-response-2)
|
||||||
|
- [Error Response](#error-response-4)
|
||||||
|
- [Example Request](#example-request-2)
|
||||||
|
- [Example Response](#example-response-2)
|
||||||
|
- [LOGOUT command](#logout-command)
|
||||||
|
- [Required pre-execution checks](#required-pre-execution-checks-3)
|
||||||
|
- [Request Parameters](#request-parameters-3)
|
||||||
|
- [Success Response](#success-response-3)
|
||||||
|
- [Error Response](#error-response-5)
|
||||||
|
- [Example Request](#example-request-3)
|
||||||
|
- [Example Response](#example-response-3)
|
||||||
|
- [LIST\_USERS command](#list_users-command)
|
||||||
|
- [Required pre-execution checks](#required-pre-execution-checks-4)
|
||||||
|
- [Request Parameters](#request-parameters-4)
|
||||||
|
- [Success Response](#success-response-4)
|
||||||
|
- [Error Response](#error-response-6)
|
||||||
|
- [Example Request](#example-request-4)
|
||||||
|
- [Example Response](#example-response-4)
|
||||||
|
|
||||||
|
<!-- Please see the comments for copy ‚ n' paste ready examples -->
|
||||||
|
|
||||||
|
# General structure of requests
|
||||||
|
As mentioned before, our protocol is based on POP3.
|
||||||
|
Each command is represented as a single line of text, starting with the command name followed by parameters. The server responds with a status line indicating success or failure, followed by the body.
|
||||||
|
|
||||||
|
Requests can have parameters that provide additional information for the command. Parameters are key-value pairs separated by an equal sign (`=`).
|
||||||
|
|
||||||
|
Responses are collections of key-value pairs, containing either a value or another collection, allowing for nested structures.
|
||||||
|
Each collection is ended with the `END` keyword.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Preconditions
|
||||||
|
The serverside pipeline to process incoming requests consists of multiple stages.
|
||||||
|
Each of these stages can yield an error response if the request does not meet the requirements of that stage.
|
||||||
|
|
||||||
|
## Parsing
|
||||||
|
One of these stages is the parsing. It is responsible for parsing the raw request into a structured format that can be easily processed by the command handlers. It validates the syntax of the request as well.
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
| Code | Description |
|
||||||
|
| :-------------- | :---------------------------------------------------------------------------------------------- |
|
||||||
|
| `PARSING_ERROR` | The body of the request contains syntax errors (see message field of response for more details) |
|
||||||
|
|
||||||
|
|
||||||
|
## Command dispatching
|
||||||
|
After the request has been successfully parsed, the next stage is to dispatch the `PrimitiveRequest` to the appropriate `CommandParser`. This is done by the `CommandDispatcherDispatcher`, which uses the command name to determine which parser to use.
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
| Code | Description |
|
||||||
|
| :---------------- | :---------------------------------------------------------------- |
|
||||||
|
| `UNKNOWN_COMMAND` | The command is unknown to this server. No parser has been defined |
|
||||||
|
|
||||||
|
|
||||||
|
## Command parsing
|
||||||
|
Once the `PrimitiveRequest` has been dispatched to the appropriate `CommandParser`, the parser is responsible for parsing the parameters of the request and creating a `Request` that can be executed by the responsible `CommandHandler`.
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
| Code | Description |
|
||||||
|
| :------------------ | :------------------------------------------------------------------------------------------------ |
|
||||||
|
| `MISSING_PARAMETER` | A required parameter is missing from the request (see message field of response for more details) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Pre-execution checks
|
||||||
|
Pre-execution checks are reusable validation steps that can be registered on command handlers.
|
||||||
|
They are implemented as `HandlerCheck` instances and are executed by the `CommandHandlerExecutor` before the handler's main logic is invoked.
|
||||||
|
|
||||||
|
<!--
|
||||||
|
## Name of the check
|
||||||
|
Description of the check, what it does and when it should be used.
|
||||||
|
|
||||||
|
### Response if not met
|
||||||
|
| Code | Description |
|
||||||
|
| :----------- | :----------------------- |
|
||||||
|
| `ERROR_CODE` | Description of the error |
|
||||||
|
-->
|
||||||
|
|
||||||
|
## UserLoggedInCheck
|
||||||
|
The `UserLoggedInCheck` is a common pre-execution check that verifies whether the user is logged in (i.e. has a user associated with his session).
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
| Code | Description |
|
||||||
|
| :------------------- | :------------------------ |
|
||||||
|
| `USER_NOT_LOGGED_IN` | The user is not logged in |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Commands
|
||||||
|
Commands are the core of our protocol, representing the various actions that clients can request from the server. Each command has a unique name and may require specific parameters in addition to pre-execution checks.
|
||||||
|
The server processes these commands and responds accordingly.
|
||||||
|
|
||||||
|
<!--
|
||||||
|
## Name of the command
|
||||||
|
Description of the command, what it does, and when it should be used.
|
||||||
|
|
||||||
|
### Required pre-execution checks
|
||||||
|
- [`Check1`](#check1)
|
||||||
|
|
||||||
|
### Request Parameters
|
||||||
|
| Parameter Name | Type | Optional | Description |
|
||||||
|
| :------------- | :----- | :---------------------------------- | :-------------------- |
|
||||||
|
| `param1` | `type` | If the parameter is optional or not | Description of param1 |
|
||||||
|
|
||||||
|
### Success Response
|
||||||
|
| Field | Type | Description |
|
||||||
|
| :------- | :------------------ | :-------------------- |
|
||||||
|
| `field1` | `type` | Description of field1 |
|
||||||
|
| `field2` | `Collection<type2>` | |
|
||||||
|
| `field3` | `Enum<type3>` | Description of field3 |
|
||||||
|
|
||||||
|
| Fields of `type2` | Type | Description |
|
||||||
|
| :---------------- | :----- | :-------------------- |
|
||||||
|
| `field1` | `type` | Description of field1 |
|
||||||
|
|
||||||
|
| Members of `type` | Description |
|
||||||
|
| :---------------- | :--------------------- |
|
||||||
|
| `MEMBER1` | Description of member1 |
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
| Code | Description |
|
||||||
|
| :----------- | :----------------------- |
|
||||||
|
| `ERROR_CODE` | Description of the error |
|
||||||
|
|
||||||
|
### Example Request
|
||||||
|
```
|
||||||
|
COMMAND_NAME PARAM1='value1' PARAM2='value2'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Response
|
||||||
|
```
|
||||||
|
+OK
|
||||||
|
KEY1=VALUE1
|
||||||
|
FIELDS
|
||||||
|
FIELD
|
||||||
|
NESTED_KEY=NESTED_VALUE
|
||||||
|
END
|
||||||
|
KEY2=VALUE2
|
||||||
|
END
|
||||||
|
```
|
||||||
|
-->
|
||||||
|
|
||||||
|
## PING command
|
||||||
|
The `PING` command is a simple command that can be used to check if the server is responsive.
|
||||||
|
|
||||||
|
### Required pre-execution checks
|
||||||
|
None.
|
||||||
|
|
||||||
|
### Request Parameters
|
||||||
|
No parameters.
|
||||||
|
|
||||||
|
### Success Response
|
||||||
|
No response fields.
|
||||||
|
|
||||||
|
### Example Request
|
||||||
|
```
|
||||||
|
PING
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Response
|
||||||
|
```
|
||||||
|
+OK
|
||||||
|
END
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## CHECK_USERNAME command
|
||||||
|
The `CHECK_USERNAME` command is used to check if a username is already taken by another user. Additional users can still log in with the same username, but their name will be substituted with a suffix.
|
||||||
|
|
||||||
|
### Required pre-execution checks
|
||||||
|
None.
|
||||||
|
|
||||||
|
### Request Parameters
|
||||||
|
| Parameter Name | Type | Optional | Description |
|
||||||
|
| :------------- | :------- | :------- | :------------------------------------- |
|
||||||
|
| `USERNAME` | `String` | no | The username to check for availability |
|
||||||
|
|
||||||
|
### Success Response
|
||||||
|
| Field | Type | Description |
|
||||||
|
| :------- | :--------------------------- | :---------------------------------------------------------------------- |
|
||||||
|
| `STATUS` | `Enum<UsernameAvailability>` | Member of enum indicating if the username is available or already taken |
|
||||||
|
|
||||||
|
| Members of `UsernameAvailability` | Description |
|
||||||
|
| :-------------------------------- | :------------------------- |
|
||||||
|
| `FREE` | Username is available |
|
||||||
|
| `TAKEN` | Username is already in use |
|
||||||
|
|
||||||
|
### Example Request
|
||||||
|
```
|
||||||
|
CHECK_USERNAME USERNAME='Lars'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Response
|
||||||
|
```
|
||||||
|
+OK
|
||||||
|
STATUS=FREE
|
||||||
|
END
|
||||||
|
```
|
||||||
|
|
||||||
|
## LOGIN command
|
||||||
|
The `LOGIN` command is used to log in a user with a specified username. If the username is already taken by another user, the server will append a suffix to the username to make it unique.
|
||||||
|
|
||||||
|
### Required pre-execution checks
|
||||||
|
None.
|
||||||
|
|
||||||
|
### Request Parameters
|
||||||
|
| Parameter Name | Type | Optional | Description |
|
||||||
|
| :------------- | :------- | :------- | :----------------------------------- |
|
||||||
|
| `USERNAME` | `String` | no | The username to create the user with |
|
||||||
|
|
||||||
|
### Success Response
|
||||||
|
| Field | Type | Description |
|
||||||
|
| :--------- | :---------------------------------------------------------------------- | :-------------------------------------------------------------------- |
|
||||||
|
| `USERNAME` | `String` | Username of the newly created user, can differ from the requested one |
|
||||||
|
| `ID` | [`UUID`](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html) | The ID of the created user |
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
| Code | Description |
|
||||||
|
| :------------------ | :----------------------------------------------------------------------------- |
|
||||||
|
| `ALREADY_LOGGED_IN` | The session is already associated with a user, logging in again is prohibited. |
|
||||||
|
|
||||||
|
### Example Request
|
||||||
|
```
|
||||||
|
LOGIN USERNAME='Lars'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Response
|
||||||
|
```
|
||||||
|
+OK
|
||||||
|
USERNAME='Lars_1234'
|
||||||
|
ID=e47a671e-2b2a-42df-bb82-953fe2ebd307
|
||||||
|
END
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## LOGOUT command
|
||||||
|
Description of the command, what it does, and when it should be used.
|
||||||
|
|
||||||
|
### Required pre-execution checks
|
||||||
|
None.
|
||||||
|
|
||||||
|
### Request Parameters
|
||||||
|
No parameters.
|
||||||
|
|
||||||
|
### Success Response
|
||||||
|
No response fields.
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
| Code | Description |
|
||||||
|
| :------------------- | :--------------------------------------------------------------- |
|
||||||
|
| `NO_USER_ASSOCIATED` | The session has no user associated, logging out is not possible. |
|
||||||
|
|
||||||
|
### Example Request
|
||||||
|
```
|
||||||
|
LOGOUT
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Response
|
||||||
|
```
|
||||||
|
+OK
|
||||||
|
END
|
||||||
|
```
|
||||||
|
|
||||||
|
## LIST_USERS command
|
||||||
|
The `LIST_USERS` command is used to retrieve a list of all currently logged-in users.
|
||||||
|
|
||||||
|
### Required pre-execution checks
|
||||||
|
None.
|
||||||
|
|
||||||
|
### Request Parameters
|
||||||
|
No parameters.
|
||||||
|
|
||||||
|
### Success Response
|
||||||
|
| Field | Type | Description |
|
||||||
|
| :------ | :----------------- | :--------------------------------------- |
|
||||||
|
| `USERS` | `Collection<User>` | Collection of all users currently online |
|
||||||
|
|
||||||
|
| Fields of `User` | Type | Description |
|
||||||
|
| :--------------- | :---------------------------------------------------------------------- | :-------------------------------------------------------------------- |
|
||||||
|
| `USERNAME` | `String` | Username of the newly created user, can differ from the requested one |
|
||||||
|
| `ID` | [`UUID`](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html) | The ID of the created user |
|
||||||
|
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
None.
|
||||||
|
|
||||||
|
### Example Request
|
||||||
|
```
|
||||||
|
LIST_USERS
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Response
|
||||||
|
```
|
||||||
|
+OK
|
||||||
|
USERS
|
||||||
|
USER
|
||||||
|
USERNAME=Lars_001
|
||||||
|
ID=56765d0f-8cd3-4eec-91b2-7e36265c1a5d
|
||||||
|
END
|
||||||
|
USER
|
||||||
|
USERNAME=Lars_002
|
||||||
|
ID=b7bbd9b3-0d49-4c92-8306-b1c8506d2ff0
|
||||||
|
END
|
||||||
|
USER
|
||||||
|
USERNAME=Lars
|
||||||
|
ID=982bc78e-547f-495a-a821-433a3603f92c
|
||||||
|
END
|
||||||
|
END
|
||||||
|
END
|
||||||
|
```
|
||||||
@@ -3,6 +3,9 @@ package ch.unibas.dmi.dbis.cs108.casono.server;
|
|||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameHandler;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameHandler;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameParser;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameParser;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameRequest;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameRequest;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.list_users.ListUsersHandler;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.list_users.ListUsersParser;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.list_users.ListUsersRequest;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginHandler;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginHandler;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginParser;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginParser;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginRequest;
|
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginRequest;
|
||||||
@@ -106,5 +109,9 @@ public class ServerApp {
|
|||||||
parserDispatcher.register("LOGOUT", new LogoutParser());
|
parserDispatcher.register("LOGOUT", new LogoutParser());
|
||||||
commandRouter.register(
|
commandRouter.register(
|
||||||
LogoutRequest.class, new LogoutHandler(responseDispatcher, userRegistry));
|
LogoutRequest.class, new LogoutHandler(responseDispatcher, userRegistry));
|
||||||
|
|
||||||
|
parserDispatcher.register("LIST_USERS", new ListUsersParser());
|
||||||
|
commandRouter.register(
|
||||||
|
ListUsersRequest.class, new ListUsersHandler(responseDispatcher, userRegistry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.list_users;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.User;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles {@link ListUsersRequest}s by retrieving all users from the {@link UserRegistry} and
|
||||||
|
* dispatching a {@link ListUsersResponse} containing the list of users.
|
||||||
|
*/
|
||||||
|
public class ListUsersHandler extends CommandHandler<ListUsersRequest> {
|
||||||
|
private final UserRegistry userRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new handler for listing all users
|
||||||
|
*
|
||||||
|
* @param responseDispatcher the dispatcher used to send the response
|
||||||
|
* @param userRegistry the registry used to look up existing users
|
||||||
|
*/
|
||||||
|
public ListUsersHandler(ResponseDispatcher responseDispatcher, UserRegistry userRegistry) {
|
||||||
|
super(responseDispatcher);
|
||||||
|
this.userRegistry = userRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the list users request
|
||||||
|
*
|
||||||
|
* <p>All users are retrieved from the {@link UserRegistry} and returned in a {@link
|
||||||
|
* ListUsersResponse}.
|
||||||
|
*
|
||||||
|
* @param request the request to execute
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void execute(ListUsersRequest request) {
|
||||||
|
Collection<User> users = userRegistry.getAllUsers();
|
||||||
|
responseDispatcher.dispatch(new ListUsersResponse(request.getContext(), users));
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.list_users;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.CommandParser;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.PrimitiveRequest;
|
||||||
|
|
||||||
|
/** Parses a primitive request into a {@link ListUsersRequest}. */
|
||||||
|
public class ListUsersParser implements CommandParser<ListUsersRequest> {
|
||||||
|
/**
|
||||||
|
* Parses a primitive request into a ListUsersRequest.
|
||||||
|
*
|
||||||
|
* @param primitiveRequest the request to parse
|
||||||
|
* @return the created {@link ListUsersRequest}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ListUsersRequest parse(PrimitiveRequest primitiveRequest) {
|
||||||
|
return new ListUsersRequest(primitiveRequest.context());
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.list_users;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.Request;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||||
|
|
||||||
|
/** Request implementation used to retrieve all existing users from the server. */
|
||||||
|
public class ListUsersRequest extends Request {
|
||||||
|
/**
|
||||||
|
* Constructs a new ListUsersRequest with the given context
|
||||||
|
*
|
||||||
|
* @param context the {@link RequestContext} containing information for responding to the
|
||||||
|
* request
|
||||||
|
*/
|
||||||
|
public ListUsersRequest(RequestContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.list_users;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.User;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.SuccessResponse;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/** Response containing a list of all active users on the server */
|
||||||
|
public class ListUsersResponse extends SuccessResponse {
|
||||||
|
/**
|
||||||
|
* Creates a new ListUsersResponse containing the given list of users
|
||||||
|
*
|
||||||
|
* @param context the {@link RequestContext} associated with the request
|
||||||
|
* @param users the collection of users currently active on the server
|
||||||
|
*/
|
||||||
|
public ListUsersResponse(RequestContext context, Collection<User> users) {
|
||||||
|
super(
|
||||||
|
context,
|
||||||
|
ResponseBody.builder()
|
||||||
|
.block(
|
||||||
|
"USERS",
|
||||||
|
users_block -> {
|
||||||
|
for (User user : users) {
|
||||||
|
users_block.block(
|
||||||
|
"USER",
|
||||||
|
user_block -> {
|
||||||
|
user_block.param("USERNAME", user.getName());
|
||||||
|
user_block.param("ID", user.getId().value());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -52,5 +52,5 @@ public abstract class CommandHandler<T extends Request> {
|
|||||||
*
|
*
|
||||||
* @param request the request to execute, of type T
|
* @param request the request to execute, of type T
|
||||||
*/
|
*/
|
||||||
public void execute(T request) {}
|
public abstract void execute(T request);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ package ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.accessor
|
|||||||
* @param <T> target type produced by the parser
|
* @param <T> target type produced by the parser
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
interface ThrowingParser<T> {
|
public interface ThrowingParser<T> {
|
||||||
/**
|
/**
|
||||||
* Parses the provided raw parameter value.
|
* Parses the provided raw parameter value.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user