Skip to content

Commit 7d0ef4a

Browse files
authored
Merge pull request #46 from Halbes-Byte/feature/specifications
Feature/specifications
2 parents c9c322b + 4326b4b commit 7d0ef4a

File tree

15 files changed

+149
-100
lines changed

15 files changed

+149
-100
lines changed

git-user-stats

Lines changed: 0 additions & 48 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.studybuddies.server.domain;
2+
3+
import java.util.HashMap;
4+
import lombok.Getter;
5+
6+
@Getter
7+
public class Filter {
8+
HashMap<String, String> filters;
9+
10+
private Filter() {}
11+
12+
public static Filter of(Filter filter, String key, String value) {
13+
if(filter == null) {
14+
filter = new Filter();
15+
filter.filters = new HashMap<>();
16+
}
17+
filter.filters.putIfAbsent(key, value);
18+
19+
return filter;
20+
}
21+
}

server/src/main/java/com/studybuddies/server/domain/MeetingEntity.java

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import jakarta.persistence.Id;
88
import jakarta.persistence.ManyToOne;
99
import jakarta.persistence.Table;
10+
import jakarta.validation.constraints.NotBlank;
1011
import java.time.LocalDateTime;
1112
import java.util.UUID;
1213
import lombok.AllArgsConstructor;
@@ -24,24 +25,25 @@
2425
@NoArgsConstructor
2526
public class MeetingEntity {
2627

27-
@Id
28-
@GeneratedValue(strategy = GenerationType.UUID)
29-
UUID id;
28+
@Id
29+
@GeneratedValue(strategy = GenerationType.UUID)
30+
UUID id;
3031

31-
UUID superId;
32+
UUID superId;
3233

33-
@Column(nullable = false)
34-
String module;
34+
@Column(nullable = false)
35+
@NotBlank
36+
String module;
3537

36-
String description;
38+
String description;
3739

38-
@Column(nullable = false)
39-
LocalDateTime dateFrom;
40-
@Column(nullable = false)
41-
LocalDateTime dateUntil;
42-
Repeat repeatable;
43-
String place;
40+
@Column(nullable = false)
41+
LocalDateTime dateFrom;
42+
@Column(nullable = false)
43+
LocalDateTime dateUntil;
44+
Repeat repeatable;
45+
String place;
4446

45-
@ManyToOne
46-
private UserEntity creator;
47+
@ManyToOne
48+
private UserEntity creator;
4749
}

server/src/main/java/com/studybuddies/server/persistance/MeetingRepository.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
import java.util.List;
55
import java.util.Optional;
66
import java.util.UUID;
7+
import org.springframework.data.jpa.domain.Specification;
8+
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
79
import org.springframework.data.repository.CrudRepository;
810
import org.springframework.stereotype.Repository;
911

