Merge branch 'bug3535' into bug2840

This commit is contained in:
Axel Uhl committed 2016-03-23 17:46:10 +01:00
commit 11a7e371db
16 files changed
+131 -31

No files matched your search

@@ -0,0 +1,37 @@
package com.sap.sailing.domain.regattalog.tracking.analyzing.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import java.util.Collections;
import java.util.Set;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl;
import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator;
import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class CompetitorDeregistrationTest extends AbstractRegattaLogTrackingTest {
private final Competitor competitor = new CompetitorImpl("comp", "Comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
@Test
public void testCompetitorDeregistration() {
log.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, competitor));
log.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, competitor2));
final CompetitorDeregistrator<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> deregistrator = new CompetitorDeregistrator<>(log,
Collections.singleton(competitor2), author);
final Set<RegattaLogEvent> events = deregistrator.analyze();
deregistrator.deregister(events);
final Set<Competitor> competitors = new CompetitorsInLogAnalyzer<>(log).analyze();
assertEquals(1, competitors.size());
assertSame(competitor, competitors.iterator().next());
}
}
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.abstractlog.shared.analyzing;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -14,14 +15,21 @@ import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
import com.sap.sse.common.Util;
/**
* Generates events that close the events that are responsible for the {@link #mapping} that is passed to the
* constructor.
* Finds the competitor registration events for a given set of {@link Competitor competitors} that must be
* {@link AbstractLog#revokeEvent(AbstractLogEventAuthor, AbstractLogEvent) revoked} in order to deregister the
* competitors. Note that the de-registration cannot be performed during analysis because
* {@link BaseLogAnalyzer#analyze()} obtains a read lock on the log whereas
* {@link AbstractLog#revokeEvent(AbstractLogEventAuthor, AbstractLogEvent)} requires a write lock, and upgrading from a
* read to a write lock is not possible.<p>
*
* Clients must call {@link #deregister} with the result of {@link #analyze()} in order to actually perform the
* deregistration.
*
* @author Jan Bross
*
*/
public class CompetitorDeregistrator<LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>, VisitorT>
extends BaseLogAnalyzer<LogT, EventT, VisitorT, Void> {
extends BaseLogAnalyzer<LogT, EventT, VisitorT, Set<EventT>> {
private static final Logger logger = Logger.getLogger(CompetitorDeregistrator.class.getName());
protected final Iterable<Competitor> competitorsToDeregister;
@@ -34,24 +42,29 @@ extends BaseLogAnalyzer<LogT, EventT, VisitorT, Void> {
}
@Override
protected Void performAnalysis() {
HashSet<Competitor> competitorSet = new HashSet<Competitor>();
protected Set<EventT> performAnalysis() {
final Set<EventT> result = new HashSet<>();
final HashSet<Competitor> competitorSet = new HashSet<Competitor>();
Util.addAll(competitorsToDeregister, competitorSet);
for (EventT event : log.getUnrevokedEventsDescending()) {
if (event instanceof RegisterCompetitorEvent) {
RegisterCompetitorEvent<?> registerEvent = (RegisterCompetitorEvent<?>) event;
if (competitorSet.contains(registerEvent.getCompetitor())) {
try {
log.revokeEvent(eventAuthor, event,
"unregistering competitor because no longer selected for registration");
} catch (NotRevokableException e) {
logger.log(Level.WARNING, "could not unregister competitor by adding RevokeEvent", e);
}
result.add(event);
}
}
}
return null;
return result;
}
public void deregister(final Set<EventT> competitorRegistrationEvents) {
for (final EventT event : competitorRegistrationEvents) {
try {
log.revokeEvent(eventAuthor, event,
"unregistering competitor because no longer selected for registration");
} catch (NotRevokableException e) {
logger.log(Level.WARNING, "could not unregister competitor by adding RevokeEvent", e);
}
}
}
}
@@ -313,19 +313,36 @@ public class TrackImpl<FixType extends Timed> implements Track<FixType> {
}
protected boolean add(FixType fix) {
return add(fix, /* replace */ false);
}
protected boolean add(FixType fix, boolean replace) {
lockForWrite();
try {
return addWithoutLocking(fix);
return addWithoutLocking(fix, replace);
} finally {
unlockAfterWrite();
}
}
/**
* The caller must ensure to hold the write lock for this track when calling this methos
* The caller must ensure to hold the write lock for this track when calling this method.
*
* @param replace
* whether or not to replace an existing fix in the track that is equal to {@link #fix} as defined by the
* comparator used for the {@link #fixes} set. By default this is a comparator only comparing the
* fixes' time stamps. Subclasses may use different comparator implementations.
*/
protected boolean addWithoutLocking(FixType fix) {
return getInternalRawFixes().add(fix);
protected boolean addWithoutLocking(FixType fix, boolean replace) {
final boolean result;
final boolean added = getInternalRawFixes().add(fix);
if (!added && replace) {
getInternalRawFixes().remove(fix);
result = getInternalFixes().add(fix);
} else {
result = added;
}
return result;
}
@Override
@@ -792,6 +792,6 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
public void deregisterCompetitors(Iterable<Competitor> competitors) {
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
CompetitorDeregistrator<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> deregisterer = new CompetitorDeregistrator<>(regattaLog, competitors, regattaLogEventAuthorForRegatta);
deregisterer.analyze();
deregisterer.deregister(deregisterer.analyze());
}
}
@@ -224,6 +224,6 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
public void deregisterCompetitors(Iterable<Competitor> competitors) {
RegattaLog regattaLog = getRegattaLike().getRegattaLog();
CompetitorDeregistrator<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> deregisterer = new CompetitorDeregistrator<>(regattaLog, competitors, regattaLogEventAuthorForAbstractLeaderboard);
deregisterer.analyze();
deregisterer.deregister(deregisterer.analyze());
}
}
@@ -4,7 +4,25 @@ import com.sap.sse.common.Timed;
public interface DynamicTrack<FixType extends Timed> extends Track<FixType> {
/**
* Tries to add {@code fix} to this track. If an {@link #equals(Object) equal} fix already exists
* in this track, the track remains unchanged and {@code false} will be returned.
*
* @return <code>true</code> if the element was added, <code>false</code> otherwise.
*/
boolean add(FixType fix);
/**
* Tries to add {@code fix} to this track. If an {@link #equals(Object) equal} fix already exists
* in this track and {@code replace} is {@code false}, the track remains unchanged and {@code false} will be returned.
* If {@code replace} is {@code true}, an equal (by definition of the comparator used for the fixes set) fix will
* replace the fix contained in this track.
*
* @param replace
* whether or not to replace an existing fix in the track that is equal to {@link #fix} as defined by the
* comparator used for the {@link #fixes} set. By default this is a comparator only comparing the fixes'
* time stamps. Subclasses may use different comparator implementations.
*
* @return <code>true</code> if the element was added, <code>false</code> otherwise.
*/
boolean add(FixType fix, boolean replace);
}
@@ -47,7 +47,7 @@ public class DynamicGPSFixMovingTrackImpl<ItemType> extends GPSFixTrackImpl<Item
*/
@Override
public void addGPSFix(GPSFixMoving gpsFix) {
add(gpsFix);
add(gpsFix, /* replace */ true);
}
@Override
@@ -55,6 +55,11 @@ public class DynamicGPSFixMovingTrackImpl<ItemType> extends GPSFixTrackImpl<Item
return super.add(new CompactGPSFixMovingImpl(fix));
}
@Override
public boolean add(GPSFixMoving fix, boolean replace) {
return super.add(new CompactGPSFixMovingImpl(fix), replace);
}
/**
* Interpolates linearly between the two fixes based on their time difference and distance. This
* intentionally ignores the {@link GPSFixMoving#getSpeed() speed values} provided by the fixes
@@ -12,12 +12,17 @@ public class DynamicGPSFixTrackImpl<ItemType> extends GPSFixTrackImpl<ItemType,
}
public void addGPSFix(GPSFix gpsFix) {
add(gpsFix);
add(gpsFix, /* replace */ true);
}
@Override
public boolean add(GPSFix fix) {
return super.add(new CompactGPSFixImpl(fix));
return super.add(fix);
}
@Override
public boolean add(GPSFix fix, boolean replace) {
return super.add(new CompactGPSFixImpl(fix), replace);
}
@Override
@@ -17,4 +17,9 @@ public class DynamicTrackImpl<FixType extends Timed> extends TrackImpl<FixType>
public boolean add(FixType fix) {
return super.add(fix);
}
@Override
public boolean add(FixType fix, boolean replace) {
return super.add(fix, replace);
}
}
@@ -1106,7 +1106,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
lockForWrite();
try {
firstFixInTrack = getRawFixes().isEmpty();
result = addWithoutLocking(fix);
result = addWithoutLocking(fix, /* replace */ false);
if (!validityCachingSuspended) {
invalidateValidityAndEstimatedSpeedAndDistanceCaches(fix);
}
@@ -108,9 +108,14 @@ public class WindTrackImpl extends TrackImpl<Wind> implements WindTrack {
}
@Override
public boolean add(Wind wind) {
public boolean add(Wind fix) {
return super.add(fix);
}
@Override
public boolean add(Wind wind, boolean replace) {
final CompactWindImpl compactWind = new CompactWindImpl(wind);
final boolean result = super.add(compactWind);
final boolean result = super.add(compactWind, replace);
notifyListenersAboutReceive(compactWind);
return result;
}
@@ -139,7 +139,6 @@ public interface TextMessages extends Messages {
String latestRaceResultsHeadline();
String latestRaceResultsIsNew();
String latestRaceResultsIsUpdated();
String latestRaceResultsRaceCountLabel();
String latestRaceResultsRaceCountUnit();
String latestRaceResultsRefresh();
String leaderboardQuickAccessLabel();
@@ -128,7 +128,6 @@ headerSponsoring=Sponsoring
latestRaceResultsHeadline=Latest Official Race Results
latestRaceResultsIsNew=New
latestRaceResultsIsUpdated=Updated
latestRaceResultsRaceCountLabel=Result after
latestRaceResultsRaceCountUnit=races
latestRaceResultsRefresh=refresh
leaderboardQuickAccessLabel=Leaderboard Quick Access
@@ -128,7 +128,6 @@ headerSponsoring=Sponsoren
latestRaceResultsHeadline=Letzten ofiziellen Ergebnisse
latestRaceResultsIsNew=Neu
latestRaceResultsIsUpdated=Aktualisiert
latestRaceResultsRaceCountLabel=Ergebnis nach
latestRaceResultsRaceCountUnit=Rennen
latestRaceResultsRefresh=aktualisieren
leaderboardQuickAccessLabel=Ergebnisliste Schnellzugang
@@ -128,7 +128,6 @@ headerSponsoring=Sponsoring
latestRaceResultsHeadline=Latest Official Race Results
latestRaceResultsIsNew=New
latestRaceResultsIsUpdated=Updated
latestRaceResultsRaceCountLabel=Result after
latestRaceResultsRaceCountUnit=races
latestRaceResultsRefresh=refresh
leaderboardQuickAccessLabel=Leaderboard Quick Access
@@ -159,7 +159,6 @@ headerSponsoring=Sponsoring
latestRaceResultsHeadline=Latest Official Race Results
latestRaceResultsIsNew=New
latestRaceResultsIsUpdated=Updated
latestRaceResultsRaceCountLabel=Result after
latestRaceResultsRaceCountUnit=races
latestRaceResultsRefresh=refresh
leaderboardQuickAccessLabel=Leaderboard Quick Access