226 lines
7.7 KiB
Java
226 lines
7.7 KiB
Java
package mops.gruppen2.service;
|
|
|
|
import lombok.extern.log4j.Log4j2;
|
|
import mops.gruppen2.domain.Group;
|
|
import mops.gruppen2.domain.GroupType;
|
|
import mops.gruppen2.domain.User;
|
|
import mops.gruppen2.domain.Visibility;
|
|
import mops.gruppen2.domain.event.Event;
|
|
import mops.gruppen2.domain.exception.EventException;
|
|
import mops.gruppen2.domain.exception.GroupNotFoundException;
|
|
import org.springframework.cache.annotation.Cacheable;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.UUID;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* Liefert verschiedene Projektionen auf Gruppen.
|
|
* Benötigt ausschließlich den EventStoreService.
|
|
*/
|
|
@Service
|
|
@Log4j2
|
|
public class ProjectionService {
|
|
|
|
private final EventStoreService eventStoreService;
|
|
|
|
public ProjectionService(EventStoreService eventStoreService) {
|
|
this.eventStoreService = eventStoreService;
|
|
}
|
|
|
|
|
|
// ################################## STATISCHE PROJEKTIONEN #################################
|
|
|
|
|
|
/**
|
|
* Konstruiert Gruppen aus einer Liste von Events.
|
|
*
|
|
* @param events Liste an Events
|
|
*
|
|
* @return Liste an Projizierten Gruppen
|
|
*
|
|
* @throws EventException Projektionsfehler
|
|
*/
|
|
static List<Group> projectGroups(List<Event> events) throws EventException {
|
|
Map<UUID, Group> groupMap = new HashMap<>();
|
|
|
|
events.forEach(event -> event.apply(getOrCreateGroup(groupMap, event.getGroupId())));
|
|
|
|
return new ArrayList<>(groupMap.values());
|
|
}
|
|
|
|
/**
|
|
* Projiziert Events, geht aber davon aus, dass alle zu derselben Gruppe gehören.
|
|
*
|
|
* @param events Eventliste
|
|
*
|
|
* @return Eine projizierte Gruppe
|
|
*
|
|
* @throws EventException Projektionsfehler, z.B. falls Events von verschiedenen Gruppen übergeben werden
|
|
*/
|
|
static Group projectSingleGroup(List<Event> events) throws EventException {
|
|
if (events.isEmpty()) {
|
|
throw new GroupNotFoundException(ProjectionService.class.toString());
|
|
}
|
|
|
|
Group group = new Group();
|
|
|
|
events.forEach(event -> event.apply(group));
|
|
|
|
return group;
|
|
}
|
|
|
|
/**
|
|
* Gibt die Gruppe mit der richtigen Id aus der übergebenen Map wieder, existiert diese nicht
|
|
* wird die Gruppe erstellt und der Map hizugefügt.
|
|
*
|
|
* @param groups Map aus GruppenIds und Gruppen
|
|
* @param groupId Die Id der Gruppe, die zurückgegeben werden soll
|
|
*
|
|
* @return Die gesuchte Gruppe
|
|
*/
|
|
private static Group getOrCreateGroup(Map<UUID, Group> groups, UUID groupId) {
|
|
if (!groups.containsKey(groupId)) {
|
|
groups.put(groupId, new Group());
|
|
}
|
|
|
|
return groups.get(groupId);
|
|
}
|
|
|
|
|
|
// ############################### PROJEKTIONEN MIT DATENBANK ################################
|
|
|
|
|
|
/**
|
|
* Projiziert Gruppen, welche sich seit einer übergebenen eventId geändert haben.
|
|
* Die Gruppen werden dabei vollständig konstruiert.
|
|
*
|
|
* @param status Letzte bekannte eventId
|
|
*
|
|
* @return Liste an Gruppen
|
|
*/
|
|
public List<Group> projectNewGroups(long status) {
|
|
List<Event> events = eventStoreService.findChangedGroupEvents(status);
|
|
|
|
return projectGroups(events);
|
|
}
|
|
|
|
/**
|
|
* Projiziert öffentliche Gruppen.
|
|
* Die Gruppen enthalten Metainformationen: Titel, Beschreibung und MaxUserAnzahl.
|
|
* Außerdem wird noch beachtet, ob der eingeloggte User bereits in entsprechenden Gruppen mitglied ist.
|
|
*
|
|
* @return Liste von projizierten Gruppen
|
|
*
|
|
* @throws EventException Projektionsfehler
|
|
*/
|
|
@Cacheable("groups")
|
|
//TODO: remove userID param
|
|
public List<Group> projectPublicGroups() throws EventException {
|
|
List<UUID> groupIds = eventStoreService.findExistingGroupIds();
|
|
List<Event> events = eventStoreService.findEventsByGroupAndType(groupIds,
|
|
"CreateGroupEvent",
|
|
"UpdateGroupDescriptionEvent",
|
|
"UpdateGroupTitleEvent",
|
|
"UpdateUserMaxEvent");
|
|
|
|
List<Group> groups = projectGroups(events);
|
|
|
|
return groups.stream()
|
|
.filter(group -> group.getVisibility() == Visibility.PUBLIC)
|
|
.collect(Collectors.toList());
|
|
}
|
|
|
|
/**
|
|
* Projiziert Vorlesungen.
|
|
* Projektionen enthalten nur Metainformationen: Titel.
|
|
*
|
|
* @return Liste von Veranstaltungen
|
|
*/
|
|
@Cacheable("groups")
|
|
public List<Group> projectLectures() {
|
|
List<UUID> groupIds = eventStoreService.findExistingGroupIds();
|
|
List<Event> events = eventStoreService.findEventsByGroupAndType(groupIds,
|
|
"CreateGroupEvent",
|
|
"UpdateGroupTitleEvent");
|
|
|
|
List<Group> lectures = projectGroups(events);
|
|
|
|
return lectures.stream()
|
|
.filter(group -> group.getType() == GroupType.LECTURE)
|
|
.collect(Collectors.toList());
|
|
}
|
|
|
|
/**
|
|
* Projiziert Gruppen, in welchen der User aktuell teilnimmt.
|
|
* Die Gruppen enthalten nur Metainformationen: Titel und Beschreibung.
|
|
*
|
|
* @param user Die Id
|
|
*
|
|
* @return Liste aus Gruppen
|
|
*/
|
|
@Cacheable("groups")
|
|
public List<Group> projectUserGroups(User user) {
|
|
List<UUID> groupIds = eventStoreService.findExistingUserGroups(user);
|
|
List<Event> groupEvents = eventStoreService.findEventsByGroupAndType(groupIds,
|
|
"CreateGroupEvent",
|
|
"UpdateGroupTitleEvent",
|
|
"UpdateGroupDescriptionEvent");
|
|
|
|
return projectGroups(groupEvents);
|
|
}
|
|
|
|
/**
|
|
* Gibt die Gruppe zurück, die zu der übergebenen Id passt.
|
|
* Enthält alle verfügbaren Informationen, also auch User (langsam).
|
|
* Gibt eine leere Gruppe zurück, falls die Id leer ist.
|
|
*
|
|
* @param groupId Die Id der gesuchten Gruppe
|
|
*
|
|
* @return Die gesuchte Gruppe
|
|
*
|
|
* @throws GroupNotFoundException Wenn die Gruppe nicht gefunden wird
|
|
*/
|
|
public Group projectSingleGroup(UUID groupId) throws GroupNotFoundException {
|
|
if (IdService.isEmpty(groupId)) {
|
|
throw new GroupNotFoundException(groupId + ": " + ProjectionService.class);
|
|
}
|
|
|
|
try {
|
|
List<Event> events = eventStoreService.findGroupEvents(groupId);
|
|
return projectSingleGroup(events);
|
|
} catch (Exception e) {
|
|
log.error("Gruppe {} wurde nicht gefunden!", groupId.toString(), e);
|
|
throw new GroupNotFoundException(groupId + ": " + ProjectionService.class);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Projiziert eine einzelne Gruppe, welche leer sein darf.
|
|
*/
|
|
public Group projectParent(UUID parentId) {
|
|
if (IdService.isEmpty(parentId)) {
|
|
return new Group();
|
|
}
|
|
|
|
return projectSingleGroup(parentId);
|
|
}
|
|
|
|
/**
|
|
* Entfernt alle Gruppen, in welchen ein User teilnimmt, aus einer Gruppenliste.
|
|
*
|
|
* @param groups Gruppenliste, aus der entfernt wird
|
|
* @param user User, welcher teilnimmt
|
|
*/
|
|
void removeUserGroups(List<Group> groups, User user) {
|
|
List<UUID> userGroups = eventStoreService.findExistingUserGroups(user);
|
|
|
|
groups.removeIf(group -> userGroups.contains(group.getId()));
|
|
}
|
|
}
|
|
|