1012
@Repository
11-
public interface MeetingRepository extends CrudRepository<MeetingEntity, UUID> {
13+
public interface MeetingRepository extends CrudRepository<MeetingEntity, UUID>,
14+
JpaSpecificationExecutor<MeetingEntity> {
1215

1316
void deleteById(UUID id);
1417

server/src/main/java/com/studybuddies/server/services/StudyGroupService.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.studybuddies.server.services;
22

3+
import com.studybuddies.server.domain.Filter;
34
import com.studybuddies.server.domain.MeetingEntity;
45
import com.studybuddies.server.domain.StudyGroupEntity;
56
import com.studybuddies.server.domain.UserEntity;
@@ -31,7 +32,7 @@ public class StudyGroupService implements
3132
private final StudyGroupMapper studyGroupMapper;
3233

3334
@Override
34-
public List<StudyGroupResponse> get(String id) {
35+
public List<StudyGroupResponse> get(String id, Filter filter) {
3536
var studyGroupEntities = findStudyGroupsByUUID(id);
3637
List<StudyGroupResponse> responses = new ArrayList<>();
3738
for (StudyGroupEntity studyGroupEntity : studyGroupEntities) {
@@ -44,12 +45,11 @@ public List<StudyGroupResponse> get(String id) {
4445
public void create(StudyGroupJoinRequest request, String clientUuid) {
4546
UserEntity userEntity = userService.findByUUID(UUIDService.parseUUID(clientUuid));
4647

47-
if (!Objects.equals(request.meetingId, "")) {
48+
if (request.meetingId != null && !request.meetingId.isEmpty()) {
4849
MeetingEntity meetingEntity = meetingService.findMeetingByUUID(request.meetingId);
4950
joinMeeting(userEntity, meetingEntity);
50-
}
51-
else if (!Objects.equals(request.superMeetingID, "")) {
52-
List<MeetingEntity> meetingList = meetingService.findMeetingsBySuperID(request.superMeetingID);
51+
} else if (request.superMeetingId != null && !request.superMeetingId.isEmpty()) {
52+
List<MeetingEntity> meetingList = meetingService.findMeetingsBySuperID(request.superMeetingId);
5353

5454
for (MeetingEntity m : meetingList) {
5555
joinMeeting(userEntity, m);

server/src/main/java/com/studybuddies/server/services/interfaces/CRUDService.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.studybuddies.server.services.interfaces;
22

3+
import com.studybuddies.server.domain.Filter;
34
import com.studybuddies.server.web.dto.interfaces.ChangeRequest;
45
import com.studybuddies.server.web.dto.interfaces.CreationRequest;
56
import com.studybuddies.server.web.dto.interfaces.Responses;
@@ -15,7 +16,17 @@ default List<S> get() {
1516
}
1617

1718
@Transactional
18-
default List<S> get(String id) {
19+
default List<S> get(Filter filter) {
20+
throw new UnsupportedOperationException("This operation is not supported");
21+
}
22+
23+
@Transactional
24+
default List<S> get(String id, Filter filter) {
25+
throw new UnsupportedOperationException("This operation is not supported");
26+
}
27+
28+
@Transactional
29+
default List<S> get(String id, String clientUUID, Filter filter) {
1930
throw new UnsupportedOperationException("This operation is not supported");
2031
}
2132

server/src/main/java/com/studybuddies/server/services/meeting/MeetingService.java

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
package com.studybuddies.server.services.meeting;
22

3+
import com.studybuddies.server.domain.Filter;
34
import com.studybuddies.server.domain.MeetingEntity;
45
import com.studybuddies.server.persistance.MeetingRepository;
56
import com.studybuddies.server.services.UUIDService;
6-
import com.studybuddies.server.services.user.UserService;
77
import com.studybuddies.server.services.exceptions.MeetingNotFoundException;
8+
import com.studybuddies.server.services.exceptions.ModuleNotFoundException;
89
import com.studybuddies.server.services.interfaces.CRUDService;
910
import com.studybuddies.server.web.dto.meeting.MeetingChangeRequest;
1011
import com.studybuddies.server.web.dto.meeting.MeetingCreationRequest;
1112
import com.studybuddies.server.web.dto.meeting.MeetingResponse;
1213
import com.studybuddies.server.web.mapper.MeetingMapper;
1314
import java.util.ArrayList;
1415
import java.util.List;
16+
import java.util.UUID;
1517
import lombok.AllArgsConstructor;
1618
import lombok.extern.slf4j.Slf4j;
1719
import org.apache.commons.lang3.NotImplementedException;
@@ -25,19 +27,25 @@ public class MeetingService implements
2527

2628
private final MeetingMapper meetingMapper;
2729
private final MeetingRepository meetingRepository;
28-
private final UserService userService;
2930
private final MeetingCreationService meetingCreationService;
3031
private final MeetingChangeService meetingChangeService;
3132

3233
@Override
33-
public List<MeetingResponse> get(String meetingId) {
34+
public List<MeetingResponse> get(String clientUUID, Filter filter) {
3435
List<MeetingResponse> responses = new ArrayList<>();
36+
List<MeetingEntity> meetings;
37+
UUID client = UUIDService.parseUUID(clientUUID);
3538

36-
if (meetingId == null) {
37-
return findAllMeetingEntities();
39+
if(filter == null) {
40+
meetings = meetingRepository.findAll(MeetingSpecificationService.getSpecParticipant(client));
41+
} else {
42+
var module = filter.getFilters().get("module");
43+
44+
if(module != null)
45+
meetings = meetingRepository.findAll(MeetingSpecificationService.getSpecRelevantMeetings(UUIDService.parseUUID(clientUUID), module.toUpperCase()));
46+
else
47+
throw new ModuleNotFoundException("Module not found");
3848
}
39-
List<MeetingEntity> meetings = meetingRepository.findBySuperId(
40-
UUIDService.parseUUID(meetingId));
4149

4250
for (var meetingEntity : meetings) {
4351
responses.add(meetingMapper.of(meetingEntity));
@@ -74,16 +82,6 @@ public void delete(String targetUUID, String clientUUID) {
7482
}
7583
}
7684

77-
private List<MeetingResponse> findAllMeetingEntities() {
78-
ArrayList<MeetingResponse> meetings = new ArrayList<>();
79-
Iterable<MeetingEntity> meetingIterator = meetingRepository.findAll();
80-
81-
for (MeetingEntity e : meetingIterator) {
82-
meetings.add(meetingMapper.of(e));
83-
}
84-
return meetings;
85-
}
86-
8785
public MeetingEntity findMeetingByUUID(String uuid) {
8886
return meetingRepository.findById(UUIDService.parseUUID(uuid)).orElse(null);
8987
}

server/src/main/java/com/studybuddies/server/services/meeting/MeetingSpecificationService.java

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package com.studybuddies.server.services.meeting;
22

33
import com.studybuddies.server.domain.MeetingEntity;
4-
import com.studybuddies.server.persistance.MeetingRepository;
4+
import com.studybuddies.server.domain.StudyGroupEntity;
5+
import jakarta.persistence.criteria.Root;
6+
import jakarta.persistence.criteria.Subquery;
57
import java.time.LocalDate;
8+
import java.time.LocalDateTime;
9+
import java.util.UUID;
610
import lombok.RequiredArgsConstructor;
711
import org.springframework.data.jpa.domain.Specification;
812
import org.springframework.stereotype.Service;
@@ -11,7 +15,6 @@
1115
@RequiredArgsConstructor
1216
public class MeetingSpecificationService {
1317

14-
final MeetingRepository meetingRepository;
1518

1619
public static Specification<MeetingEntity> isThisWeek() {
1720
return (root, query, builder) -> {
@@ -24,4 +27,57 @@ public static Specification<MeetingEntity> isThisWeek() {
2427
);
2528
};
2629
}
30+
31+
private static Specification<MeetingEntity> isParticipant(UUID userId) {
32+
return (root, query, cb) -> {
33+
Subquery<UUID> subquery = query.subquery(UUID.class);
34+
Root<StudyGroupEntity> studyGroupRoot = subquery.from(StudyGroupEntity.class);
35+
subquery.select(studyGroupRoot.get("meeting").get("id"))
36+
.where(cb.equal(studyGroupRoot.get("user").get("id"), userId));
37+
38+
return cb.or(cb.in(root.get("id")).value(subquery), cb.equal(root.get("creator").get("id"), userId));
39+
};
40+
}
41+
42+
private static Specification<MeetingEntity> isNotParticipant(UUID userId) {
43+
return (root, query, cb) -> {
44+
Subquery<UUID> subquery = query.subquery(UUID.class);
45+
Root<StudyGroupEntity> sg = subquery.from(StudyGroupEntity.class);
46+
47+
subquery.select(sg.get("meeting").get("id"))
48+
.where(cb.equal(sg.get("user").get("id"), userId));
49+
50+
return cb.and(
51+
cb.not(root.get("id").in(subquery)),
52+
cb.notEqual(root.get("creator").get("id"), userId)
53+
);
54+
};
55+
}
56+
57+
private static Specification<MeetingEntity> isRelevant(String userModules) {
58+
return (r, q, b) -> b.equal(r.get("module"), userModules);
59+
}
60+
61+
public static Specification<MeetingEntity> startsAfter(LocalDateTime start) {
62+
return (r, q, b) ->
63+
b.greaterThanOrEqualTo(r.get("dateFrom"), start);
64+
}
65+
66+
public static Specification<MeetingEntity> endsBefore(LocalDateTime end) {
67+
return (r, q, b) ->
68+
b.lessThanOrEqualTo(r.get("dateUntil"), end);
69+
}
70+
71+
public static Specification<MeetingEntity> getSpecRelevantMeetings(
72+
UUID clientId,
73+
String modules
74+
) {
75+
return Specification
76+
.where(isNotParticipant(clientId))
77+
.and(isRelevant(modules));
78+
}
79+
80+
public static Specification<MeetingEntity> getSpecParticipant(UUID userId) {
81+
return isParticipant(userId);
82+
}
2783
}

server/src/main/java/com/studybuddies/server/services/module/ModuleCrudService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.studybuddies.server.services.module;
22

3+
import com.studybuddies.server.domain.Filter;
34
import com.studybuddies.server.domain.ModuleEntity;
45
import com.studybuddies.server.persistance.ModuleRepository;
56
import com.studybuddies.server.services.exceptions.ModuleMayAlreadyExistException;
@@ -30,7 +31,7 @@ public List<ModuleResponse> get() {
3031
}
3132

3233
@Override
33-
public List<ModuleResponse> get(String name) {
34+
public List<ModuleResponse> get(String name, Filter filter) {
3435
String creationModule = moduleUtilService.normalizeModuleName(name);
3536
Iterable<ModuleEntity> iterable = moduleRepository.findAll();
3637

server/src/main/java/com/studybuddies/server/services/user/UserService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.studybuddies.server.services.user;
22

3+
import com.studybuddies.server.domain.Filter;
34
import com.studybuddies.server.domain.UserEntity;
45
import com.studybuddies.server.persistance.UserRepository;
56
import com.studybuddies.server.services.UUIDService;
@@ -33,7 +34,7 @@ public class UserService implements
3334
private final ModuleValidationService moduleValidationService;
3435

3536
@Override
36-
public List<UserResponse> get(String userUUID) {
37+
public List<UserResponse> get(String userUUID, Filter filter) {
3738
Optional<UserEntity> target = userRepository.findById(UUIDService.parseUUID(userUUID));
3839

3940
if (target.isEmpty()) {

0 commit comments

Comments
 (0)