java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeagueEventHierarchyOwnershipChangeTest.java
... ...
@@ -2,6 +2,7 @@ package com.sap.sailing.server.test;
2 2
3 3
import static org.junit.jupiter.api.Assertions.assertNull;
4 4
import static org.junit.jupiter.api.Assertions.assertSame;
5
+import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
5 6
6 7
import java.util.Collections;
7 8
import java.util.Locale;
... ...
@@ -142,6 +143,37 @@ public class LeagueEventHierarchyOwnershipChangeTest {
142 143
final OwnershipAnnotation eventOwnership = securityService.getOwnership(event.getIdentifier());
143 144
assertSame(eventOwnership.getAnnotation().getTenantOwner(), lg2Ownership.getAnnotation().getTenantOwner());
144 145
}
146
+
147
+ @Test
148
+ public void testCyclicLeagueHierarchyOwnershipChangeStartingAtEventTerminates() {
149
+ final Event otherEvent = service.addEvent("Test2", "Test Event 2", TimePoint.now(), TimePoint.now().plus(Duration.ONE_WEEK), "There",
150
+ /* isPublic */ true, UUID.randomUUID());
151
+ otherEvent.getVenue().addCourseArea(defaultCourseArea);
152
+ try {
153
+ final LeaderboardGroup sharedLeaderboardGroup = new LeaderboardGroupImpl("LG-shared", "LGDesc-shared",
154
+ "The shared LG", /* displayGroupsInReverseOrder */ false, Collections.emptyList());
155
+ final Leaderboard sharedOverallLeaderboard = new LeaderboardGroupMetaLeaderboard(sharedLeaderboardGroup, new LowPoint(),
156
+ new ThresholdBasedResultDiscardingRuleImpl(new int[0]));
157
+ sharedLeaderboardGroup.setOverallLeaderboard(sharedOverallLeaderboard);
158
+ sharedLeaderboardGroup.addLeaderboard(new FlexibleLeaderboardImpl("SharedFlexibleLeaderboard",
159
+ new ThresholdBasedResultDiscardingRuleImpl(new int[0]), new LowPoint(), defaultCourseArea));
160
+ event.addLeaderboardGroup(sharedLeaderboardGroup);
161
+ otherEvent.addLeaderboardGroup(sharedLeaderboardGroup);
162
+
163
+ assertTimeoutPreemptively(java.time.Duration.ofSeconds(5), () -> SailingHierarchyOwnershipUpdater
164
+ .createOwnershipUpdater(/* createNewGroup */ true, /* existingGroupIdOrNull */ null,
165
+ THE_NEW_OWNING_GROUP_NAME, /* migrateCompetitors */ true, /* migrateBoats */ true,
166
+ /* copyMembersAndRoles */ true, service)
167
+ .updateGroupOwnershipForEventHierarchy(event));
168
+
169
+ final OwnershipAnnotation eventOwnership = securityService.getOwnership(event.getIdentifier());
170
+ final OwnershipAnnotation otherEventOwnership = securityService.getOwnership(otherEvent.getIdentifier());
171
+ assertSame(eventOwnership.getAnnotation().getTenantOwner(),
172
+ otherEventOwnership.getAnnotation().getTenantOwner());
173
+ } finally {
174
+ service.removeEvent(otherEvent.getId());
175
+ }
176
+ }
145 177
146 178
@AfterEach
147 179
public void tearDown() {
java/com.sap.sailing.server/src/com/sap/sailing/server/hierarchy/SailingHierarchyOwnershipUpdater.java
... ...
@@ -65,6 +65,9 @@ public class SailingHierarchyOwnershipUpdater {
65 65
private final boolean updateCompetitors;
66 66
private final boolean updateBoats;
67 67
private final Set<QualifiedObjectIdentifier> objectsToUpdateOwnershipsFor;
68
+ private final Set<QualifiedObjectIdentifier> visitedEvents;
69
+ private final Set<QualifiedObjectIdentifier> visitedLeaderboardGroups;
70
+ private final Set<QualifiedObjectIdentifier> visitedLeaderboards;
68 71
69 72
private SailingHierarchyOwnershipUpdater(final RacingEventService service, SecurityService securityService,
70 73
final GroupOwnerUpdateStrategy updateStrategy, final boolean updateCompetitors, final boolean updateBoats) {
... ...
@@ -74,6 +77,9 @@ public class SailingHierarchyOwnershipUpdater {
74 77
this.updateCompetitors = updateCompetitors;
75 78
this.updateBoats = updateBoats;
76 79
objectsToUpdateOwnershipsFor = new HashSet<>();
80
+ visitedEvents = new HashSet<>();
81
+ visitedLeaderboardGroups = new HashSet<>();
82
+ visitedLeaderboards = new HashSet<>();
77 83
}
78 84
79 85
public void updateGroupOwnershipForEventHierarchy(Event event) {
... ...
@@ -82,6 +88,9 @@ public class SailingHierarchyOwnershipUpdater {
82 88
}
83 89
84 90
private void updateGroupOwnershipForEventHierarchyInternal(Event event) {
91
+ if (!visitedEvents.add(event.getIdentifier())) {
92
+ return;
93
+ }
85 94
updateGroupOwner(event.getIdentifier());
86 95
SailingHierarchyWalker.walkFromEvent(event, /* includeLeaderboardGroupsWithOverallLeaderboard */ false,
87 96
new EventHierarchyVisitor() {
... ...
@@ -106,6 +115,9 @@ public class SailingHierarchyOwnershipUpdater {
106 115
}
107 116
108 117
private void updateGroupOwnershipForLeaderboardGroupHierarchyInternal(LeaderboardGroup leaderboardGroup, Event eventToExclude) {
118
+ if (!visitedLeaderboardGroups.add(leaderboardGroup.getIdentifier())) {
119
+ return;
120
+ }
109 121
updateGroupOwner(leaderboardGroup.getIdentifier());
110 122
SailingHierarchyWalker.walkFromLeaderboardGroup(service, leaderboardGroup,
111 123
/* includeEventsIfLeaderboardGroupHasOverallLeaderboard */ true,
... ...
@@ -132,6 +144,9 @@ public class SailingHierarchyOwnershipUpdater {
132 144
}
133 145
134 146
private void updateGroupOwnershipForLeaderboardHierarchyInternal(Leaderboard leaderboard) {
147
+ if (!visitedLeaderboards.add(leaderboard.getIdentifier())) {
148
+ return;
149
+ }
135 150
updateGroupOwner(leaderboard.getIdentifier());
136 151
if (leaderboard instanceof RegattaLeaderboard) {
137 152
RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard;