mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-09 20:41:10 +00:00
Merge branch 'master' into bug4509
Change-Id: I23ff6e0b645ab626284fc95b172243878e022806
This commit is contained in:
commit
231e83bc2c
18 files changed
+108
-407
No files matched your search
+1
-5
@@ -24,8 +24,6 @@ import com.sap.sailing.dashboards.gwt.client.widgets.startanalysis.rankingtable.
|
||||
import com.sap.sailing.dashboards.gwt.shared.StartlineAdvantageType;
|
||||
import com.sap.sailing.dashboards.gwt.shared.dto.StartAnalysisDTO;
|
||||
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
|
||||
import com.sap.sailing.gwt.ui.client.CompetitorColorProvider;
|
||||
import com.sap.sailing.gwt.ui.client.CompetitorColorProviderImpl;
|
||||
import com.sap.sailing.gwt.ui.client.RaceCompetitorSelectionModel;
|
||||
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
@@ -75,7 +73,6 @@ public class StartAnalysisCard extends Composite implements HasWidgets, StartAna
|
||||
private SailingServiceAsync sailingServiceAsync;
|
||||
private StringMessages stringMessages;
|
||||
private final RaceCompetitorSelectionModel competitorSelectionModel;
|
||||
private final CompetitorColorProvider colorProvider;
|
||||
|
||||
private final double WIND_LINE_ADVANTAGE_DIV_WIDTH_IN_PT = 185;
|
||||
private final double GEOMETRIC_LINE_ADVANTAGE_DIV_WIDTH_IN_PT = 210;
|
||||
@@ -87,8 +84,7 @@ public class StartAnalysisCard extends Composite implements HasWidgets, StartAna
|
||||
stringMessages = StringMessages.INSTANCE;
|
||||
this.sailingServiceAsync = sailingServiceAsync;
|
||||
this.raceMapResources = raceMapResources;
|
||||
colorProvider = new CompetitorColorProviderImpl();
|
||||
competitorSelectionModel = new RaceCompetitorSelectionModel(/* hasMultiSelection */true, colorProvider);
|
||||
competitorSelectionModel = new RaceCompetitorSelectionModel(/* hasMultiSelection */true);
|
||||
competitorSelectionModel.setCompetitors(startAnalysisDTO.getCompetitorDTOsFromStartAnaylsisCompetitorDTOs(),
|
||||
raceMap);
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ public class CompetitorDTOImpl extends CompetitorWithoutBoatDTOImpl implements C
|
||||
@Override
|
||||
public String getShortInfo() {
|
||||
String result = null;
|
||||
if (getShortName() != null) {
|
||||
if (getShortName() != null && !getShortName().trim().isEmpty()) {
|
||||
result = getShortName();
|
||||
} else if (getBoat() != null) {
|
||||
result = getBoat().getSailId() != null ? getBoat().getSailId() : getBoat().getName();
|
||||
|
||||
+46
-33
@@ -11,8 +11,9 @@ import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -62,11 +63,12 @@ import com.sap.sailing.domain.racelogtracking.test.RaceLogTrackingTestHelper;
|
||||
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.RaceHandle;
|
||||
import com.sap.sailing.domain.tracking.RaceListener;
|
||||
import com.sap.sailing.domain.tracking.Track;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.impl.RacingEventServiceImpl;
|
||||
import com.sap.sailing.server.util.WaitForTrackedRaceUtil;
|
||||
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
@@ -130,7 +132,7 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper {
|
||||
Exception {
|
||||
RaceColumn column = leaderboard.getRaceColumnByName(columnName);
|
||||
exception.expect(NotDenotedForRaceLogTrackingException.class);
|
||||
trackRace(column);
|
||||
trackAndGetRace(column);
|
||||
}
|
||||
|
||||
private void testSize(Track<?> track, int expected) {
|
||||
@@ -202,15 +204,12 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper {
|
||||
raceLog.add(new RaceLogRegisterCompetitorEventImpl(t(), author, 0, comp1, boat1));
|
||||
raceLog.add(new RaceLogStartOfTrackingEventImpl(t(0), author, /* passId */ 0));
|
||||
// start tracking
|
||||
trackRace(column);
|
||||
|
||||
|
||||
// now there is a tracked race
|
||||
TrackedRace race = column.getTrackedRace(fleet);
|
||||
TrackedRace race = trackAndGetRace(column);
|
||||
assertNotNull(race);
|
||||
|
||||
RaceLogFixTrackerManager raceLogFixTrackerManager = new RaceLogFixTrackerManager((DynamicTrackedRace) race, sensorFixStore, null);
|
||||
|
||||
raceLogFixTrackerManager.waitForTracker();
|
||||
race.waitForLoadingToFinish();
|
||||
addFixes1(race, comp1, dev1);
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, 0, comp1, dev1, t(11), t(20)));
|
||||
@@ -225,21 +224,10 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper {
|
||||
addFixes3(race, comp1, dev1);
|
||||
}
|
||||
|
||||
private void trackRace(RaceColumn column) throws NotDenotedForRaceLogTrackingException, Exception {
|
||||
private TrackedRace trackAndGetRace(RaceColumn column) throws NotDenotedForRaceLogTrackingException, Exception {
|
||||
final RaceHandle raceHandle = adapter.startTracking(service, leaderboard, column, fleet, /* trackWind */ false, /* correctWindDirectionByMagneticDeclination */ false);
|
||||
|
||||
// The following lines ensure that we received all necessary events from the TrackedRegatta
|
||||
// When removing a listener we get a Future whose get method will block until all previously triggered events are processed.
|
||||
final RaceListener raceListener = new RaceListener() {
|
||||
@Override
|
||||
public void raceRemoved(TrackedRace trackedRace) {
|
||||
}
|
||||
@Override
|
||||
public void raceAdded(TrackedRace trackedRace) {
|
||||
}
|
||||
};
|
||||
raceHandle.getTrackedRegatta().addRaceListener(raceListener, Optional.empty());
|
||||
raceHandle.getTrackedRegatta().removeRaceListener(raceListener).get();
|
||||
raceHandle.getRace();
|
||||
return WaitForTrackedRaceUtil.waitForTrackedRace(column, fleet, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,10 +243,7 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper {
|
||||
raceLog = column.getRaceLog(fleet);
|
||||
adapter.denoteRaceForRaceLogTracking(service, leaderboard, column, fleet, "race");
|
||||
// start tracking
|
||||
adapter.startTracking(service, leaderboard, column, fleet, /* trackWind */ false, /* correctWindDirectionByMagneticDeclination */ false);
|
||||
|
||||
// now there is a trackedrace
|
||||
TrackedRace race = column.getTrackedRace(fleet);
|
||||
TrackedRace race = trackAndGetRace(column);
|
||||
assertNotNull(race);
|
||||
final TimePoint startTimeInRaceLog = new MillisecondsTimePoint(123456);
|
||||
final TimePoint endTimeInRaceLog = new MillisecondsTimePoint(234567);
|
||||
@@ -276,9 +261,8 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper {
|
||||
|
||||
// now remove the tracked race and track again; again, the explicit tracking times in the race log must prevail
|
||||
service.removeRace(regatta, race.getRace());
|
||||
trackRace(column);
|
||||
TrackedRace race2 = column.getTrackedRace(fleet);
|
||||
assertEquals(explicitStartOfTracking, race2.getStartOfTracking());
|
||||
TrackedRace race2 = trackAndGetRace(column);
|
||||
assertEquals(explicitStartOfTracking, waitForStartOfTracking(race2));
|
||||
assertEquals(explicitEndOfTracking, race2.getEndOfTracking());
|
||||
}
|
||||
|
||||
@@ -300,14 +284,12 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper {
|
||||
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(t(), t(), author, UUID.randomUUID(), comp1));
|
||||
raceLog.add(new RaceLogStartOfTrackingEventImpl(t(0), author, /* passId */ 0));
|
||||
|
||||
trackRace(column);
|
||||
|
||||
// now there is a trackedrace
|
||||
TrackedRace race = column.getTrackedRace(fleet);
|
||||
TrackedRace race = trackAndGetRace(column);
|
||||
assertNotNull(race);
|
||||
|
||||
RaceLogFixTrackerManager raceLogFixTrackerManager = new RaceLogFixTrackerManager((DynamicTrackedRace) race, sensorFixStore, null);
|
||||
|
||||
raceLogFixTrackerManager.waitForTracker();
|
||||
race.waitForLoadingToFinish();
|
||||
addFixes1(race, comp1, dev1);
|
||||
|
||||
@@ -322,4 +304,35 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper {
|
||||
raceLogFixTrackerManager.stop(false, /* willBeRemoved */ false);
|
||||
addFixes3(race, comp1, dev1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Waits for startOfTracking being available for a given {@link TrackedRace}.
|
||||
*/
|
||||
public static TimePoint waitForStartOfTracking(TrackedRace trackedRace) {
|
||||
final CompletableFuture<TimePoint> future = new CompletableFuture<>();
|
||||
|
||||
final AbstractRaceChangeListener listener = new AbstractRaceChangeListener() {
|
||||
@Override
|
||||
public void startOfTrackingChanged(TimePoint oldStartOfTracking, TimePoint newStartOfTracking) {
|
||||
if (newStartOfTracking != null) {
|
||||
future.complete(newStartOfTracking);
|
||||
trackedRace.removeListener(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
trackedRace.addListener(listener);
|
||||
final TimePoint startOfTracking = trackedRace.getStartOfTracking();
|
||||
if (startOfTracking != null) {
|
||||
trackedRace.removeListener(listener);
|
||||
return startOfTracking;
|
||||
}
|
||||
|
||||
try {
|
||||
return future.get(10, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
trackedRace.removeListener(listener);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -90,6 +90,7 @@ public class RaceLogFixTrackerManager implements TrackingDataLoader {
|
||||
} else {
|
||||
stopTrackerIfStillRunning(/* preemptive */ false, /* willBeRemoved */ false);
|
||||
}
|
||||
this.notifyAll();
|
||||
}
|
||||
|
||||
private void addRaceLog(RaceLog raceLog) {
|
||||
@@ -153,4 +154,11 @@ public class RaceLogFixTrackerManager implements TrackingDataLoader {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized FixLoaderAndTracker waitForTracker() throws InterruptedException {
|
||||
while (tracker == null) {
|
||||
this.wait();
|
||||
}
|
||||
return tracker;
|
||||
}
|
||||
}
|
||||
-1
@@ -725,7 +725,6 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab
|
||||
boatDTO = convertToBoatDTO(boat);
|
||||
}
|
||||
CompetitorDTO competitorDTO = new CompetitorDTOImpl(c, boatDTO);
|
||||
|
||||
return competitorDTO;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -61,7 +61,7 @@ public class RaceEndWithBoatsPresenterImpl extends AutoPlayPresenterConfigured<A
|
||||
final SingleRaceLeaderboardSettings leaderboardSettings = new SingleRaceLeaderboardSettings(
|
||||
/* maneuverDetailsToShow */ null, /* legDetailsToShow */ null, /* raceDetailsToShow */ null,
|
||||
/* overallDetailsToShow */ null, /* delayBetweenAutoAdvancesInMilliseconds */ null,
|
||||
/* showAddedScores */ false, /* showCompetitorShortNameColumn */ false,
|
||||
/* showAddedScores */ false, /* showCompetitorShortNameColumn */ true,
|
||||
/* showCompetitorFullNameColumn */ false, /* isCompetitorNationalityColumnVisible */ false,
|
||||
/* showCompetitorBoatInfoColumn */ false, /* showRaceRankColumn */ true);
|
||||
|
||||
@@ -70,7 +70,7 @@ public class RaceEndWithBoatsPresenterImpl extends AutoPlayPresenterConfigured<A
|
||||
timer = new com.sap.sse.gwt.client.player.Timer(PlayModes.Live,
|
||||
PlayStates.Paused,
|
||||
/* delayBetweenAutoAdvancesInMilliseconds */ LeaderboardEntryPoint.DEFAULT_REFRESH_INTERVAL_MILLIS);
|
||||
leaderboardPanel = new SingleRaceLeaderboardPanel(null,null,sailingService, new AsyncActionsExecutor(), leaderboardSettings,
|
||||
leaderboardPanel = new SingleRaceLeaderboardPanel(null, null, sailingService, new AsyncActionsExecutor(), leaderboardSettings,
|
||||
true, liveRace, competitorSelectionProvider, timer, null,
|
||||
getSlideCtx().getContextDefinition().getLeaderboardName(), errorReporter, StringMessages.INSTANCE,
|
||||
false, null, false, null, false, true, false, false, false, new SixtyInchLeaderBoardStyle(true),
|
||||
|
||||
+9
-10
@@ -140,11 +140,11 @@ public class LiveRaceWithRacemapAndLeaderBoardPresenterImpl
|
||||
}
|
||||
SailingServiceAsync sailingService = getClientFactory().getSailingService();
|
||||
ErrorReporter errorReporter = getClientFactory().getErrorReporter();
|
||||
RegattaAndRaceIdentifier lifeRace = getSlideCtx().getLiveRace();
|
||||
RegattaAndRaceIdentifier liveRace = getSlideCtx().getLiveRace();
|
||||
ArrayList<String> racesToShow = null;
|
||||
if (lifeRace != null) {
|
||||
if (liveRace != null) {
|
||||
racesToShow = new ArrayList<>();
|
||||
racesToShow.add(lifeRace.getRaceName());
|
||||
racesToShow.add(liveRace.getRaceName());
|
||||
} else {
|
||||
view.showErrorNoLive(this, panel, new IllegalStateException("No race is live"));
|
||||
return;
|
||||
@@ -152,21 +152,20 @@ public class LiveRaceWithRacemapAndLeaderBoardPresenterImpl
|
||||
final SingleRaceLeaderboardSettings leaderboardSettings = new SingleRaceLeaderboardSettings(
|
||||
/* maneuverDetailsToShow */ null, /* legDetailsToShow */ null, /* raceDetailsToShow */ null,
|
||||
/* overallDetailsToShow */ null, /* delayBetweenAutoAdvancesInMilliseconds */ null,
|
||||
/* showAddedScores */ false, /* showCompetitorShortNameColumn */ false,
|
||||
/* showAddedScores */ false, /* showCompetitorShortNameColumn */ true,
|
||||
/* showCompetitorFullNameColumn */ false, /* isCompetitorNationalityColumnVisible */ false,
|
||||
/* showCompetitorBoatInfoColumn */ false, /* showRaceRankColumn */ true);
|
||||
timer = new com.sap.sse.gwt.client.player.Timer(
|
||||
// perform the first request as "live" but don't by default auto-play
|
||||
PlayModes.Live, PlayStates.Playing,
|
||||
/* delayBetweenAutoAdvancesInMilliseconds */ LeaderboardEntryPoint.DEFAULT_REFRESH_INTERVAL_MILLIS);
|
||||
leaderboardPanel = new SingleRaceLeaderboardPanel(null,null,sailingService, new AsyncActionsExecutor(), leaderboardSettings,
|
||||
true, lifeRace, getPlace().getRaceMapSelectionProvider(), timer, null,
|
||||
getSlideCtx().getContextDefinition().getLeaderboardName(), errorReporter, StringMessages.INSTANCE,
|
||||
leaderboardPanel = new SingleRaceLeaderboardPanel(null, null, sailingService, new AsyncActionsExecutor(),
|
||||
leaderboardSettings, true, liveRace, getPlace().getRaceMapSelectionProvider(), timer, null,
|
||||
getSlideCtx().getContextDefinition().getLeaderboardName(), errorReporter, StringMessages.INSTANCE,
|
||||
false, null, false, null, false, true, false, false, false, new SixtyInchLeaderBoardStyle(true),
|
||||
FlagImageResolverImpl.get());
|
||||
|
||||
getPlace().getRaceMap().setQuickRanksDTOProvider(new QuickRanksDTOFromLeaderboardDTOProvider(new RaceCompetitorSet(getPlace().getRaceMapSelectionProvider()), lifeRace));
|
||||
|
||||
getPlace().getRaceMap().setQuickRanksDTOProvider(new QuickRanksDTOFromLeaderboardDTOProvider(
|
||||
new RaceCompetitorSet(getPlace().getRaceMapSelectionProvider()), liveRace));
|
||||
view.startingWith(this, panel, getPlace().getRaceMap(), leaderboardPanel);
|
||||
selectionTimer.schedule(SWITCH_COMPETITOR_DELAY);
|
||||
}
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ import com.sap.sailing.gwt.autoplay.client.app.AnimationPanel;
|
||||
import com.sap.sailing.gwt.autoplay.client.app.AutoPlayClientFactory;
|
||||
import com.sap.sailing.gwt.autoplay.client.app.AutoPlayPresenterConfigured;
|
||||
import com.sap.sailing.gwt.settings.client.leaderboard.SingleRaceLeaderboardSettings;
|
||||
import com.sap.sailing.gwt.ui.client.RaceCompetitorSelectionModel;
|
||||
import com.sap.sailing.gwt.ui.client.FlagImageResolverImpl;
|
||||
import com.sap.sailing.gwt.ui.client.RaceCompetitorSelectionModel;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardEntryPoint;
|
||||
@@ -97,7 +97,7 @@ public class PreLiveRaceLeaderBoardWithImagePresenterImpl
|
||||
final SingleRaceLeaderboardSettings leaderboardSettings = new SingleRaceLeaderboardSettings(
|
||||
/* maneuverDetailsToShow */ null, /* legDetailsToShow */ null, /* raceDetailsToShow */ null,
|
||||
/* overallDetailsToShow */ null, /* delayBetweenAutoAdvancesInMilliseconds */ null,
|
||||
/* showAddedScores */ false, /* showCompetitorShortNameColumn */ false,
|
||||
/* showAddedScores */ false, /* showCompetitorShortNameColumn */ true,
|
||||
/* showCompetitorFullNameColumn */ false, /* isCompetitorNationalityColumnVisible */ false,
|
||||
/* showCompetitorBoatInfoColumn */ false, /* showRaceRankColumn */ false);
|
||||
|
||||
|
||||
Regular → Executable
+6
-7
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.autoplay.client.utils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
@@ -197,16 +198,14 @@ public class AutoplayHelper {
|
||||
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfo,
|
||||
long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest,
|
||||
long clientTimeWhenResponseWasReceived) {
|
||||
|
||||
// keep the creationTime updated upon liveChanges!
|
||||
creationTimer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest,
|
||||
clientTimeWhenResponseWasReceived);
|
||||
creationTimer
|
||||
.setLivePlayDelayInMillis(raceTimesInfo.get(regattaAndRaceIdentifier).delayToLiveInMs);
|
||||
creationTimer.play();
|
||||
|
||||
if (regattaAndRaceIdentifier != null) {
|
||||
if(!mapAlreadyCreated){
|
||||
if (!mapAlreadyCreated) {
|
||||
mapAlreadyCreated = true;
|
||||
sailingService.getCompetitorBoats(regattaAndRaceIdentifier,
|
||||
new AsyncCallback<Map<CompetitorDTO, BoatDTO>>() {
|
||||
@@ -280,16 +279,16 @@ public class AutoplayHelper {
|
||||
typesToConsiderOnZoom.add(ZoomTypes.BUOYS);
|
||||
typesToConsiderOnZoom.add(ZoomTypes.BOATS);
|
||||
RaceMapZoomSettings autoFollowRace = new RaceMapZoomSettings(typesToConsiderOnZoom, true);
|
||||
|
||||
RaceMapSettings settings = new RaceMapSettings(autoFollowRace, new RaceMapHelpLinesSettings(), false, 15,
|
||||
100000l, false, RaceMapSettings.DEFAULT_BUOY_ZONE_RADIUS, false, true, false, false, false, false,
|
||||
RaceMapSettings.getDefaultManeuvers(), false, false);
|
||||
|
||||
RaceMapLifecycle raceMapLifecycle = new RaceMapLifecycle(StringMessages.INSTANCE);
|
||||
|
||||
final CompetitorColorProvider colorProvider = new CompetitorColorProviderImpl(currentLiveRace, result);
|
||||
RaceCompetitorSelectionModel competitorSelectionProvider = new RaceCompetitorSelectionModel(
|
||||
/* hasMultiSelection */ true, colorProvider);
|
||||
/* hasMultiSelection */ true, colorProvider, result);
|
||||
for (Entry<CompetitorDTO, BoatDTO> entry : result.entrySet()) {
|
||||
competitorSelectionProvider.setBoat(entry.getKey(), entry.getValue());
|
||||
}
|
||||
competitorSelectionProvider.setCompetitors(competitors);
|
||||
RaceMap raceboardPerspective = new RaceMap(null, null, raceMapLifecycle, settings, sailingService,
|
||||
asyncActionsExecutor, errorReporter, raceboardTimer, competitorSelectionProvider,
|
||||
|
||||
+3
-1
@@ -185,7 +185,9 @@ public class CompetitorEditDialog extends DataEntryDialog<CompetitorDTO> {
|
||||
color = new InvalidColor(iae);
|
||||
}
|
||||
}
|
||||
CompetitorDTO result = new CompetitorDTOImpl(name.getText(), shortName.getText(), color, email.getText(),
|
||||
CompetitorDTO result = new CompetitorDTOImpl(name.getText(),
|
||||
shortName.getText().trim().isEmpty() ? null : shortName.getText(), color,
|
||||
email.getText().trim().isEmpty() ? null : email.getText(),
|
||||
/* twoLetterIsoCountryCode */ null,
|
||||
threeLetterIocCountryCode.getValue(threeLetterIocCountryCode.getSelectedIndex()),
|
||||
/* countryName */ null, competitorToEdit.getIdAsString(),
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ public class CompetitorSelectionModel implements CompetitorSelectionProvider {
|
||||
this.hasMultiSelection = hasMultiSelection;
|
||||
this.competitorColorProvider = competitorColorProvider;
|
||||
this.competitorsFilterSet = competitorsFilterSet;
|
||||
this.allCompetitors = new LinkedHashSet<CompetitorDTO>();
|
||||
this.allCompetitors = new LinkedHashSet<>();
|
||||
this.selectedCompetitors = new LinkedHashMap<>();
|
||||
this.listeners = new HashSet<CompetitorSelectionChangeListener>();
|
||||
}
|
||||
|
||||
-313
@@ -1,313 +0,0 @@
|
||||
package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.filter.Filter;
|
||||
import com.sap.sse.common.filter.FilterSet;
|
||||
|
||||
public class CompetitorWithBoatSelectionModel implements CompetitorSelectionProvider {
|
||||
private final Set<CompetitorDTO> allCompetitors;
|
||||
|
||||
/**
|
||||
* Keys are {@link CompetitorDTO#getIdAsString()} of their values
|
||||
*/
|
||||
private final LinkedHashMap<String, CompetitorDTO> selectedCompetitors;
|
||||
|
||||
private final Set<CompetitorSelectionChangeListener> listeners;
|
||||
|
||||
private final boolean hasMultiSelection;
|
||||
|
||||
private FilterSet<CompetitorDTO, Filter<CompetitorDTO>> competitorsFilterSet;
|
||||
|
||||
private final CompetitorColorProvider competitorColorProvider;
|
||||
|
||||
public CompetitorWithBoatSelectionModel(boolean hasMultiSelection) {
|
||||
this(hasMultiSelection, new CompetitorColorProviderImpl(), null);
|
||||
}
|
||||
|
||||
public CompetitorWithBoatSelectionModel(boolean hasMultiSelection, CompetitorColorProvider competitorColorProvider) {
|
||||
this(hasMultiSelection, competitorColorProvider, null);
|
||||
}
|
||||
|
||||
private CompetitorWithBoatSelectionModel(boolean hasMultiSelection, CompetitorColorProvider competitorColorProvider, FilterSet<CompetitorDTO, Filter<CompetitorDTO>> competitorsFilterSet) {
|
||||
super();
|
||||
this.hasMultiSelection = hasMultiSelection;
|
||||
this.competitorColorProvider = competitorColorProvider;
|
||||
this.competitorsFilterSet = competitorsFilterSet;
|
||||
this.allCompetitors = new LinkedHashSet<CompetitorDTO>();
|
||||
this.selectedCompetitors = new LinkedHashMap<>();
|
||||
this.listeners = new HashSet<CompetitorSelectionChangeListener>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a competitor to the {@link #getAllCompetitors() set of all competitors}. If the competitor was not yet
|
||||
* contained, it will be deselected.
|
||||
*/
|
||||
public void add(CompetitorDTO competitor) {
|
||||
add(competitor, true);
|
||||
}
|
||||
|
||||
private void add(CompetitorDTO competitor, boolean notifyListeners) {
|
||||
if (competitor.getColor() != null) {
|
||||
competitorColorProvider.addBlockedColor(competitor.getColor());
|
||||
}
|
||||
boolean changed = allCompetitors.add(competitor);
|
||||
if (notifyListeners && changed) {
|
||||
fireListChanged(getAllCompetitors());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMultiSelection() {
|
||||
return hasMultiSelection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all competitors. Afterwards, this model is empty. Deselection events are issued for all competitors that
|
||||
* were selected so far.
|
||||
*/
|
||||
public void clear() {
|
||||
Iterator<CompetitorDTO> selIter = getSelectedCompetitors().iterator();
|
||||
while (selIter.hasNext()) {
|
||||
CompetitorDTO selected = selIter.next();
|
||||
setSelected(selected, false);
|
||||
selIter = getSelectedCompetitors().iterator();
|
||||
}
|
||||
assert selectedCompetitors.isEmpty();
|
||||
allCompetitors.clear();
|
||||
fireListChanged(getAllCompetitors());
|
||||
}
|
||||
|
||||
public void addAll(Iterable<CompetitorDTO> competitors) {
|
||||
boolean changed = false;
|
||||
for (CompetitorDTO competitor : competitors) {
|
||||
add(competitor, false);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
fireListChanged(getAllCompetitors());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the competitor from the {@link #getAllCompetitors() set of all competitor}. If the competitor was previously
|
||||
* contained and selected, it is deselected first.
|
||||
*/
|
||||
public void remove(CompetitorDTO competitor) {
|
||||
if (isSelected(competitor)) {
|
||||
setSelected(competitor, false);
|
||||
}
|
||||
if (competitor.getColor() != null) {
|
||||
competitorColorProvider.removeBlockedColor(competitor.getColor());
|
||||
}
|
||||
boolean changed = allCompetitors.remove(competitor);
|
||||
if (changed) {
|
||||
fireListChanged(getAllCompetitors());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<CompetitorDTO> getSelectedCompetitors() {
|
||||
return Collections.unmodifiableCollection(selectedCompetitors.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<CompetitorDTO> getSelectedFilteredCompetitors() {
|
||||
Set<CompetitorDTO> result = new HashSet<>(selectedCompetitors.values());
|
||||
result.retainAll(getFilteredCompetitors());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<CompetitorDTO> getAllCompetitors() {
|
||||
return Collections.unmodifiableCollection(allCompetitors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<CompetitorDTO> getFilteredCompetitors() {
|
||||
Set<CompetitorDTO> currentFilteredList = new LinkedHashSet<CompetitorDTO>(allCompetitors);
|
||||
if (competitorsFilterSet != null) {
|
||||
for (Filter<CompetitorDTO> filter : competitorsFilterSet.getFilters()) {
|
||||
for (Iterator<CompetitorDTO> i=currentFilteredList.iterator(); i.hasNext(); ) {
|
||||
CompetitorDTO competitorDTO = i.next();
|
||||
if (!filter.matches(competitorDTO)) {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return currentFilteredList;
|
||||
}
|
||||
|
||||
public void setSelected(CompetitorDTO competitor, boolean selected, CompetitorSelectionChangeListener... listenersNotToNotify) {
|
||||
if (selected) {
|
||||
if (allCompetitors.contains(competitor) && !selectedCompetitors.containsKey(competitor.getIdAsString())) {
|
||||
selectedCompetitors.put(competitor.getIdAsString(), competitor);
|
||||
fireAddedToSelection(competitor, listenersNotToNotify);
|
||||
}
|
||||
} else {
|
||||
if (selectedCompetitors.containsKey(competitor.getIdAsString())) {
|
||||
selectedCompetitors.remove(competitor.getIdAsString());
|
||||
fireRemovedFromSelection(competitor, listenersNotToNotify);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fireAddedToSelection(CompetitorDTO competitor, CompetitorSelectionChangeListener... listenersNotToNotify) {
|
||||
for (CompetitorSelectionChangeListener listener : listeners) {
|
||||
if (listenersNotToNotify == null || !Arrays.asList(listenersNotToNotify).contains(listener)) {
|
||||
listener.addedToSelection(competitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fireRemovedFromSelection(CompetitorDTO competitor, CompetitorSelectionChangeListener... listenersNotToNotify) {
|
||||
for (CompetitorSelectionChangeListener listener : listeners) {
|
||||
if (listenersNotToNotify == null || !Arrays.asList(listenersNotToNotify).contains(listener)) {
|
||||
listener.removedFromSelection(competitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fireListChanged(Iterable<CompetitorDTO> competitors, CompetitorSelectionChangeListener... listenersNotToNotify) {
|
||||
for (CompetitorSelectionChangeListener listener : listeners) {
|
||||
if (listenersNotToNotify == null || !Arrays.asList(listenersNotToNotify).contains(listener)) {
|
||||
listener.competitorsListChanged(competitors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(CompetitorDTO competitor) {
|
||||
return selectedCompetitors.containsKey(competitor.getIdAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCompetitorSelectionChangeListener(CompetitorSelectionChangeListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCompetitorSelectionChangeListener(CompetitorSelectionChangeListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelection(Iterable<CompetitorDTO> newSelection, CompetitorSelectionChangeListener... listenersNotToNotify) {
|
||||
Set<CompetitorDTO> competitorsToRemoveFromSelection = new HashSet<CompetitorDTO>(selectedCompetitors.values());
|
||||
for (CompetitorDTO newSelectedCompetitor : newSelection) {
|
||||
setSelected(newSelectedCompetitor, true, listenersNotToNotify);
|
||||
competitorsToRemoveFromSelection.remove(newSelectedCompetitor);
|
||||
}
|
||||
for (CompetitorDTO competitorToRemoveFromSelection : competitorsToRemoveFromSelection) {
|
||||
setSelected(competitorToRemoveFromSelection, false, listenersNotToNotify);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompetitors(Iterable<CompetitorDTO> newCompetitors, CompetitorSelectionChangeListener... listenersNotToNotify) {
|
||||
boolean changed = false;
|
||||
Map<String, CompetitorDTO> oldCompetitorsToRemove = new HashMap<String, CompetitorDTO>();
|
||||
for (final CompetitorDTO c : allCompetitors) {
|
||||
oldCompetitorsToRemove.put(c.getIdAsString(), c);
|
||||
}
|
||||
for (CompetitorDTO newCompetitor : newCompetitors) {
|
||||
// Search by equality, including all CompetitorDTO fields; if equal object is found, leave it in place;
|
||||
// non-equal objects may still represent the same competitor entity; yet, replace the object to obtain the
|
||||
// new, changed state; make sure the selection keeps unchanged regarding the selected competitor "entities";
|
||||
// see also bug 3413 for more background.
|
||||
if (allCompetitors.contains(newCompetitor)) {
|
||||
oldCompetitorsToRemove.remove(newCompetitor.getIdAsString()); // the old competitor object remains in allCompetitors; it is equal but doesn't have to be identical to newCompetitor
|
||||
} else {
|
||||
boolean selected = isSelected(newCompetitor);
|
||||
if (selected) {
|
||||
remove(oldCompetitorsToRemove.get(newCompetitor.getIdAsString()));
|
||||
oldCompetitorsToRemove.remove(newCompetitor.getIdAsString());
|
||||
}
|
||||
add(newCompetitor, false); // due to the equals definition of CompetitorDTOImpl that compares most fields, state changes lead to a replacement here
|
||||
if (selected) {
|
||||
// restore selection for replaced element
|
||||
setSelected(newCompetitor, selected, listenersNotToNotify);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
for (CompetitorDTO oldCompetitorToRemove : oldCompetitorsToRemove.values()) {
|
||||
remove(oldCompetitorToRemove);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
fireListChanged(getAllCompetitors(), listenersNotToNotify);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getColor(CompetitorDTO competitor) {
|
||||
return allCompetitors.contains(competitor) ? competitorColorProvider.getColor(competitor) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterSet<CompetitorDTO, Filter<CompetitorDTO>> getCompetitorsFilterSet() {
|
||||
return competitorsFilterSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterSet<CompetitorDTO, Filter<CompetitorDTO>> getOrCreateCompetitorsFilterSet(String nameToAssignToNewFilterSet) {
|
||||
if (competitorsFilterSet == null) {
|
||||
competitorsFilterSet = new FilterSet<CompetitorDTO, Filter<CompetitorDTO>>(nameToAssignToNewFilterSet);
|
||||
}
|
||||
return getCompetitorsFilterSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompetitorsFilterSet(FilterSet<CompetitorDTO, Filter<CompetitorDTO>> competitorsFilterSet) {
|
||||
FilterSet<CompetitorDTO, ? extends Filter<CompetitorDTO>> oldFilterSet = this.competitorsFilterSet;
|
||||
this.competitorsFilterSet = competitorsFilterSet;
|
||||
if (!Util.equalsWithNull(competitorsFilterSet, oldFilterSet)) {
|
||||
for (CompetitorSelectionChangeListener listener : listeners) {
|
||||
listener.filterChanged(oldFilterSet, competitorsFilterSet);
|
||||
}
|
||||
}
|
||||
for (CompetitorSelectionChangeListener listener : listeners) {
|
||||
listener.filteredCompetitorsListChanged(getFilteredCompetitors());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActiveFilters() {
|
||||
return (competitorsFilterSet != null && !competitorsFilterSet.getFilters().isEmpty()
|
||||
&& getFilteredCompetitors().size() != allCompetitors.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllFilters() {
|
||||
if (hasActiveFilters()) {
|
||||
Iterator<CompetitorDTO> selIter = getSelectedCompetitors().iterator();
|
||||
while (selIter.hasNext()) {
|
||||
CompetitorDTO selected = selIter.next();
|
||||
setSelected(selected, false);
|
||||
selIter = getSelectedCompetitors().iterator();
|
||||
}
|
||||
competitorsFilterSet = null;
|
||||
fireListChanged(getAllCompetitors());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFilteredCompetitorsListSize() {
|
||||
return getFilteredCompetitors().size();
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -9,14 +9,17 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sse.common.Color;
|
||||
|
||||
public class RaceCompetitorSelectionModel extends CompetitorSelectionModel implements RaceCompetitorSelectionProvider {
|
||||
private final Map<CompetitorDTO, BoatDTO> boatsOfCompetitors = new HashMap<>();
|
||||
private final Map<CompetitorDTO, BoatDTO> boatsOfCompetitors;
|
||||
|
||||
public RaceCompetitorSelectionModel(boolean hasMultiSelection) {
|
||||
super(hasMultiSelection);
|
||||
boatsOfCompetitors = new HashMap<>();
|
||||
}
|
||||
|
||||
public RaceCompetitorSelectionModel(boolean hasMultiSelection, CompetitorColorProvider competitorColorProvider) {
|
||||
public RaceCompetitorSelectionModel(boolean hasMultiSelection, CompetitorColorProvider competitorColorProvider, Map<CompetitorDTO, BoatDTO> boatsOfCompetitors) {
|
||||
super(hasMultiSelection, competitorColorProvider);
|
||||
this.boatsOfCompetitors = boatsOfCompetitors;
|
||||
addAll(boatsOfCompetitors.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -1869,7 +1869,7 @@ selectCompetitorsToEliminate=Select competitors to eliminate
|
||||
trackedRaceAlreadyLinked=The race is already linked to a race column. Do you really want to change the link?
|
||||
boatAlreadyLinked=The boat is already linked to a competitor
|
||||
chooseAAutoplayConfiguration=Choose an autoplay configuration
|
||||
raceRankShort=Race rank:
|
||||
raceRankShort=Race rank
|
||||
showRaceRankColumn=Show race rank
|
||||
estimatedDistance=Estimated Distance
|
||||
estimatedTime=Estimated Time
|
||||
|
||||
+4
-4
@@ -202,9 +202,9 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint
|
||||
final CompetitorColorProvider colorProvider = new CompetitorColorProviderImpl(selectedRaceIdentifier, competitorsAndBoats);
|
||||
final RaceCompetitorSelectionProvider competitorSelection;
|
||||
if (showCompetitors) {
|
||||
competitorSelection = new RaceCompetitorSelectionModel(/* hasMultiSelection */ true, colorProvider);
|
||||
competitorSelection = new RaceCompetitorSelectionModel(/* hasMultiSelection */ true, colorProvider, competitorsAndBoats);
|
||||
} else {
|
||||
competitorSelection = createEmptyFilterCompetitorModel(colorProvider); // show no competitors
|
||||
competitorSelection = createEmptyFilterCompetitorModel(colorProvider, competitorsAndBoats); // show no competitors
|
||||
}
|
||||
final RaceMap raceMap = new RaceMap(null, null, new RaceMapLifecycle(getStringMessages()), raceMapSettings,
|
||||
sailingService, asyncActionsExecutor, /* errorReporter */ EmbeddedMapAndWindChartEntryPoint.this, timer,
|
||||
@@ -232,8 +232,8 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint
|
||||
timer.setTime(timer.getTime().getTime()-1000l);
|
||||
}
|
||||
|
||||
private RaceCompetitorSelectionProvider createEmptyFilterCompetitorModel(CompetitorColorProvider colorProvider) {
|
||||
final RaceCompetitorSelectionModel result = new RaceCompetitorSelectionModel(/* hasMultiSelection */ true, colorProvider);
|
||||
private RaceCompetitorSelectionProvider createEmptyFilterCompetitorModel(CompetitorColorProvider colorProvider, Map<CompetitorDTO, BoatDTO> competitorsAndBoats) {
|
||||
final RaceCompetitorSelectionModel result = new RaceCompetitorSelectionModel(/* hasMultiSelection */ true, colorProvider, competitorsAndBoats);
|
||||
final FilterSet<CompetitorDTO, Filter<CompetitorDTO>> filterSet = result.getOrCreateCompetitorsFilterSet("Empty");
|
||||
filterSet.addFilter(new Filter<CompetitorDTO>() {
|
||||
@Override public boolean matches(CompetitorDTO object) { return false; }
|
||||
|
||||
+1
-1
@@ -211,7 +211,7 @@ public class RaceBoardPanel
|
||||
timeRangeWithZoomModel = new TimeRangeWithZoomModel();
|
||||
|
||||
final CompetitorColorProvider colorProvider = new CompetitorColorProviderImpl(selectedRaceIdentifier, competitorsAndTheirBoats);
|
||||
competitorSelectionProvider = new RaceCompetitorSelectionModel(/* hasMultiSelection */ true, colorProvider);
|
||||
competitorSelectionProvider = new RaceCompetitorSelectionModel(/* hasMultiSelection */ true, colorProvider, competitorsAndTheirBoats);
|
||||
|
||||
raceMapResources.raceMapStyle().ensureInjected();
|
||||
RaceMapLifecycle raceMapLifecycle = lifecycle.getRaceMapLifecycle();
|
||||
|
||||
-16
@@ -42,8 +42,6 @@ import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.RaceListener;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
||||
@@ -94,20 +92,6 @@ public class StatisticsTest {
|
||||
private TrackedRaceStatisticsCacheImpl getStatisticsCacheWithRegattaAdded() throws Exception {
|
||||
TrackedRaceStatisticsCacheImpl trackedRaceStatisticsCache = new TrackedRaceStatisticsCacheImpl();
|
||||
trackedRaceStatisticsCache.regattaAdded(regatta);
|
||||
|
||||
// The following lines ensure that we received all necessary events from the TrackedRegatta
|
||||
// When removing a listener we get a Future whose get method will block until all previously triggered events are processed.
|
||||
RaceListener raceListener = new RaceListener() {
|
||||
@Override
|
||||
public void raceRemoved(TrackedRace trackedRace) {
|
||||
}
|
||||
@Override
|
||||
public void raceAdded(TrackedRace trackedRace) {
|
||||
}
|
||||
};
|
||||
regatta.addRaceListener(raceListener, Optional.empty());
|
||||
regatta.removeRaceListener(raceListener).get();
|
||||
|
||||
return trackedRaceStatisticsCache;
|
||||
}
|
||||
|
||||
|
||||
+18
-7
@@ -76,7 +76,12 @@ public class TrackedRaceStatisticsCacheImpl extends AbstractTrackedRegattaAndRac
|
||||
/**
|
||||
* For testing purposes only!
|
||||
*/
|
||||
public TrackedRaceStatistics getStatisticsWaitingForLatest(TrackedRace trackedRace) {
|
||||
public TrackedRaceStatistics getStatisticsWaitingForLatest(TrackedRace trackedRace) throws InterruptedException {
|
||||
synchronized (listeners) {
|
||||
while (!listeners.containsKey(trackedRace)) {
|
||||
listeners.wait();
|
||||
}
|
||||
}
|
||||
return cache.get(trackedRace, true);
|
||||
}
|
||||
|
||||
@@ -84,9 +89,12 @@ public class TrackedRaceStatisticsCacheImpl extends AbstractTrackedRegattaAndRac
|
||||
protected void onRaceAdded(RegattaAndRaceIdentifier raceIdentifier, DynamicTrackedRegatta trackedRegatta,
|
||||
DynamicTrackedRace trackedRace) {
|
||||
Listener listener = new Listener(trackedRace);
|
||||
listeners.put(trackedRace, listener);
|
||||
trackedRace.addListener(listener);
|
||||
triggerUpdateDirect(trackedRace);
|
||||
synchronized (listeners) {
|
||||
listeners.put(trackedRace, listener);
|
||||
trackedRace.addListener(listener);
|
||||
triggerUpdateDirect(trackedRace);
|
||||
listeners.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
private void triggerUpdateScheduled(final DynamicTrackedRace trackedRace) {
|
||||
@@ -116,9 +124,12 @@ public class TrackedRaceStatisticsCacheImpl extends AbstractTrackedRegattaAndRac
|
||||
|
||||
@Override
|
||||
protected void onRaceRemoved(DynamicTrackedRace trackedRace) {
|
||||
Listener listener = listeners.remove(trackedRace);
|
||||
if (listener != null) {
|
||||
trackedRace.removeListener(listener);
|
||||
synchronized (listeners) {
|
||||
Listener listener = listeners.remove(trackedRace);
|
||||
if (listener != null) {
|
||||
trackedRace.removeListener(listener);
|
||||
}
|
||||
listeners.notifyAll();
|
||||
}
|
||||
|
||||
// To prevent leakage of TrackedRace instances as keys in the cache,
|
||||
|
||||
Reference in new issue
Block a user