1

new eventbuilderservice + projectionservice + searchservice, some renamings etc

This commit is contained in:
Christoph
2020-04-06 00:07:46 +02:00
parent 5a5d1586ed
commit 3d66f58af8
17 changed files with 503 additions and 389 deletions

View File

@ -7,9 +7,10 @@ import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.api.GroupRequestWrapper;
import mops.gruppen2.domain.event.Event;
import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.service.APIFormatterService;
import mops.gruppen2.service.EventService;
import mops.gruppen2.service.APIService;
import mops.gruppen2.service.EventStoreService;
import mops.gruppen2.service.GroupService;
import mops.gruppen2.service.ProjectionService;
import mops.gruppen2.service.UserService;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
@ -29,23 +30,25 @@ import java.util.stream.Collectors;
@RequestMapping("/gruppen2/api")
public class APIController {
private final EventService eventService;
private final EventStoreService eventStoreService;
private final GroupService groupService;
private final UserService userService;
private final ProjectionService projectionService;
public APIController(EventService eventService, GroupService groupService, UserService userService) {
this.eventService = eventService;
public APIController(EventStoreService eventStoreService, GroupService groupService, UserService userService, ProjectionService projectionService) {
this.eventStoreService = eventStoreService;
this.groupService = groupService;
this.userService = userService;
this.projectionService = projectionService;
}
@GetMapping("/updateGroups/{lastEventId}")
@Secured("ROLE_api_user")
@ApiOperation("Gibt alle Gruppen zurück, in denen sich etwas geändert hat")
public GroupRequestWrapper updateGroups(@ApiParam("Letzter Status des Anfragestellers") @PathVariable Long lastEventId) throws EventException {
List<Event> events = eventService.getNewEvents(lastEventId);
List<Event> events = eventStoreService.getNewEvents(lastEventId);
return APIFormatterService.wrap(eventService.getMaxEventId(), groupService.projectEventList(events));
return APIService.wrap(eventStoreService.getMaxEventId(), projectionService.projectEventList(events));
}
@GetMapping("/getGroupIdsOfUser/{userId}")
@ -61,8 +64,8 @@ public class APIController {
@Secured("ROLE_api_user")
@ApiOperation("Gibt die Gruppe mit der als Parameter mitgegebenden groupId zurück")
public Group getGroupById(@ApiParam("GruppenId der gefordeten Gruppe") @PathVariable String groupId) throws EventException {
List<Event> eventList = eventService.getEventsOfGroup(UUID.fromString(groupId));
List<Group> groups = groupService.projectEventList(eventList);
List<Event> eventList = eventStoreService.getEventsOfGroup(UUID.fromString(groupId));
List<Group> groups = projectionService.projectEventList(eventList);
if (groups.isEmpty()) {
return null;

View File

@ -4,6 +4,7 @@ import mops.gruppen2.domain.Account;
import mops.gruppen2.service.ControllerService;
import mops.gruppen2.service.GroupService;
import mops.gruppen2.service.KeyCloakService;
import mops.gruppen2.service.ProjectionService;
import mops.gruppen2.service.ValidationService;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.springframework.cache.annotation.CacheEvict;
@ -27,11 +28,13 @@ public class GroupCreationController {
private final GroupService groupService;
private final ControllerService controllerService;
private final ValidationService validationService;
private final ProjectionService projectionService;
public GroupCreationController(GroupService groupService, ControllerService controllerService, ValidationService validationService) {
public GroupCreationController(GroupService groupService, ControllerService controllerService, ValidationService validationService, ProjectionService projectionService) {
this.groupService = groupService;
this.controllerService = controllerService;
this.validationService = validationService;
this.projectionService = projectionService;
}
@RolesAllowed({"ROLE_orga", "ROLE_actuator"})
@ -42,7 +45,7 @@ public class GroupCreationController {
Account account = KeyCloakService.createAccountFromPrincipal(token);
model.addAttribute("account", account);
model.addAttribute("lectures", groupService.getAllLecturesWithVisibilityPublic());
model.addAttribute("lectures", projectionService.getAllLecturesWithVisibilityPublic());
return "createOrga";
}
@ -85,7 +88,7 @@ public class GroupCreationController {
Account account = KeyCloakService.createAccountFromPrincipal(token);
model.addAttribute("account", account);
model.addAttribute("lectures", groupService.getAllLecturesWithVisibilityPublic());
model.addAttribute("lectures", projectionService.getAllLecturesWithVisibilityPublic());
return "createStudent";
}

View File

@ -7,11 +7,19 @@ import org.springframework.stereotype.Service;
import java.util.List;
@Service
public final class APIFormatterService {
public class APIService {
private APIFormatterService() {}
// private APIService() {}
public static GroupRequestWrapper wrap(long status, List<Group> groupList) {
return new GroupRequestWrapper(status, groupList);
}
// public static void updateGroups()
// public static void getGroupIdsOfUser()
// public static void getGroupById()
// public static void updateNecessary()
}

View File

@ -15,18 +15,15 @@ import mops.gruppen2.domain.event.UpdateGroupTitleEvent;
import mops.gruppen2.domain.event.UpdateRoleEvent;
import mops.gruppen2.domain.event.UpdateUserMaxEvent;
import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.domain.exception.WrongFileException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import static mops.gruppen2.domain.Role.ADMIN;
@ -35,29 +32,18 @@ import static mops.gruppen2.domain.Role.ADMIN;
public class ControllerService {
private static final Logger LOG = LoggerFactory.getLogger("controllerServiceLogger");
private final EventService eventService;
private final EventStoreService eventStoreService;
private final UserService userService;
private final ValidationService validationService;
private final InviteService inviteService;
public ControllerService(EventService eventService, UserService userService, ValidationService validationService, InviteService inviteService) {
this.eventService = eventService;
public ControllerService(EventStoreService eventStoreService, UserService userService, ValidationService validationService, InviteService inviteService) {
this.eventStoreService = eventStoreService;
this.userService = userService;
this.validationService = validationService;
this.inviteService = inviteService;
}
private static User getVeteranMember(Account account, Group group) {
List<User> members = group.getMembers();
String newAdminId;
if (members.get(0).getId().equals(account.getName())) {
newAdminId = members.get(1).getId();
} else {
newAdminId = members.get(0).getId();
}
return new User(newAdminId, "", "", "");
}
/**
* Wie createGroup, nur das hier die Gruppe auch als Veranstaltung gesetzt werden kann und CSV Dateien mit Nutzern
* eingelesen werden können.
@ -72,6 +58,8 @@ public class ControllerService {
* @param parent Parameter für die neue Gruppe
* @param file Parameter für die neue Gruppe
*/
//TODO: remove booleans + add wrapper?
//TODO: auslagern teilweise -> EventBuilderService
public void createGroupAsOrga(Account account,
String title,
String description,
@ -82,17 +70,17 @@ public class ControllerService {
UUID parent,
MultipartFile file) {
userMaximum = checkInfiniteUsers(isMaximumInfinite, userMaximum);
userMaximum = GroupService.checkInfiniteUsers(isMaximumInfinite, userMaximum);
List<User> newUsers = readCsvFile(file);
List<User> newUsers = CsvService.readCsvFile(file);
List<User> oldUsers = new ArrayList<>();
User user = new User(account);
oldUsers.add(user);
removeOldUsersFromNewUsers(oldUsers, newUsers);
GroupService.removeOldUsersFromNewUsers(oldUsers, newUsers);
userMaximum = adjustUserMaximum((long) newUsers.size(), 1L, userMaximum);
userMaximum = GroupService.adjustUserMaximum((long) newUsers.size(), 1L, userMaximum);
UUID groupId = createGroup(account,
title,
@ -105,25 +93,6 @@ public class ControllerService {
addUserList(newUsers, groupId);
}
/**
* Wenn die maximale Useranzahl unendlich ist, wird das Maximum auf 100000 gesetzt. Praktisch gibt es also Maximla 100000
* Nutzer pro Gruppe.
*
* @param isMaximumInfinite Gibt an ob es unendlich viele User geben soll
* @param userMaximum Das Maximum an Usern, falls es eins gibt
*
* @return Maximum an Usern
*/
private static Long checkInfiniteUsers(Boolean isMaximumInfinite, Long userMaximum) {
isMaximumInfinite = isMaximumInfinite != null;
if (isMaximumInfinite) {
userMaximum = 100_000L;
}
return userMaximum;
}
/**
* Erzeugt eine neue Gruppe, fügt den User, der die Gruppe erstellt hat, hinzu und setzt seine Rolle als Admin fest.
* Zudem wird der Gruppentitel und die Gruppenbeschreibung erzeugt, welche vorher der Methode übergeben wurden.
@ -133,7 +102,8 @@ public class ControllerService {
* @param title Gruppentitel
* @param description Gruppenbeschreibung
*/
//TODO: remove booleans
//TODO: remove booleans + add wrapper?
//TODO: auslagern teilweise -> EventBuilderService
public UUID createGroup(Account account,
String title,
String description,
@ -143,12 +113,12 @@ public class ControllerService {
Long userMaximum,
UUID parent) {
userMaximum = checkInfiniteUsers(isMaximumInfinite, userMaximum);
userMaximum = GroupService.checkInfiniteUsers(isMaximumInfinite, userMaximum);
Visibility groupVisibility = setGroupVisibility(isVisibilityPrivate);
Visibility groupVisibility = GroupService.setGroupVisibility(isVisibilityPrivate);
UUID groupId = UUID.randomUUID();
GroupType groupType = setGroupType(isLecture);
GroupType groupType = GroupService.setGroupType(isLecture);
CreateGroupEvent createGroupEvent = new CreateGroupEvent(groupId,
account.getName(),
@ -156,7 +126,7 @@ public class ControllerService {
groupType,
groupVisibility,
userMaximum);
eventService.saveEvent(createGroupEvent);
eventStoreService.saveEvent(createGroupEvent);
inviteService.createLink(groupId);
@ -170,35 +140,7 @@ public class ControllerService {
return groupId;
}
private static List<User> readCsvFile(MultipartFile file) throws EventException {
if (file == null) {
return new ArrayList<>();
}
if (!file.isEmpty()) {
try {
List<User> userList = CsvService.read(file.getInputStream());
return userList.stream().distinct().collect(Collectors.toList()); //filters duplicates from list
} catch (IOException ex) {
LOG.warn("File konnte nicht gelesen werden");
throw new WrongFileException(file.getOriginalFilename());
}
}
return new ArrayList<>();
}
private static void removeOldUsersFromNewUsers(List<User> oldUsers, List<User> newUsers) {
for (User oldUser : oldUsers) {
newUsers.remove(oldUser);
}
}
private static Long adjustUserMaximum(Long newUsers, Long oldUsers, Long maxUsers) {
if (oldUsers + newUsers > maxUsers) {
maxUsers = oldUsers + newUsers;
}
return maxUsers;
}
//TODO: GroupService/eventbuilderservice
private void addUserList(List<User> newUsers, UUID groupId) {
for (User user : newUsers) {
Group group = userService.getGroupById(groupId);
@ -206,40 +148,24 @@ public class ControllerService {
LOG.info("Benutzer {} ist bereits in Gruppe", user.getId());
} else {
AddUserEvent addUserEvent = new AddUserEvent(groupId, user.getId(), user.getGivenname(), user.getFamilyname(), user.getEmail());
eventService.saveEvent(addUserEvent);
eventStoreService.saveEvent(addUserEvent);
}
}
}
private static Visibility setGroupVisibility(Boolean isVisibilityPrivate) {
isVisibilityPrivate = isVisibilityPrivate != null;
if (isVisibilityPrivate) {
return Visibility.PRIVATE;
} else {
return Visibility.PUBLIC;
}
}
private static GroupType setGroupType(Boolean isLecture) {
isLecture = isLecture != null;
if (isLecture) {
return GroupType.LECTURE;
} else {
return GroupType.SIMPLE;
}
}
//TODO: GroupService/eventbuilderservice
public void addUser(Account account, UUID groupId) {
AddUserEvent addUserEvent = new AddUserEvent(groupId, account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail());
eventService.saveEvent(addUserEvent);
eventStoreService.saveEvent(addUserEvent);
}
//TODO: GroupService/eventbuilderservice
private void updateTitle(Account account, UUID groupId, String title) {
UpdateGroupTitleEvent updateGroupTitleEvent = new UpdateGroupTitleEvent(groupId, account.getName(), title);
eventService.saveEvent(updateGroupTitleEvent);
eventStoreService.saveEvent(updateGroupTitleEvent);
}
//TODO: GroupService/eventbuilderservice
public void updateRole(User user, UUID groupId) throws EventException {
UpdateRoleEvent updateRoleEvent;
Group group = userService.getGroupById(groupId);
@ -250,23 +176,25 @@ public class ControllerService {
} else {
updateRoleEvent = new UpdateRoleEvent(group.getId(), user.getId(), ADMIN);
}
eventService.saveEvent(updateRoleEvent);
eventStoreService.saveEvent(updateRoleEvent);
}
//TODO: GroupService/eventbuilderservice
private void updateDescription(Account account, UUID groupId, String description) {
UpdateGroupDescriptionEvent updateGroupDescriptionEvent = new UpdateGroupDescriptionEvent(groupId, account.getName(), description);
eventService.saveEvent(updateGroupDescriptionEvent);
eventStoreService.saveEvent(updateGroupDescriptionEvent);
}
//TODO: GroupService
public void addUsersFromCsv(Account account, MultipartFile file, String groupId) {
Group group = userService.getGroupById(UUID.fromString(groupId));
List<User> newUserList = readCsvFile(file);
removeOldUsersFromNewUsers(group.getMembers(), newUserList);
List<User> newUserList = CsvService.readCsvFile(file);
GroupService.removeOldUsersFromNewUsers(group.getMembers(), newUserList);
UUID groupUUID = getUUID(groupId);
Long newUserMaximum = adjustUserMaximum((long) newUserList.size(), (long) group.getMembers().size(), group.getUserMaximum());
Long newUserMaximum = GroupService.adjustUserMaximum((long) newUserList.size(), (long) group.getMembers().size(), group.getUserMaximum());
if (newUserMaximum > group.getUserMaximum()) {
updateMaxUser(account, groupUUID, newUserMaximum);
}
@ -274,15 +202,18 @@ public class ControllerService {
addUserList(newUserList, groupUUID);
}
//TODO: GroupService
public UUID getUUID(String id) {
return UUID.fromString(Objects.requireNonNullElse(id, "00000000-0000-0000-0000-000000000000"));
}
//TODO: GroupService/eventbuilderservice
public void updateMaxUser(Account account, UUID groupId, Long userMaximum) {
UpdateUserMaxEvent updateUserMaxEvent = new UpdateUserMaxEvent(groupId, account.getName(), userMaximum);
eventService.saveEvent(updateUserMaxEvent);
eventStoreService.saveEvent(updateUserMaxEvent);
}
//TODO: GroupService
public void changeMetaData(Account account, Group group, String title, String description) {
if (!title.equals(group.getTitle())) {
updateTitle(account, group.getId(), title);
@ -293,14 +224,16 @@ public class ControllerService {
}
}
//TODO: GroupService oder in Group?
public Group getParent(UUID parentId) {
Group parent = new Group();
if (!idIsEmpty(parentId)) {
if (!GroupService.idIsEmpty(parentId)) {
parent = userService.getGroupById(parentId);
}
return parent;
}
//TODO: GroupService
public void deleteUser(Account account, User user, Group group) throws EventException {
changeRoleIfLastAdmin(account, group);
@ -313,32 +246,28 @@ public class ControllerService {
}
}
private static boolean idIsEmpty(UUID id) {
if (id == null) {
return true;
}
return "00000000-0000-0000-0000-000000000000".equals(id.toString());
}
//TODO: GroupService/eventbuilderservice
private void deleteUserEvent(User user, UUID groupId) {
DeleteUserEvent deleteUserEvent = new DeleteUserEvent(groupId, user.getId());
eventService.saveEvent(deleteUserEvent);
eventStoreService.saveEvent(deleteUserEvent);
}
//TODO: GroupService/eventbuilderservice
public void deleteGroupEvent(String userId, UUID groupId) {
DeleteGroupEvent deleteGroupEvent = new DeleteGroupEvent(groupId, userId);
inviteService.destroyLink(groupId);
eventService.saveEvent(deleteGroupEvent);
eventStoreService.saveEvent(deleteGroupEvent);
}
//TODO: GroupService
private void promoteVeteranMember(Account account, Group group) {
if (validationService.checkIfLastAdmin(account, group)) {
User newAdmin = getVeteranMember(account, group);
User newAdmin = GroupService.getVeteranMember(account, group);
updateRole(newAdmin, group.getId());
}
}
//TODO: GroupService
public void changeRoleIfLastAdmin(Account account, Group group) {
if (group.getMembers().size() <= 1) {
return;
@ -346,6 +275,7 @@ public class ControllerService {
promoteVeteranMember(account, group);
}
//TODO: GroupService
public void changeRole(Account account, User user, Group group) {
if (user.getId().equals(account.getName())) {
if (group.getMembers().size() <= 1) {

View File

@ -4,15 +4,24 @@ import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import mops.gruppen2.domain.User;
import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.domain.exception.WrongFileException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service
public final class CsvService {
private static final Logger LOG = LoggerFactory.getLogger(CsvService.class);
private CsvService() {}
static List<User> read(InputStream stream) throws IOException {
@ -23,4 +32,21 @@ public final class CsvService {
return reader.<User>readValues(stream).readAll();
}
//TODO: CsvService
static List<User> readCsvFile(MultipartFile file) throws EventException {
if (file == null) {
return new ArrayList<>();
}
if (!file.isEmpty()) {
try {
List<User> userList = read(file.getInputStream());
return userList.stream().distinct().collect(Collectors.toList()); //filters duplicates from list
} catch (IOException ex) {
LOG.warn("File konnte nicht gelesen werden");
throw new WrongFileException(file.getOriginalFilename());
}
}
return new ArrayList<>();
}
}

View File

@ -0,0 +1,4 @@
package mops.gruppen2.service;
public class EventBuilderService {
}

View File

@ -15,12 +15,12 @@ import java.util.stream.Collectors;
@Service
//TODO: Evtl aufsplitten in EventRepoService und EventService?
public class EventService {
public class EventStoreService {
private static final Logger LOG = LoggerFactory.getLogger(EventService.class);
private static final Logger LOG = LoggerFactory.getLogger(EventStoreService.class);
private final EventRepository eventStore;
public EventService(EventRepository eventStore) {
public EventStoreService(EventRepository eventStore) {
this.eventStore = eventStore;
}

View File

@ -3,32 +3,101 @@ package mops.gruppen2.service;
import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.User;
import mops.gruppen2.domain.Visibility;
import mops.gruppen2.domain.dto.EventDTO;
import mops.gruppen2.domain.event.Event;
import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.repository.EventRepository;
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;
/**
* Behandelt Aufgaben, welche sich auf eine Gruppe beziehen
*/
@Service
public class GroupService {
private final EventService eventService;
private final EventStoreService eventStoreService;
private final EventRepository eventRepository;
public GroupService(EventService eventService, EventRepository eventRepository) {
this.eventService = eventService;
public GroupService(EventStoreService eventStoreService, EventRepository eventRepository) {
this.eventStoreService = eventStoreService;
this.eventRepository = eventRepository;
}
static User getVeteranMember(Account account, Group group) {
List<User> members = group.getMembers();
String newAdminId;
if (members.get(0).getId().equals(account.getName())) {
newAdminId = members.get(1).getId();
} else {
newAdminId = members.get(0).getId();
}
return new User(newAdminId, "", "", "");
}
/**
* Wenn die maximale Useranzahl unendlich ist, wird das Maximum auf 100000 gesetzt. Praktisch gibt es also Maximla 100000
* Nutzer pro Gruppe.
*
* @param isMaximumInfinite Gibt an ob es unendlich viele User geben soll
* @param userMaximum Das Maximum an Usern, falls es eins gibt
*
* @return Maximum an Usern
*/
static Long checkInfiniteUsers(Boolean isMaximumInfinite, Long userMaximum) {
isMaximumInfinite = isMaximumInfinite != null;
if (isMaximumInfinite) {
userMaximum = 100_000L;
}
return userMaximum;
}
static void removeOldUsersFromNewUsers(List<User> oldUsers, List<User> newUsers) {
for (User oldUser : oldUsers) {
newUsers.remove(oldUser);
}
}
static Long adjustUserMaximum(Long newUsers, Long oldUsers, Long maxUsers) {
if (oldUsers + newUsers > maxUsers) {
maxUsers = oldUsers + newUsers;
}
return maxUsers;
}
static Visibility setGroupVisibility(Boolean isVisibilityPrivate) {
isVisibilityPrivate = isVisibilityPrivate != null;
if (isVisibilityPrivate) {
return Visibility.PRIVATE;
} else {
return Visibility.PUBLIC;
}
}
static GroupType setGroupType(Boolean isLecture) {
isLecture = isLecture != null;
if (isLecture) {
return GroupType.LECTURE;
} else {
return GroupType.SIMPLE;
}
}
static boolean idIsEmpty(UUID id) {
if (id == null) {
return true;
}
return "00000000-0000-0000-0000-000000000000".equals(id.toString());
}
/**
* Sucht in der DB alle Zeilen raus welche eine der Gruppen_ids hat.
* Wandelt die Zeilen in Events um und gibt davon eine Liste zurück.
@ -43,128 +112,7 @@ public class GroupService {
for (UUID groupId : groupIds) {
eventDTOS.addAll(eventRepository.findEventDTOByGroupId(groupId.toString()));
}
return eventService.getEventsFromDTOs(eventDTOS);
return eventStoreService.getEventsFromDTOs(eventDTOS);
}
/**
* Wird verwendet beim Gruppe erstellen bei der Parent-Auswahl: nur Titel benötigt.
*
* @return List of groups
*/
@Cacheable("groups")
public List<Group> getAllLecturesWithVisibilityPublic() {
List<Event> createEvents = eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("CreateGroupEvent"));
createEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("DeleteGroupEvent")));
createEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateGroupTitleEvent")));
createEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("DeleteGroupEvent")));
List<Group> visibleGroups = projectEventList(createEvents);
return visibleGroups.stream()
.filter(group -> group.getType() == GroupType.LECTURE)
.filter(group -> group.getVisibility() == Visibility.PUBLIC)
.collect(Collectors.toList());
}
/**
* Erzeugt eine neue Map wo Gruppen aus den Events erzeugt und den Gruppen_ids zugeordnet werden.
* Die Gruppen werden als Liste zurückgegeben.
*
* @param events Liste an Events
*
* @return Liste an Projizierten Gruppen
*
* @throws EventException Projektionsfehler
*/
public List<Group> projectEventList(List<Event> events) throws EventException {
Map<UUID, Group> groupMap = new HashMap<>();
events.parallelStream()
.forEachOrdered(event -> event.apply(getOrCreateGroup(groupMap, event.getGroupId())));
return new ArrayList<>(groupMap.values());
}
/**
* 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);
}
/**
* Filtert alle öffentliche Gruppen nach dem Suchbegriff und gibt diese als Liste von Gruppen zurück.
* Groß und Kleinschreibung wird nicht beachtet.
*
* @param search Der Suchstring
*
* @return Liste von projizierten Gruppen
*
* @throws EventException Projektionsfehler
*/
//Todo Rename
@Cacheable("groups")
public List<Group> findGroupWith(String search, Account account) throws EventException {
if (search.isEmpty()) {
return getAllGroupWithVisibilityPublic(account.getName());
}
return getAllGroupWithVisibilityPublic(account.getName()).parallelStream().filter(group -> group.getTitle().toLowerCase().contains(search.toLowerCase()) || group.getDescription().toLowerCase().contains(search.toLowerCase())).collect(Collectors.toList());
}
/**
* Wird verwendet bei der Suche nach Gruppen: Titel, Beschreibung werden benötigt.
* Außerdem wird beachtet, ob der eingeloggte User bereits in entsprechenden Gruppen mitglied ist.
*
* @return Liste von projizierten Gruppen
*
* @throws EventException Projektionsfehler
*/
//TODO Rename
@Cacheable("groups")
public List<Group> getAllGroupWithVisibilityPublic(String userId) throws EventException {
List<Event> groupEvents = eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("CreateGroupEvent"));
groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateGroupDescriptionEvent")));
groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateGroupTitleEvent")));
groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("DeleteGroupEvent")));
groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateUserMaxEvent")));
List<Group> visibleGroups = projectEventList(groupEvents);
sortByGroupType(visibleGroups);
return visibleGroups.stream()
.filter(group -> group.getType() != null)
.filter(group -> !eventService.userInGroup(group.getId(), userId))
.filter(group -> group.getVisibility() == Visibility.PUBLIC)
.collect(Collectors.toList());
}
/**
* Sortiert die übergebene Liste an Gruppen, sodass Veranstaltungen am Anfang der Liste sind.
*
* @param groups Die Liste von Gruppen die sortiert werden soll
*/
void sortByGroupType(List<Group> groups) {
groups.sort((Group g1, Group g2) -> {
if (g1.getType() == GroupType.LECTURE) {
return -1;
}
if (g2.getType() == GroupType.LECTURE) {
return 0;
}
return 1;
});
}
}

View File

@ -33,9 +33,8 @@ public class InviteService {
return UUID.fromString(inviteRepository.findGroupIdByLink(link));
} catch (Exception e) {
LOG.error("Gruppe zu Link ({}) konnte nicht gefunden werden!", link);
throw new InvalidInviteException(link);
}
throw new InvalidInviteException(link);
}
public String getLinkByGroupId(UUID groupId) {
@ -43,8 +42,7 @@ public class InviteService {
return inviteRepository.findLinkByGroupId(groupId.toString());
} catch (Exception e) {
LOG.error("Link zu Gruppe ({}) konnte nicht gefunden werden!", groupId);
throw new NoInviteExistException(groupId.toString());
}
throw new NoInviteExistException(groupId.toString());
}
}

View File

@ -0,0 +1,120 @@
package mops.gruppen2.service;
import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.Visibility;
import mops.gruppen2.domain.event.Event;
import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.repository.EventRepository;
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
*/
@Service
public class ProjectionService {
private final EventRepository eventRepository;
private final EventStoreService eventStoreService;
public ProjectionService(EventRepository eventRepository, EventStoreService eventStoreService) {
this.eventRepository = eventRepository;
this.eventStoreService = eventStoreService;
}
/**
* 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
*/
//TODO: ProjectionService
private static Group getOrCreateGroup(Map<UUID, Group> groups, UUID groupId) {
if (!groups.containsKey(groupId)) {
groups.put(groupId, new Group());
}
return groups.get(groupId);
}
/**
* Wird verwendet bei der Suche nach Gruppen: Titel, Beschreibung werden benötigt.
* Außerdem wird beachtet, ob der eingeloggte User bereits in entsprechenden Gruppen mitglied ist.
*
* @return Liste von projizierten Gruppen
*
* @throws EventException Projektionsfehler
*/
//TODO: ProjectionService
//TODO Rename
@Cacheable("groups")
public List<Group> getAllGroupWithVisibilityPublic(String userId) throws EventException {
List<Event> groupEvents = eventStoreService.getEventsFromDTOs(eventRepository.findAllEventsByType("CreateGroupEvent"));
groupEvents.addAll(eventStoreService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateGroupDescriptionEvent")));
groupEvents.addAll(eventStoreService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateGroupTitleEvent")));
groupEvents.addAll(eventStoreService.getEventsFromDTOs(eventRepository.findAllEventsByType("DeleteGroupEvent")));
groupEvents.addAll(eventStoreService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateUserMaxEvent")));
List<Group> visibleGroups = projectEventList(groupEvents);
SearchService.sortByGroupType(visibleGroups);
return visibleGroups.stream()
.filter(group -> group.getType() != null)
.filter(group -> !eventStoreService.userInGroup(group.getId(), userId))
.filter(group -> group.getVisibility() == Visibility.PUBLIC)
.collect(Collectors.toList());
}
/**
* Wird verwendet beim Gruppe erstellen bei der Parent-Auswahl: nur Titel benötigt.
*
* @return List of groups
*/
@Cacheable("groups")
//TODO: ProjectionService
public List<Group> getAllLecturesWithVisibilityPublic() {
List<Event> createEvents = eventStoreService.getEventsFromDTOs(eventRepository.findAllEventsByType("CreateGroupEvent"));
createEvents.addAll(eventStoreService.getEventsFromDTOs(eventRepository.findAllEventsByType("DeleteGroupEvent")));
createEvents.addAll(eventStoreService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateGroupTitleEvent")));
createEvents.addAll(eventStoreService.getEventsFromDTOs(eventRepository.findAllEventsByType("DeleteGroupEvent")));
List<Group> visibleGroups = projectEventList(createEvents);
return visibleGroups.stream()
.filter(group -> group.getType() == GroupType.LECTURE)
.filter(group -> group.getVisibility() == Visibility.PUBLIC)
.collect(Collectors.toList());
}
/**
* Erzeugt eine neue Map wo Gruppen aus den Events erzeugt und den Gruppen_ids zugeordnet werden.
* Die Gruppen werden als Liste zurückgegeben.
*
* @param events Liste an Events
*
* @return Liste an Projizierten Gruppen
*
* @throws EventException Projektionsfehler
*/
//TODO: ProjectionService
public List<Group> projectEventList(List<Event> events) throws EventException {
Map<UUID, Group> groupMap = new HashMap<>();
events.parallelStream()
.forEachOrdered(event -> event.apply(getOrCreateGroup(groupMap, event.getGroupId())));
return new ArrayList<>(groupMap.values());
}
}

View File

@ -1,6 +1,59 @@
package mops.gruppen2.service;
import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.exception.EventException;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class SearchService {}
public class SearchService {
private final ProjectionService projectionService;
public SearchService(ProjectionService projectionService) {this.projectionService = projectionService;}
/**
* Sortiert die übergebene Liste an Gruppen, sodass Veranstaltungen am Anfang der Liste sind.
*
* @param groups Die Liste von Gruppen die sortiert werden soll
*/
//TODO: ProjectionService/SearchSortService
static void sortByGroupType(List<Group> groups) {
groups.sort((Group g1, Group g2) -> {
if (g1.getType() == GroupType.LECTURE) {
return -1;
}
if (g2.getType() == GroupType.LECTURE) {
return 0;
}
return 1;
});
}
/**
* Filtert alle öffentliche Gruppen nach dem Suchbegriff und gibt diese als Liste von Gruppen zurück.
* Groß und Kleinschreibung wird nicht beachtet.
*
* @param search Der Suchstring
*
* @return Liste von projizierten Gruppen
*
* @throws EventException Projektionsfehler
*/
//TODO: ProjectionService/SearchSortService
//Todo Rename
@Cacheable("groups")
public List<Group> findGroupWith(String search, Account account) throws EventException {
if (search.isEmpty()) {
return projectionService.getAllGroupWithVisibilityPublic(account.getName());
}
return projectionService.getAllGroupWithVisibilityPublic(account.getName()).parallelStream().filter(group -> group.getTitle().toLowerCase().contains(search.toLowerCase()) || group.getDescription().toLowerCase().contains(search.toLowerCase())).collect(Collectors.toList());
}
}

View File

@ -16,11 +16,13 @@ import java.util.UUID;
public class UserService {
private final GroupService groupService;
private final EventService eventService;
private final EventStoreService eventStoreService;
private final ProjectionService projectionService;
public UserService(GroupService groupService, EventService eventService) {
public UserService(GroupService groupService, EventStoreService eventStoreService, ProjectionService projectionService) {
this.groupService = groupService;
this.eventService = eventService;
this.eventStoreService = eventStoreService;
this.projectionService = projectionService;
}
@Cacheable("groups")
@ -38,9 +40,9 @@ public class UserService {
//TODO: Nur AddUserEvents + DeleteUserEvents betrachten
@Cacheable("groups")
public List<Group> getUserGroups(User user) {
List<UUID> groupIds = eventService.findGroupIdsByUser(user.getId());
List<UUID> groupIds = eventStoreService.findGroupIdsByUser(user.getId());
List<Event> events = groupService.getGroupEvents(groupIds);
List<Group> groups = groupService.projectEventList(events);
List<Group> groups = projectionService.projectEventList(events);
List<Group> newGroups = new ArrayList<>();
for (Group group : groups) {
@ -48,7 +50,7 @@ public class UserService {
newGroups.add(group);
}
}
groupService.sortByGroupType(newGroups);
SearchService.sortByGroupType(newGroups);
return newGroups;
}
@ -68,7 +70,7 @@ public class UserService {
try {
List<Event> events = groupService.getGroupEvents(groupIds);
return groupService.projectEventList(events).get(0);
return projectionService.projectEventList(events).get(0);
} catch (IndexOutOfBoundsException e) {
throw new GroupNotFoundException("@UserService");
}

View File

@ -24,17 +24,17 @@ import static mops.gruppen2.domain.Role.ADMIN;
public class ValidationService {
private final UserService userService;
private final GroupService groupService;
private final SearchService searchService;
public ValidationService(UserService userService, GroupService groupService) {
public ValidationService(UserService userService, SearchService searchService) {
this.userService = userService;
this.groupService = groupService;
this.searchService = searchService;
}
//TODO: make static or change return + assignment
public List<Group> checkSearch(String search, List<Group> groups, Account account) {
if (search != null) {
groups = groupService.findGroupWith(search, account);
groups = searchService.findGroupWith(search, account);
}
return groups;
}