Common library + roster service updates #52

Merged
Maece97 merged 7 commits from common into dev 2021-11-08 13:35:38 +00:00
57 changed files with 548 additions and 101 deletions
Showing only changes of commit 5c445a2f66 - Show all commits

View File

@ -1,7 +0,0 @@
package ch.unisg.assignment.assignment.application.port.in;
import ch.unisg.assignment.assignment.domain.Task;
public interface ApplyForTaskUseCase {
Task applyForTask(ApplyForTaskCommand applyForTaskCommand);
}

View File

View File

@ -56,6 +56,12 @@
<version>1.2</version> <version>1.2</version>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.5</version>
</dependency>
<dependency> <dependency>
<groupId>org.json</groupId> <groupId>org.json</groupId>
<artifactId>json</artifactId> <artifactId>json</artifactId>

View File

@ -1,13 +1,13 @@
package ch.unisg.assignment; package ch.unisg.roster;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication @SpringBootApplication
public class AssignmentApplication { public class RosterApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(AssignmentApplication.class, args); SpringApplication.run(RosterApplication.class, args);
} }
} }

View File

@ -0,0 +1,94 @@
package ch.unisg.roster.roster.adapter.common.clients;
import ch.unisg.roster.roster.adapter.in.messaging.mqtt.AuctionEventsMqttDispatcher;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
/**
* MQTT client for your TAPAS application. This class is defined as a singleton, but it does not have
* to be this way. This class is only provided as an example to help you bootstrap your project.
* You are welcomed to change this class as you see fit.
*/
public class TapasMqttClient {
private static final Logger LOGGER = LogManager.getLogger(TapasMqttClient.class);
private static TapasMqttClient tapasClient = null;
private MqttClient mqttClient;
private final String mqttClientId;
private final String brokerAddress;
private final MessageReceivedCallback messageReceivedCallback;
private final AuctionEventsMqttDispatcher dispatcher;
private TapasMqttClient(String brokerAddress, AuctionEventsMqttDispatcher dispatcher) {
this.mqttClientId = UUID.randomUUID().toString();
this.brokerAddress = brokerAddress;
this.messageReceivedCallback = new MessageReceivedCallback();
this.dispatcher = dispatcher;
}
public static synchronized TapasMqttClient getInstance(String brokerAddress,
AuctionEventsMqttDispatcher dispatcher) {
if (tapasClient == null) {
tapasClient = new TapasMqttClient(brokerAddress, dispatcher);
}
return tapasClient;
}
public void startReceivingMessages() throws MqttException {
mqttClient = new org.eclipse.paho.client.mqttv3.MqttClient(brokerAddress, mqttClientId, new MemoryPersistence());
mqttClient.connect();
mqttClient.setCallback(messageReceivedCallback);
subscribeToAllTopics();
}
public void stopReceivingMessages() throws MqttException {
mqttClient.disconnect();
}
private void subscribeToAllTopics() throws MqttException {
for (String topic : dispatcher.getAllTopics()) {
subscribeToTopic(topic);
}
}
private void subscribeToTopic(String topic) throws MqttException {
mqttClient.subscribe(topic);
}
private void publishMessage(String topic, String payload) throws MqttException {
MqttMessage message = new MqttMessage(payload.getBytes(StandardCharsets.UTF_8));
mqttClient.publish(topic, message);
}
private class MessageReceivedCallback implements MqttCallback {
@Override
public void connectionLost(Throwable cause) { }
@Override
public void messageArrived(String topic, MqttMessage message) {
LOGGER.info("Received new MQTT message for topic " + topic + ": "
+ new String(message.getPayload()));
if (topic != null && !topic.isEmpty()) {
dispatcher.dispatchEvent(topic, message);
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) { }
}
}

View File

@ -0,0 +1,11 @@
package ch.unisg.roster.roster.adapter.in.messaging.mqtt;
import org.eclipse.paho.client.mqttv3.MqttMessage;
/**
* Abstract MQTT listener for auction-related events
*/
public abstract class AuctionEventMqttListener {
public abstract boolean handleEvent(MqttMessage message);
}

View File

@ -0,0 +1,52 @@
package ch.unisg.roster.roster.adapter.in.messaging.mqtt;
import org.eclipse.paho.client.mqttv3.*;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
/**
* Dispatches MQTT messages for known topics to associated event listeners. Used in conjunction with
* {@link ch.unisg.tapas.auctionhouse.adapter.common.clients.TapasMqttClient}.
*
* This is where you would define MQTT topics and map them to event listeners (see
* {@link AuctionEventsMqttDispatcher#initRouter()}).
*
* This class is only provided as an example to help you bootstrap the project. You are welcomed to
* change this class as you see fit.
*/
public class AuctionEventsMqttDispatcher {
private final Map<String, AuctionEventMqttListener> router;
public AuctionEventsMqttDispatcher() {
this.router = new Hashtable<>();
initRouter();
}
// TODO: Register here your topics and event listener adapters
private void initRouter() {
router.put("ch/unisg/tapas-group-tutors/executors/added", new ExecutorAddedEventListenerMqttAdapter());
router.put("ch/unisg/tapas-group-tutors/executors/removed", new ExecutorRemovedEventListenerMqttAdapter());
}
/**
* Returns all topics registered with this dispatcher.
*
* @return the set of registered topics
*/
public Set<String> getAllTopics() {
return router.keySet();
}
/**
* Dispatches an event received via MQTT for a given topic.
*
* @param topic the topic for which the MQTT message was received
* @param message the received MQTT message
*/
public void dispatchEvent(String topic, MqttMessage message) {
AuctionEventMqttListener listener = router.get(topic);
listener.handleEvent(message);
}
}

View File

@ -0,0 +1,44 @@
package ch.unisg.roster.roster.adapter.in.messaging.mqtt;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import ch.unisg.common.valueobject.ExecutorURI;
import ch.unisg.roster.roster.application.handler.ExecutorAddedHandler;
import ch.unisg.roster.roster.application.port.in.ExecutorAddedEvent;
import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
public class ExecutorAddedEventListenerMqttAdapter extends AuctionEventMqttListener {
private static final Logger LOGGER = LogManager.getLogger(ExecutorAddedEventListenerMqttAdapter.class);
@Override
public boolean handleEvent(MqttMessage message) {
String payload = new String(message.getPayload());
try {
// Note: this messge representation is provided only as an example. You should use a
// representation that makes sense in the context of your application.
JsonNode data = new ObjectMapper().readTree(payload);
String taskType = data.get("taskType").asText();
String executorId = data.get("executorURI").asText();
ExecutorAddedEvent executorAddedEvent = new ExecutorAddedEvent(
new ExecutorURI(executorId),
new ExecutorType(taskType)
);
ExecutorAddedHandler newExecutorHandler = new ExecutorAddedHandler();
newExecutorHandler.handleNewExecutorEvent(executorAddedEvent);
} catch (JsonProcessingException | NullPointerException e) {
LOGGER.error(e.getMessage(), e);
return false;
}
return true;
}
}

View File

@ -0,0 +1,41 @@
package ch.unisg.roster.roster.adapter.in.messaging.mqtt;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import ch.unisg.common.valueobject.ExecutorURI;
import ch.unisg.roster.roster.application.handler.ExecutorRemovedHandler;
import ch.unisg.roster.roster.application.port.in.ExecutorRemovedEvent;
public class ExecutorRemovedEventListenerMqttAdapter extends AuctionEventMqttListener {
private static final Logger LOGGER = LogManager.getLogger(ExecutorRemovedEventListenerMqttAdapter.class);
@Override
public boolean handleEvent(MqttMessage message) {
String payload = new String(message.getPayload());
try {
// Note: this messge representation is provided only as an example. You should use a
// representation that makes sense in the context of your application.
JsonNode data = new ObjectMapper().readTree(payload);
String executorId = data.get("executorURI").asText();
ExecutorRemovedEvent executorRemovedEvent = new ExecutorRemovedEvent(
new ExecutorURI(executorId));
ExecutorRemovedHandler executorRemovedHandler = new ExecutorRemovedHandler();
executorRemovedHandler.handleExecutorRemovedEvent(executorRemovedEvent);
} catch (JsonProcessingException | NullPointerException e) {
LOGGER.error(e.getMessage(), e);
return false;
}
return true;
}
}

View File

@ -1,13 +1,13 @@
package ch.unisg.assignment.assignment.adapter.in.web; package ch.unisg.roster.roster.adapter.in.web;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ch.unisg.assignment.assignment.application.port.in.ApplyForTaskCommand; import ch.unisg.roster.roster.application.port.in.ApplyForTaskCommand;
import ch.unisg.assignment.assignment.application.port.in.ApplyForTaskUseCase; import ch.unisg.roster.roster.application.port.in.ApplyForTaskUseCase;
import ch.unisg.assignment.assignment.domain.ExecutorInfo; import ch.unisg.roster.roster.domain.ExecutorInfo;
import ch.unisg.assignment.assignment.domain.Task; import ch.unisg.roster.roster.domain.Task;
@RestController @RestController
public class ApplyForTaskController { public class ApplyForTaskController {

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.adapter.in.web; package ch.unisg.roster.roster.adapter.in.web;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -6,9 +6,9 @@ import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ch.unisg.assignment.assignment.application.port.in.DeleteTaskCommand; import ch.unisg.roster.roster.application.port.in.DeleteTaskCommand;
import ch.unisg.assignment.assignment.application.port.in.DeleteTaskUseCase; import ch.unisg.roster.roster.application.port.in.DeleteTaskUseCase;
import ch.unisg.assignment.assignment.domain.Task; import ch.unisg.roster.roster.domain.Task;
@RestController @RestController
public class DeleteTaskController { public class DeleteTaskController {

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.adapter.in.web; package ch.unisg.roster.roster.adapter.in.web;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -6,9 +6,9 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ch.unisg.assignment.assignment.application.port.in.NewTaskCommand; import ch.unisg.roster.roster.application.port.in.NewTaskCommand;
import ch.unisg.assignment.assignment.application.port.in.NewTaskUseCase; import ch.unisg.roster.roster.application.port.in.NewTaskUseCase;
import ch.unisg.assignment.assignment.domain.Task; import ch.unisg.roster.roster.domain.Task;
@RestController @RestController
public class NewTaskController { public class NewTaskController {

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.adapter.in.web; package ch.unisg.roster.roster.adapter.in.web;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -6,9 +6,9 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ch.unisg.assignment.assignment.application.port.in.TaskCompletedCommand; import ch.unisg.roster.roster.application.port.in.TaskCompletedCommand;
import ch.unisg.assignment.assignment.application.port.in.TaskCompletedUseCase; import ch.unisg.roster.roster.application.port.in.TaskCompletedUseCase;
import ch.unisg.assignment.assignment.domain.Task; import ch.unisg.roster.roster.domain.Task;
@RestController @RestController
public class TaskCompletedController { public class TaskCompletedController {

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.adapter.in.web; package ch.unisg.roster.roster.adapter.in.web;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.adapter.out.web; package ch.unisg.roster.roster.adapter.out.web;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -14,8 +14,8 @@ import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ch.unisg.assignment.assignment.application.port.out.GetAllExecutorInExecutorPoolByTypePort; import ch.unisg.roster.roster.application.port.out.GetAllExecutorInExecutorPoolByTypePort;
import ch.unisg.assignment.assignment.domain.valueobject.ExecutorType; import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
@Component @Component
@Primary @Primary

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.adapter.out.web; package ch.unisg.roster.roster.adapter.out.web;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -12,8 +12,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ch.unisg.assignment.assignment.application.port.out.NewTaskEventPort; import ch.unisg.roster.roster.application.port.out.NewTaskEventPort;
import ch.unisg.assignment.assignment.domain.event.NewTaskEvent; import ch.unisg.roster.roster.domain.event.NewTaskEvent;
@Component @Component
@Primary @Primary

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.adapter.out.web; package ch.unisg.roster.roster.adapter.out.web;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -13,8 +13,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ch.unisg.assignment.assignment.application.port.out.TaskAssignedEventPort; import ch.unisg.roster.roster.application.port.out.TaskAssignedEventPort;
import ch.unisg.assignment.assignment.domain.event.TaskAssignedEvent; import ch.unisg.roster.roster.domain.event.TaskAssignedEvent;
@Component @Component
@Primary @Primary

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.adapter.out.web; package ch.unisg.roster.roster.adapter.out.web;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -13,8 +13,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ch.unisg.assignment.assignment.application.port.out.TaskCompletedEventPort; import ch.unisg.roster.roster.application.port.out.TaskCompletedEventPort;
import ch.unisg.assignment.assignment.domain.event.TaskCompletedEvent; import ch.unisg.roster.roster.domain.event.TaskCompletedEvent;
@Component @Component
@Primary @Primary

View File

@ -0,0 +1,16 @@
package ch.unisg.roster.roster.application.handler;
import ch.unisg.roster.roster.application.port.in.ExecutorAddedEvent;
import ch.unisg.roster.roster.application.port.in.ExecutorAddedEventHandler;
import ch.unisg.roster.roster.domain.ExecutorRegistry;
import org.springframework.stereotype.Component;
@Component
public class ExecutorAddedHandler implements ExecutorAddedEventHandler {
@Override
public boolean handleNewExecutorEvent(ExecutorAddedEvent executorAddedEvent) {
return ExecutorRegistry.getInstance().addExecutor(executorAddedEvent.getExecutorType(),
executorAddedEvent.getExecutorURI());
}
}

View File

@ -0,0 +1,19 @@
package ch.unisg.roster.roster.application.handler;
import ch.unisg.roster.roster.application.port.in.ExecutorRemovedEvent;
import ch.unisg.roster.roster.application.port.in.ExecutorRemovedEventHandler;
import ch.unisg.roster.roster.domain.ExecutorRegistry;
import org.springframework.stereotype.Component;
/**
* Handler for executor removed events. It removes the executor from this roster's executor
* registry.
*/
@Component
public class ExecutorRemovedHandler implements ExecutorRemovedEventHandler {
@Override
public boolean handleExecutorRemovedEvent(ExecutorRemovedEvent executorRemovedEvent) {
return ExecutorRegistry.getInstance().removeExecutor(executorRemovedEvent.getExecutorURI());
}
}

View File

@ -1,8 +1,8 @@
package ch.unisg.assignment.assignment.application.port.in; package ch.unisg.roster.roster.application.port.in;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import ch.unisg.assignment.assignment.domain.valueobject.ExecutorType; import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
import ch.unisg.common.validation.SelfValidating; import ch.unisg.common.validation.SelfValidating;
import ch.unisg.common.valueobject.ExecutorURI; import ch.unisg.common.valueobject.ExecutorURI;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;

View File

@ -0,0 +1,7 @@
package ch.unisg.roster.roster.application.port.in;
import ch.unisg.roster.roster.domain.Task;
public interface ApplyForTaskUseCase {
Task applyForTask(ApplyForTaskCommand applyForTaskCommand);
}

View File

@ -1,8 +1,8 @@
package ch.unisg.assignment.assignment.application.port.in; package ch.unisg.roster.roster.application.port.in;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import ch.unisg.assignment.assignment.domain.valueobject.ExecutorType; import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
import ch.unisg.common.validation.SelfValidating; import ch.unisg.common.validation.SelfValidating;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Value; import lombok.Value;

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.application.port.in; package ch.unisg.roster.roster.application.port.in;
public interface DeleteTaskUseCase { public interface DeleteTaskUseCase {
boolean deleteTask(DeleteTaskCommand deleteTaskCommand); boolean deleteTask(DeleteTaskCommand deleteTaskCommand);

View File

@ -0,0 +1,33 @@
package ch.unisg.roster.roster.application.port.in;
import lombok.Value;
import javax.validation.constraints.NotNull;
import ch.unisg.common.validation.SelfValidating;
import ch.unisg.common.valueobject.ExecutorURI;
import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
/**
* Event that notifies the auction house that an executor has been added to this TAPAS application.
*/
@Value
public class ExecutorAddedEvent extends SelfValidating<ExecutorAddedEvent> {
@NotNull
private final ExecutorURI executorURI;
@NotNull
private final ExecutorType executorType;
/**
* Constructs an executor added event.
*
* @param executorURI the identifier of the executor that was added to this TAPAS application
*/
public ExecutorAddedEvent(ExecutorURI executorURI, ExecutorType executorType) {
this.executorURI = executorURI;
this.executorType = executorType;
this.validateSelf();
}
}

View File

@ -0,0 +1,6 @@
package ch.unisg.roster.roster.application.port.in;
public interface ExecutorAddedEventHandler {
boolean handleNewExecutorEvent(ExecutorAddedEvent executorAddedEvent);
}

View File

@ -0,0 +1,27 @@
package ch.unisg.roster.roster.application.port.in;
import lombok.Value;
import javax.validation.constraints.NotNull;
import ch.unisg.common.validation.SelfValidating;
import ch.unisg.common.valueobject.ExecutorURI;
/**
* Event that notifies the auction house that an executor has been removed from this TAPAS application.
*/
@Value
public class ExecutorRemovedEvent extends SelfValidating<ExecutorRemovedEvent> {
@NotNull
private final ExecutorURI executorURI;
/**
* Constructs an executor removed event.
*
* @param executorURI the identifier of the executor that was removed from this TAPAS application
*/
public ExecutorRemovedEvent(ExecutorURI executorURI) {
this.executorURI = executorURI;
this.validateSelf();
}
}

View File

@ -0,0 +1,6 @@
package ch.unisg.roster.roster.application.port.in;
public interface ExecutorRemovedEventHandler {
boolean handleExecutorRemovedEvent(ExecutorRemovedEvent executorRemovedEvent);
}

View File

@ -1,8 +1,8 @@
package ch.unisg.assignment.assignment.application.port.in; package ch.unisg.roster.roster.application.port.in;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import ch.unisg.assignment.assignment.domain.valueobject.ExecutorType; import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
import ch.unisg.common.validation.SelfValidating; import ch.unisg.common.validation.SelfValidating;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Value; import lombok.Value;

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.application.port.in; package ch.unisg.roster.roster.application.port.in;
public interface NewTaskUseCase { public interface NewTaskUseCase {
boolean addNewTaskToQueue(NewTaskCommand newTaskCommand); boolean addNewTaskToQueue(NewTaskCommand newTaskCommand);

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.application.port.in; package ch.unisg.roster.roster.application.port.in;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.application.port.in; package ch.unisg.roster.roster.application.port.in;
public interface TaskCompletedUseCase { public interface TaskCompletedUseCase {
void taskCompleted(TaskCompletedCommand taskCompletedCommand); void taskCompleted(TaskCompletedCommand taskCompletedCommand);

View File

@ -1,6 +1,6 @@
package ch.unisg.assignment.assignment.application.port.out; package ch.unisg.roster.roster.application.port.out;
import ch.unisg.assignment.assignment.domain.valueobject.ExecutorType; import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
public interface GetAllExecutorInExecutorPoolByTypePort { public interface GetAllExecutorInExecutorPoolByTypePort {
/** /**

View File

@ -1,6 +1,6 @@
package ch.unisg.assignment.assignment.application.port.out; package ch.unisg.roster.roster.application.port.out;
import ch.unisg.assignment.assignment.domain.event.NewTaskEvent; import ch.unisg.roster.roster.domain.event.NewTaskEvent;
public interface NewTaskEventPort { public interface NewTaskEventPort {
/** /**

View File

@ -1,6 +1,6 @@
package ch.unisg.assignment.assignment.application.port.out; package ch.unisg.roster.roster.application.port.out;
import ch.unisg.assignment.assignment.domain.event.TaskAssignedEvent; import ch.unisg.roster.roster.domain.event.TaskAssignedEvent;
public interface TaskAssignedEventPort { public interface TaskAssignedEventPort {
/** /**

View File

@ -1,6 +1,6 @@
package ch.unisg.assignment.assignment.application.port.out; package ch.unisg.roster.roster.application.port.out;
import ch.unisg.assignment.assignment.domain.event.TaskCompletedEvent; import ch.unisg.roster.roster.domain.event.TaskCompletedEvent;
public interface TaskCompletedEventPort { public interface TaskCompletedEventPort {
/** /**

View File

@ -1,15 +1,15 @@
package ch.unisg.assignment.assignment.application.service; package ch.unisg.roster.roster.application.service;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ch.unisg.assignment.assignment.application.port.in.ApplyForTaskCommand; import ch.unisg.roster.roster.application.port.in.ApplyForTaskCommand;
import ch.unisg.assignment.assignment.application.port.in.ApplyForTaskUseCase; import ch.unisg.roster.roster.application.port.in.ApplyForTaskUseCase;
import ch.unisg.assignment.assignment.application.port.out.TaskAssignedEventPort; import ch.unisg.roster.roster.application.port.out.TaskAssignedEventPort;
import ch.unisg.assignment.assignment.domain.Roster; import ch.unisg.roster.roster.domain.Roster;
import ch.unisg.assignment.assignment.domain.Task; import ch.unisg.roster.roster.domain.Task;
import ch.unisg.assignment.assignment.domain.event.TaskAssignedEvent; import ch.unisg.roster.roster.domain.event.TaskAssignedEvent;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor

View File

@ -1,12 +1,12 @@
package ch.unisg.assignment.assignment.application.service; package ch.unisg.roster.roster.application.service;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ch.unisg.assignment.assignment.application.port.in.DeleteTaskCommand; import ch.unisg.roster.roster.application.port.in.DeleteTaskCommand;
import ch.unisg.assignment.assignment.application.port.in.DeleteTaskUseCase; import ch.unisg.roster.roster.application.port.in.DeleteTaskUseCase;
import ch.unisg.assignment.assignment.domain.Roster; import ch.unisg.roster.roster.domain.Roster;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor

View File

@ -1,16 +1,16 @@
package ch.unisg.assignment.assignment.application.service; package ch.unisg.roster.roster.application.service;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ch.unisg.assignment.assignment.application.port.in.NewTaskCommand; import ch.unisg.roster.roster.application.port.in.NewTaskCommand;
import ch.unisg.assignment.assignment.application.port.in.NewTaskUseCase; import ch.unisg.roster.roster.application.port.in.NewTaskUseCase;
import ch.unisg.assignment.assignment.application.port.out.GetAllExecutorInExecutorPoolByTypePort; import ch.unisg.roster.roster.application.port.out.NewTaskEventPort;
import ch.unisg.assignment.assignment.application.port.out.NewTaskEventPort; import ch.unisg.roster.roster.domain.ExecutorRegistry;
import ch.unisg.assignment.assignment.domain.Roster; import ch.unisg.roster.roster.domain.Roster;
import ch.unisg.assignment.assignment.domain.Task; import ch.unisg.roster.roster.domain.Task;
import ch.unisg.assignment.assignment.domain.event.NewTaskEvent; import ch.unisg.roster.roster.domain.event.NewTaskEvent;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor
@ -19,7 +19,6 @@ import lombok.RequiredArgsConstructor;
public class NewTaskService implements NewTaskUseCase { public class NewTaskService implements NewTaskUseCase {
private final NewTaskEventPort newTaskEventPort; private final NewTaskEventPort newTaskEventPort;
private final GetAllExecutorInExecutorPoolByTypePort getAllExecutorInExecutorPoolByTypePort;
/** /**
* Checks if we can execute the give task, if yes the task gets added to the task queue and return true. * Checks if we can execute the give task, if yes the task gets added to the task queue and return true.
@ -29,9 +28,10 @@ public class NewTaskService implements NewTaskUseCase {
@Override @Override
public boolean addNewTaskToQueue(NewTaskCommand command) { public boolean addNewTaskToQueue(NewTaskCommand command) {
// if (!getAllExecutorInExecutorPoolByTypePort.doesExecutorTypeExist(command.getTaskType())) { ExecutorRegistry executorRegistry = ExecutorRegistry.getInstance();
// return false; if (!executorRegistry.containsTaskType(command.getTaskType())) {
// } return false;
}
Task task = new Task(command.getTaskID(), command.getTaskType()); Task task = new Task(command.getTaskID(), command.getTaskType());

View File

@ -1,14 +1,14 @@
package ch.unisg.assignment.assignment.application.service; package ch.unisg.roster.roster.application.service;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ch.unisg.assignment.assignment.application.port.in.TaskCompletedCommand; import ch.unisg.roster.roster.application.port.in.TaskCompletedCommand;
import ch.unisg.assignment.assignment.application.port.in.TaskCompletedUseCase; import ch.unisg.roster.roster.application.port.in.TaskCompletedUseCase;
import ch.unisg.assignment.assignment.application.port.out.TaskCompletedEventPort; import ch.unisg.roster.roster.application.port.out.TaskCompletedEventPort;
import ch.unisg.assignment.assignment.domain.Roster; import ch.unisg.roster.roster.domain.Roster;
import ch.unisg.assignment.assignment.domain.event.TaskCompletedEvent; import ch.unisg.roster.roster.domain.event.TaskCompletedEvent;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor

View File

@ -1,6 +1,6 @@
package ch.unisg.assignment.assignment.domain; package ch.unisg.roster.roster.domain;
import ch.unisg.assignment.assignment.domain.valueobject.ExecutorType; import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
import ch.unisg.common.valueobject.ExecutorURI; import ch.unisg.common.valueobject.ExecutorURI;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;

View File

@ -0,0 +1,92 @@
package ch.unisg.roster.roster.domain;
import java.util.*;
import ch.unisg.common.valueobject.ExecutorURI;
import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
/**
* Registry that keeps a track of executors internal to the TAPAS application and the types of tasks
* they can achieve. One executor may correspond to multiple task types.
* This class is a singleton.
*/
public class ExecutorRegistry {
private static ExecutorRegistry registry;
private final Map<ExecutorType, Set<ExecutorURI>> executors;
private ExecutorRegistry() {
this.executors = new Hashtable<>();
}
public static synchronized ExecutorRegistry getInstance() {
if (registry == null) {
registry = new ExecutorRegistry();
}
return registry;
}
/**
* Adds an executor to the registry for a given task type.
*
* @param taskType the type of the task
* @param executorIdentifier the identifier of the executor (can be any string)
* @return true unless a runtime exception occurs
*/
public boolean addExecutor(ExecutorType executorType, ExecutorURI executorURI) {
Set<ExecutorURI> taskTypeExecs = executors.getOrDefault(executorType,
Collections.synchronizedSet(new HashSet<>()));
taskTypeExecs.add(executorURI);
executors.put(executorType, taskTypeExecs);
return true;
}
/**
* Removes an executor from the registry. The executor is disassociated from all known task types.
*
* @param executorURI the identifier of the executor
* @return true unless a runtime exception occurs
*/
public boolean removeExecutor(ExecutorURI executorURI) {
Iterator<ExecutorType> iterator = executors.keySet().iterator();
while (iterator.hasNext()) {
ExecutorType executorType = iterator.next();
Set<ExecutorURI> set = executors.get(executorType);
set.remove(executorURI);
if (set.isEmpty()) {
iterator.remove();
}
}
return true;
}
/**
* Checks if the registry contains an executor for a given task type. Used during task creation
* to decide if a task can be executed.
*
* @param taskType the task type being auctioned
* @return
*/
public boolean containsTaskType(ExecutorType taskType) {
return executors.containsKey(taskType);
}
/**
* Adds a list of executors to current executor list. Should only be used on startup to
* add all available executors from the executor pool to the registry.
*
* @param executors the initial executors
* @return
*/
public void init(Map<ExecutorType, Set<ExecutorURI>> executors) {
this.executors.putAll(executors);
}
}

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.domain; package ch.unisg.roster.roster.domain;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -6,7 +6,7 @@ import java.util.HashMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import ch.unisg.assignment.assignment.domain.valueobject.ExecutorType; import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
import ch.unisg.common.valueobject.ExecutorURI; import ch.unisg.common.valueobject.ExecutorURI;
public class Roster { public class Roster {

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.domain; package ch.unisg.roster.roster.domain;
import ch.unisg.common.valueobject.ExecutorURI; import ch.unisg.common.valueobject.ExecutorURI;
import lombok.Getter; import lombok.Getter;

View File

@ -1,6 +1,6 @@
package ch.unisg.assignment.assignment.domain; package ch.unisg.roster.roster.domain;
import ch.unisg.assignment.assignment.domain.valueobject.ExecutorType; import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;

View File

@ -1,6 +1,6 @@
package ch.unisg.assignment.assignment.domain.event; package ch.unisg.roster.roster.domain.event;
import ch.unisg.assignment.assignment.domain.valueobject.ExecutorType; import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
public class NewTaskEvent { public class NewTaskEvent {
public final ExecutorType taskType; public final ExecutorType taskType;

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.domain.event; package ch.unisg.roster.roster.domain.event;
public class TaskAssignedEvent { public class TaskAssignedEvent {
public final String taskID; public final String taskID;

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.domain.event; package ch.unisg.roster.roster.domain.event;
public class TaskCompletedEvent { public class TaskCompletedEvent {
public final String taskID; public final String taskID;

View File

@ -1,4 +1,4 @@
package ch.unisg.assignment.assignment.domain.valueobject; package ch.unisg.roster.roster.domain.valueobject;
import lombok.Value; import lombok.Value;

View File

@ -1,10 +1,10 @@
package ch.unisg.assignment; package ch.unisg.roster;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest @SpringBootTest
class AssignmentApplicationTests { class RosterApplicationTests {
@Test @Test
void contextLoads() { void contextLoads() {