Merge remote-tracking branch 'server/competitor_searchtag'

This commit is contained in:
Axel Uhl committed 2016-04-15 14:29:02 +02:00
commit 8b5cade99d
75 files changed
+6602 -6488

No files matched your search

@@ -17,7 +17,9 @@ public interface CompetitorDTO extends Serializable, MappableToDevice {
String getIdAsString();
String getSailID();
String getSearchTag();
BoatDTO getBoat();
BoatClassDTO getBoatClass();
@@ -1,207 +1,219 @@
package com.sap.sailing.domain.common.dto;
import java.io.Serializable;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
/**
* Equality and hash code are based on the {@link #getIdAsString() ID}, the {@link #getSailID() sail number}, the
* {@link #getBoatClass() boat class} (whose equality and hash code, in turn, depends on its name) and the
* {@link #getThreeLetterIocCountryCode() IOC country code}. Note that the three latter properties are subject
* to change for a competitor while the ID remains unchanged.
*
* @author Axel Uhl (d043530)
*
*/
public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serializable {
private static final long serialVersionUID = -4997852354821083154L;
private String countryName;
private String twoLetterIsoCountryCode;
private String threeLetterIocCountryCode;
private Color color;
private String email;
private String idAsString;
private BoatClassDTO boatClass;
private BoatDTO boat;
private String imageURL;
private String flagImageURL;
private Double timeOnTimeFactor;
private Duration timeOnDistanceAllowancePerNauticalMile;
public CompetitorDTOImpl() {}
public CompetitorDTOImpl(String name, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode,
String countryName, String idAsString, String imageURL, String flagImageURL,
BoatDTO boat, BoatClassDTO boatClass, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) {
super(name);
this.color = color;
this.email = email;
this.twoLetterIsoCountryCode = twoLetterIsoCountryCode;
this.threeLetterIocCountryCode = threeLetterIocCountryCode;
this.countryName = countryName;
this.idAsString = idAsString;
this.imageURL = imageURL;
this.flagImageURL = flagImageURL;
this.boat = boat;
this.boatClass = boatClass;
this.timeOnTimeFactor = timeOnTimeFactor;
this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((boatClass == null) ? 0 : boatClass.hashCode());
result = prime * result + ((boat == null) ? 0 : boat.hashCode());
result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode());
result = prime * result + ((color == null) ? 0 : color.hashCode());
result = prime * result + ((email == null) ? 0 : email.hashCode());
result = prime * result + ((threeLetterIocCountryCode == null) ? 0 : threeLetterIocCountryCode.hashCode());
result = prime * result + ((imageURL == null) ? 0 : imageURL.hashCode());
result = prime * result + ((flagImageURL == null) ? 0 : flagImageURL.hashCode());
result = prime * result + ((timeOnTimeFactor == null) ? 0 : timeOnTimeFactor.hashCode());
result = prime * result + ((timeOnDistanceAllowancePerNauticalMile == null) ? 0 : timeOnDistanceAllowancePerNauticalMile.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
CompetitorDTOImpl other = (CompetitorDTOImpl) obj;
if (boatClass == null) {
if (other.boatClass != null)
return false;
} else if (!boatClass.equals(other.boatClass))
return false;
if (boat == null) {
if (other.boat != null)
return false;
} else if (!boat.equals(other.boat))
return false;
if (idAsString == null) {
if (other.idAsString != null)
return false;
} else if (!idAsString.equals(other.idAsString))
return false;
if (threeLetterIocCountryCode == null) {
if (other.threeLetterIocCountryCode != null)
return false;
} else if (!threeLetterIocCountryCode.equals(other.threeLetterIocCountryCode))
return false;
if (color == null) {
if (other.color != null)
return false;
} else if (!color.equals(other.color))
return false;
if (email == null) {
if (other.email != null)
return false;
} else if (!email.equals(other.email))
return false;
if (imageURL == null) {
if (other.imageURL != null)
return false;
} else if (!imageURL.equals(other.imageURL))
return false;
if (flagImageURL == null) {
if (other.flagImageURL != null)
return false;
} else if (!flagImageURL.equals(other.flagImageURL))
return false;
if (timeOnTimeFactor == null) {
if (other.timeOnTimeFactor != null)
return false;
} else if (!timeOnTimeFactor.equals(other.timeOnTimeFactor))
return false;
if (timeOnDistanceAllowancePerNauticalMile == null) {
if (other.timeOnDistanceAllowancePerNauticalMile != null)
return false;
} else if (!timeOnDistanceAllowancePerNauticalMile.equals(other.timeOnDistanceAllowancePerNauticalMile))
return false;
return true;
}
@Override
public String getTwoLetterIsoCountryCode() {
return twoLetterIsoCountryCode;
}
@Override
public String getThreeLetterIocCountryCode() {
return threeLetterIocCountryCode;
}
@Override
public String getCountryName() {
return countryName;
}
@Override
public String getSailID() {
return boat==null?null:boat.getSailId();
}
@Override
public String getImageURL() {
return imageURL;
}
@Override
public String getFlagImageURL() {
return flagImageURL;
}
@Override
public String getIdAsString() {
return idAsString;
}
@Override
public BoatClassDTO getBoatClass() {
return boatClass;
}
@Override
public CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion) {
return this;
}
public Color getColor() {
return color;
}
public String getEmail() {
return email;
}
public String email(){
return email;
}
@Override
public boolean hasEmail() {
return email != null && !email.isEmpty();
}
@Override
public Double getTimeOnTimeFactor() {
return timeOnTimeFactor;
}
@Override
public Duration getTimeOnDistanceAllowancePerNauticalMile() {
return timeOnDistanceAllowancePerNauticalMile;
}
@Override
public BoatDTO getBoat() {
return boat;
}
}
package com.sap.sailing.domain.common.dto;
import java.io.Serializable;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
/**
* Equality and hash code are based on the {@link #getIdAsString() ID}, the {@link #getSailID() sail number}, the
* {@link #getBoatClass() boat class} (whose equality and hash code, in turn, depends on its name) and the
* {@link #getThreeLetterIocCountryCode() IOC country code}. Note that the three latter properties are subject
* to change for a competitor while the ID remains unchanged.
*
* @author Axel Uhl (d043530)
*
*/
public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serializable {
private static final long serialVersionUID = -4997852354821083154L;
private String countryName;
private String twoLetterIsoCountryCode;
private String threeLetterIocCountryCode;
private Color color;
private String email;
private String searchTag;
private String idAsString;
private BoatClassDTO boatClass;
private BoatDTO boat;
private String imageURL;
private String flagImageURL;
private Double timeOnTimeFactor;
private Duration timeOnDistanceAllowancePerNauticalMile;
public CompetitorDTOImpl() {}
public CompetitorDTOImpl(String name, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode,
String countryName, String idAsString, String imageURL, String flagImageURL,
BoatDTO boat, BoatClassDTO boatClass, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) {
super(name);
this.color = color;
this.email = email;
this.twoLetterIsoCountryCode = twoLetterIsoCountryCode;
this.threeLetterIocCountryCode = threeLetterIocCountryCode;
this.countryName = countryName;
this.idAsString = idAsString;
this.imageURL = imageURL;
this.flagImageURL = flagImageURL;
this.boat = boat;
this.boatClass = boatClass;
this.timeOnTimeFactor = timeOnTimeFactor;
this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile;
this.searchTag = searchTag;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((boatClass == null) ? 0 : boatClass.hashCode());
result = prime * result + ((boat == null) ? 0 : boat.hashCode());
result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode());
result = prime * result + ((color == null) ? 0 : color.hashCode());
result = prime * result + ((email == null) ? 0 : email.hashCode());
result = prime * result + ((threeLetterIocCountryCode == null) ? 0 : threeLetterIocCountryCode.hashCode());
result = prime * result + ((imageURL == null) ? 0 : imageURL.hashCode());
result = prime * result + ((flagImageURL == null) ? 0 : flagImageURL.hashCode());
result = prime * result + ((timeOnTimeFactor == null) ? 0 : timeOnTimeFactor.hashCode());
result = prime * result + ((timeOnDistanceAllowancePerNauticalMile == null) ? 0 : timeOnDistanceAllowancePerNauticalMile.hashCode());
result = prime * result + ((searchTag == null) ? 0 : searchTag.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
CompetitorDTOImpl other = (CompetitorDTOImpl) obj;
if (boatClass == null) {
if (other.boatClass != null)
return false;
} else if (!boatClass.equals(other.boatClass))
return false;
if (boat == null) {
if (other.boat != null)
return false;
} else if (!boat.equals(other.boat))
return false;
if (idAsString == null) {
if (other.idAsString != null)
return false;
} else if (!idAsString.equals(other.idAsString))
return false;
if (threeLetterIocCountryCode == null) {
if (other.threeLetterIocCountryCode != null)
return false;
} else if (!threeLetterIocCountryCode.equals(other.threeLetterIocCountryCode))
return false;
if (color == null) {
if (other.color != null)
return false;
} else if (!color.equals(other.color))
return false;
if (email == null) {
if (other.email != null)
return false;
} else if (!email.equals(other.email))
return false;
if (imageURL == null) {
if (other.imageURL != null)
return false;
} else if (!imageURL.equals(other.imageURL))
return false;
if (flagImageURL == null) {
if (other.flagImageURL != null)
return false;
} else if (!flagImageURL.equals(other.flagImageURL))
return false;
if (timeOnTimeFactor == null) {
if (other.timeOnTimeFactor != null)
return false;
} else if (!timeOnTimeFactor.equals(other.timeOnTimeFactor))
return false;
if (timeOnDistanceAllowancePerNauticalMile == null) {
if (other.timeOnDistanceAllowancePerNauticalMile != null)
return false;
} else if (!timeOnDistanceAllowancePerNauticalMile.equals(other.timeOnDistanceAllowancePerNauticalMile))
return false;
if (searchTag == null) {
if (other.searchTag != null)
return false;
} else if (!searchTag.equals(other.searchTag))
return false;
return true;
}
@Override
public String getTwoLetterIsoCountryCode() {
return twoLetterIsoCountryCode;
}
@Override
public String getThreeLetterIocCountryCode() {
return threeLetterIocCountryCode;
}
@Override
public String getCountryName() {
return countryName;
}
@Override
public String getSailID() {
return boat==null?null:boat.getSailId();
}
@Override
public String getImageURL() {
return imageURL;
}
@Override
public String getFlagImageURL() {
return flagImageURL;
}
@Override
public String getIdAsString() {
return idAsString;
}
@Override
public BoatClassDTO getBoatClass() {
return boatClass;
}
@Override
public CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion) {
return this;
}
public Color getColor() {
return color;
}
public String getSearchTag() {
return searchTag;
}
public String getEmail() {
return email;
}
public String email(){
return email;
}
@Override
public boolean hasEmail() {
return email != null && !email.isEmpty();
}
@Override
public Double getTimeOnTimeFactor() {
return timeOnTimeFactor;
}
@Override
public Duration getTimeOnDistanceAllowancePerNauticalMile() {
return timeOnDistanceAllowancePerNauticalMile;
}
@Override
public BoatDTO getBoat() {
return boat;
}
}
@@ -1,143 +1,149 @@
package com.sap.sailing.domain.common.dto;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
/**
* Equality and hash code are based on the index pointing into a previous leaderboard's competitors list.
*
* @author Axel Uhl (d043530)
*
*/
public class PreviousCompetitorDTOImpl implements CompetitorDTO {
private static final long serialVersionUID = 8820028699103040805L;
private int indexInPreviousCompetitorList;
PreviousCompetitorDTOImpl() {} // for serialization only
public PreviousCompetitorDTOImpl(int indexInPreviousCompetitorList) {
super();
this.indexInPreviousCompetitorList = indexInPreviousCompetitorList;
}
protected int getIndexInPreviousCompetitorList() {
return indexInPreviousCompetitorList;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + indexInPreviousCompetitorList;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PreviousCompetitorDTOImpl other = (PreviousCompetitorDTOImpl) obj;
if (indexInPreviousCompetitorList != other.indexInPreviousCompetitorList)
return false;
return true;
}
@Override
public String getTwoLetterIsoCountryCode() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getThreeLetterIocCountryCode() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getCountryName() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getSailID() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public BoatDTO getBoat() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public Color getColor() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getIdAsString() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public BoatClassDTO getBoatClass() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getName() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getEmail() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getImageURL() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getFlagImageURL() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public boolean hasEmail() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public Double getTimeOnTimeFactor() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public Duration getTimeOnDistanceAllowancePerNauticalMile() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion) {
return previousVersion.competitors.get(indexInPreviousCompetitorList);
}
package com.sap.sailing.domain.common.dto;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
/**
* Equality and hash code are based on the index pointing into a previous leaderboard's competitors list.
*
* @author Axel Uhl (d043530)
*
*/
public class PreviousCompetitorDTOImpl implements CompetitorDTO {
private static final long serialVersionUID = 8820028699103040805L;
private int indexInPreviousCompetitorList;
PreviousCompetitorDTOImpl() {} // for serialization only
public PreviousCompetitorDTOImpl(int indexInPreviousCompetitorList) {
super();
this.indexInPreviousCompetitorList = indexInPreviousCompetitorList;
}
protected int getIndexInPreviousCompetitorList() {
return indexInPreviousCompetitorList;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + indexInPreviousCompetitorList;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PreviousCompetitorDTOImpl other = (PreviousCompetitorDTOImpl) obj;
if (indexInPreviousCompetitorList != other.indexInPreviousCompetitorList)
return false;
return true;
}
@Override
public String getTwoLetterIsoCountryCode() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getThreeLetterIocCountryCode() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getCountryName() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getSailID() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public BoatDTO getBoat() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public Color getColor() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getIdAsString() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public BoatClassDTO getBoatClass() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getName() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getEmail() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getSearchTag() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getImageURL() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public String getFlagImageURL() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public boolean hasEmail() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public Double getTimeOnTimeFactor() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public Duration getTimeOnDistanceAllowancePerNauticalMile() {
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
" need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization");
}
@Override
public CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion) {
return previousVersion.competitors.get(indexInPreviousCompetitorList);
}
}
@@ -22,6 +22,7 @@ public class CompetitorJsonConstants {
public static final String FIELD_BOAT = "boat";
public static final String FIELD_DISPLAY_COLOR = "displayColor";
public static final String FIELD_EMAIL = "email";
public static final String FIELD_SEARCHTAG = "searchTag";
public static final String FIELD_FLAG_IMAGE_URI = "flagImageUri";
public static final String FIELD_TEAM_IMAGE_URI = "teamImageUri";
public static final String FIELD_TIME_ON_TIME_FACTOR = "timeOnTimeFactor";
@@ -1,94 +1,94 @@
package com.sap.sailing.domain.racelogtracking.test;
import static com.sap.sse.common.Util.size;
import static junit.framework.Assert.assertEquals;
import java.util.UUID;
import org.junit.After;
import org.junit.Before;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl;
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl;
import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl;
import com.sap.sailing.domain.persistence.racelog.tracking.impl.MongoGPSFixStoreImpl;
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
import com.sap.sailing.domain.racelog.tracking.test.mock.MockDeviceAndSessionIdentifierWithGPSFixesDeserializer;
import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServiceFinderFactory;
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
import com.sap.sailing.domain.tracking.Track;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.gateway.deserialization.impl.DeviceAndSessionIdentifierWithGPSFixesDeserializer;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class AbstractGPSFixStoreTest {
protected RacingEventService service;
protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory();
DeviceAndSessionIdentifierWithGPSFixesDeserializer deserializer =
new MockDeviceAndSessionIdentifierWithGPSFixesDeserializer();
protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a");
protected RaceLog raceLog;
protected RegattaLog regattaLog;
protected GPSFixStore store;
protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null);
protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark");
protected final AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0);
protected GPSFixMoving createFix(long millis, double lat, double lng, double knots, double degrees) {
return new GPSFixMovingImpl(new DegreePosition(lat, lng),
new MillisecondsTimePoint(millis), new KnotSpeedWithBearingImpl(knots, new DegreeBearingImpl(degrees)));
}
@Before
public void setServiceAndRaceLog() {
service = new RacingEventServiceImpl(null, null, serviceFinderFactory);
raceLog = new RaceLogImpl("racelog");
regattaLog = new RegattaLogImpl("regattalog");
store = new MongoGPSFixStoreImpl(service.getMongoObjectFactory(), service.getDomainObjectFactory(),
serviceFinderFactory);
}
@After
public void after() {
MongoObjectFactoryImpl mongoOF = (MongoObjectFactoryImpl) service.getMongoObjectFactory();
mongoOF.getGPSFixCollection().drop();
mongoOF.getGPSFixMetadataCollection().drop();
}
protected void map(RegattaLog regattaLog, Competitor comp, DeviceIdentifier device, long from, long to) {
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(),
comp, device, new MillisecondsTimePoint(from), new MillisecondsTimePoint(to)));
}
protected void map(Competitor comp, DeviceIdentifier device, long from, long to) {
map(regattaLog, comp, device, from, to);
}
protected void map(Mark mark, DeviceIdentifier device, long from, long to) {
regattaLog.add(new RegattaLogDeviceMarkMappingEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(),
mark, device, new MillisecondsTimePoint(from), new MillisecondsTimePoint(to)));
}
protected void testNumberOfRawFixes(Track<?> track, long expected) {
track.lockForRead();
assertEquals(expected, size(track.getRawFixes()));
track.unlockAfterRead();
}
}
package com.sap.sailing.domain.racelogtracking.test;
import static com.sap.sse.common.Util.size;
import static junit.framework.Assert.assertEquals;
import java.util.UUID;
import org.junit.After;
import org.junit.Before;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl;
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl;
import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl;
import com.sap.sailing.domain.persistence.racelog.tracking.impl.MongoGPSFixStoreImpl;
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
import com.sap.sailing.domain.racelog.tracking.test.mock.MockDeviceAndSessionIdentifierWithGPSFixesDeserializer;
import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServiceFinderFactory;
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
import com.sap.sailing.domain.tracking.Track;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.gateway.deserialization.impl.DeviceAndSessionIdentifierWithGPSFixesDeserializer;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class AbstractGPSFixStoreTest {
protected RacingEventService service;
protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory();
DeviceAndSessionIdentifierWithGPSFixesDeserializer deserializer =
new MockDeviceAndSessionIdentifierWithGPSFixesDeserializer();
protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a");
protected RaceLog raceLog;
protected RegattaLog regattaLog;
protected GPSFixStore store;
protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null);
protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark");
protected final AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0);
protected GPSFixMoving createFix(long millis, double lat, double lng, double knots, double degrees) {
return new GPSFixMovingImpl(new DegreePosition(lat, lng),
new MillisecondsTimePoint(millis), new KnotSpeedWithBearingImpl(knots, new DegreeBearingImpl(degrees)));
}
@Before
public void setServiceAndRaceLog() {
service = new RacingEventServiceImpl(null, null, serviceFinderFactory);
raceLog = new RaceLogImpl("racelog");
regattaLog = new RegattaLogImpl("regattalog");
store = new MongoGPSFixStoreImpl(service.getMongoObjectFactory(), service.getDomainObjectFactory(),
serviceFinderFactory);
}
@After
public void after() {
MongoObjectFactoryImpl mongoOF = (MongoObjectFactoryImpl) service.getMongoObjectFactory();
mongoOF.getGPSFixCollection().drop();
mongoOF.getGPSFixMetadataCollection().drop();
}
protected void map(RegattaLog regattaLog, Competitor comp, DeviceIdentifier device, long from, long to) {
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(),
comp, device, new MillisecondsTimePoint(from), new MillisecondsTimePoint(to)));
}
protected void map(Competitor comp, DeviceIdentifier device, long from, long to) {
map(regattaLog, comp, device, from, to);
}
protected void map(Mark mark, DeviceIdentifier device, long from, long to) {
regattaLog.add(new RegattaLogDeviceMarkMappingEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(),
mark, device, new MillisecondsTimePoint(from), new MillisecondsTimePoint(to)));
}
protected void testNumberOfRawFixes(Track<?> track, long expected) {
track.lockForRead();
assertEquals(expected, size(track.getRawFixes()));
track.unlockAfterRead();
}
}
@@ -170,7 +170,7 @@ public class CreateAndTrackWithRaceLogTest {
// add a mapping and one fix in, one out of mapping
Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null, null, null,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1");
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, 0, comp1, dev1, t(0), t(10)));
addFixes0(dev1);
@@ -206,7 +206,7 @@ public class CreateAndTrackWithRaceLogTest {
// add a mapping and one fix in, one out of mapping
Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null, null, null,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1");
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, UUID.randomUUID(), comp1, dev1,
t(0), t(10)));
@@ -1,150 +1,150 @@
package com.sap.sailing.domain.racelogtracking.test.impl;
import static junit.framework.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.WaypointImpl;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
import com.sap.sailing.domain.racelogtracking.test.AbstractGPSFixStoreTest;
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.TimeRangeImpl;
public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er");
@Test
public void doesRaceLoadOnlyBetweenStartAndEndOfTracking() throws TransformationException,
NoCorrespondingServiceRegisteredException, InterruptedException {
Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2");
DeviceIdentifier markDevice = new SmartphoneImeiIdentifier("imei2");
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark));
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2));
Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark),
new WaypointImpl(mark2) }));
RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp, comp2 }));
map(comp, device, 0, 10000);
map(mark, markDevice, 0, 10000);
store.storeFix(device, createFix(100, 10, 20, 30, 40)); // before
store.storeFix(device, createFix(1100, 10, 20, 30, 40)); // in
store.storeFix(device, createFix(2100, 10, 20, 30, 40)); // after
store.storeFix(markDevice, createFix(100, 10, 20, 30, 40));
store.storeFix(markDevice, createFix(1100, 10, 20, 30, 40));
store.storeFix(markDevice, createFix(2100, 10, 20, 30, 40));
TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE,
EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */
null, /* endDate */null, null, null, "a", null));
final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race,
Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, store, 0, 0, 0, /*useMarkPassingCalculator*/ false,
OneDesignRankingMetric::new, mock(RaceLogResolver.class));
trackedRace.setStartOfTrackingReceived(new MillisecondsTimePoint(1000));
trackedRace.setEndOfTrackingReceived(new MillisecondsTimePoint(2000));
trackedRace.attachRaceLog(raceLog);
trackedRace.attachRegattaLog(regattaLog);
trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(regattaLog);
testNumberOfRawFixes(trackedRace.getTrack(comp), 1);
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1);
// now extend the tracking interval of the tracked race and assert that the additional fixes are loaded
trackedRace.setEndOfTrackingReceived(new MillisecondsTimePoint(2500), /* wait for fixes to load */ true);
testNumberOfRawFixes(trackedRace.getTrack(comp), 2);
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2);
trackedRace.setStartOfTrackingReceived(new MillisecondsTimePoint(0), /* wait for fixes to load */ true);
testNumberOfRawFixes(trackedRace.getTrack(comp), 3);
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 3);
}
@Test
public void areFixesStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException,
InterruptedException {
Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2");
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark));
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2));
DeviceIdentifier device2 = new SmartphoneImeiIdentifier("imei2");
DeviceIdentifier device3 = new SmartphoneImeiIdentifier("imei3");
Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark),
new WaypointImpl(mark2) }));
RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp,
comp2 }));
map(comp, device, 0, 20000);
map(comp2, device2, 0, 600);
// reuse device for two marks
map(mark, device3, 0, 600);
map(mark2, device3, 0, 600);
store.storeFix(device, createFix(100, 10, 20, 30, 40));
store.storeFix(device, createFix(200, 10, 20, 30, 40));
store.storeFix(device2, createFix(100, 10, 20, 30, 40));
store.storeFix(device3, createFix(100, 10, 20, 30, 40));
store.storeFix(device3, createFix(100, 10, 20, 30, 40));
for (int i = 0; i < 10000; i++) {
store.storeFix(device, createFix(i + 1000, 10, 20, 30, 40));
}
TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE,
EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */
null, /* endDate */null, null, null, "a", null));
DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race,
Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, store, 0, 0, 0, /*useMarkPassingCalculator*/ false,
OneDesignRankingMetric::new, mock(RaceLogResolver.class));
trackedRace.attachRaceLog(raceLog);
trackedRace.attachRegattaLog(regattaLog);
trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(regattaLog);
testNumberOfRawFixes(trackedRace.getTrack(comp), 10002);
testNumberOfRawFixes(trackedRace.getTrack(comp2), 1);
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1);
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark2), 1);
}
@Test
public void metadataStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException {
assertEquals(0, store.getNumberOfFixes(device));
assertEquals(null, store.getTimeRangeCoveredByFixes(device));
map(comp, device, 0, 600);
store.storeFix(device, createFix(100, 10, 20, 30, 40));
store.storeFix(device, createFix(200, 10, 20, 30, 40));
assertEquals(2, store.getNumberOfFixes(device));
assertEquals(TimeRangeImpl.create(100, 200), store.getTimeRangeCoveredByFixes(device));
}
}
package com.sap.sailing.domain.racelogtracking.test.impl;
import static junit.framework.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.WaypointImpl;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
import com.sap.sailing.domain.racelogtracking.test.AbstractGPSFixStoreTest;
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.TimeRangeImpl;
public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er");
@Test
public void doesRaceLoadOnlyBetweenStartAndEndOfTracking() throws TransformationException,
NoCorrespondingServiceRegisteredException, InterruptedException {
Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2");
DeviceIdentifier markDevice = new SmartphoneImeiIdentifier("imei2");
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark));
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2));
Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark),
new WaypointImpl(mark2) }));
RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp, comp2 }));
map(comp, device, 0, 10000);
map(mark, markDevice, 0, 10000);
store.storeFix(device, createFix(100, 10, 20, 30, 40)); // before
store.storeFix(device, createFix(1100, 10, 20, 30, 40)); // in
store.storeFix(device, createFix(2100, 10, 20, 30, 40)); // after
store.storeFix(markDevice, createFix(100, 10, 20, 30, 40));
store.storeFix(markDevice, createFix(1100, 10, 20, 30, 40));
store.storeFix(markDevice, createFix(2100, 10, 20, 30, 40));
TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE,
EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */
null, /* endDate */null, null, null, "a", null));
final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race,
Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, store, 0, 0, 0, /*useMarkPassingCalculator*/ false,
OneDesignRankingMetric::new, mock(RaceLogResolver.class));
trackedRace.setStartOfTrackingReceived(new MillisecondsTimePoint(1000));
trackedRace.setEndOfTrackingReceived(new MillisecondsTimePoint(2000));
trackedRace.attachRaceLog(raceLog);
trackedRace.attachRegattaLog(regattaLog);
trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(regattaLog);
testNumberOfRawFixes(trackedRace.getTrack(comp), 1);
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1);
// now extend the tracking interval of the tracked race and assert that the additional fixes are loaded
trackedRace.setEndOfTrackingReceived(new MillisecondsTimePoint(2500), /* wait for fixes to load */ true);
testNumberOfRawFixes(trackedRace.getTrack(comp), 2);
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2);
trackedRace.setStartOfTrackingReceived(new MillisecondsTimePoint(0), /* wait for fixes to load */ true);
testNumberOfRawFixes(trackedRace.getTrack(comp), 3);
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 3);
}
@Test
public void areFixesStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException,
InterruptedException {
Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2");
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark));
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2));
DeviceIdentifier device2 = new SmartphoneImeiIdentifier("imei2");
DeviceIdentifier device3 = new SmartphoneImeiIdentifier("imei3");
Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark),
new WaypointImpl(mark2) }));
RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp,
comp2 }));
map(comp, device, 0, 20000);
map(comp2, device2, 0, 600);
// reuse device for two marks
map(mark, device3, 0, 600);
map(mark2, device3, 0, 600);
store.storeFix(device, createFix(100, 10, 20, 30, 40));
store.storeFix(device, createFix(200, 10, 20, 30, 40));
store.storeFix(device2, createFix(100, 10, 20, 30, 40));
store.storeFix(device3, createFix(100, 10, 20, 30, 40));
store.storeFix(device3, createFix(100, 10, 20, 30, 40));
for (int i = 0; i < 10000; i++) {
store.storeFix(device, createFix(i + 1000, 10, 20, 30, 40));
}
TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE,
EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */
null, /* endDate */null, null, null, "a", null));
DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race,
Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, store, 0, 0, 0, /*useMarkPassingCalculator*/ false,
OneDesignRankingMetric::new, mock(RaceLogResolver.class));
trackedRace.attachRaceLog(raceLog);
trackedRace.attachRegattaLog(regattaLog);
trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(regattaLog);
testNumberOfRawFixes(trackedRace.getTrack(comp), 10002);
testNumberOfRawFixes(trackedRace.getTrack(comp2), 1);
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1);
testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark2), 1);
}
@Test
public void metadataStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException {
assertEquals(0, store.getNumberOfFixes(device));
assertEquals(null, store.getTimeRangeCoveredByFixes(device));
map(comp, device, 0, 600);
store.storeFix(device, createFix(100, 10, 20, 30, 40));
store.storeFix(device, createFix(200, 10, 20, 30, 40));
assertEquals(2, store.getNumberOfFixes(device));
assertEquals(TimeRangeImpl.create(100, 200), store.getTimeRangeCoveredByFixes(device));
}
}
@@ -54,7 +54,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest {
public void testStartTimeInferencePrecedenceOrder() throws TransformationException,
NoCorrespondingServiceRegisteredException, InterruptedException {
Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2");
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark));
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2));
@@ -19,8 +19,8 @@ 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);
private final Competitor competitor = new CompetitorImpl("comp", "Comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
@Test
public void testCompetitorDeregistration() {
@@ -27,8 +27,8 @@ import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class DeviceMappingFinderTest 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);
private final Competitor competitor = new CompetitorImpl("comp", "Comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
private final DeviceIdentifier device = new SmartphoneImeiIdentifier("imei");
private int time = 0;
@@ -23,6 +23,8 @@ public interface Competitor extends Named, WithID, IsManagedByCache<SharedDomain
boolean hasEmail();
String getSearchTag();
/**
* an alternative flag image (per default the nation flag
* @return the URI of the flag image
@@ -1,20 +1,22 @@
package com.sap.sailing.domain.base;
import java.net.URI;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
public interface CompetitorChangeListener extends BoatChangeListener, NationalityChangeListener {
void colorChanged(Color oldColor, Color newColor);
void nameChanged(String oldName, String newName);
void emailChanged(String oldEmail, String newEmail);
void flagImageChanged(URI oldFlagImageURI, URI newFlagImageURI);
void timeOnTimeFactorChanged(Double oldTimeOnTimeFactor, Double newTimeOnTimeFactor);
void timeOnDistanceAllowancePerNauticalMileChanged(Duration oldTimeOnDistanceAllowancePerNauticalMile, Duration newTimeOnDistanceAllowancePerNauticalMile);
}
package com.sap.sailing.domain.base;
import java.net.URI;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
public interface CompetitorChangeListener extends BoatChangeListener, NationalityChangeListener {
void colorChanged(Color oldColor, Color newColor);
void nameChanged(String oldName, String newName);
void emailChanged(String oldEmail, String newEmail);
void searchTagChanged(String oldSearchTag, String newSearchTag);
void flagImageChanged(URI oldFlagImageURI, URI newFlagImageURI);
void timeOnTimeFactorChanged(Double oldTimeOnTimeFactor, Double newTimeOnTimeFactor);
void timeOnDistanceAllowancePerNauticalMileChanged(Duration oldTimeOnDistanceAllowancePerNauticalMile, Duration newTimeOnDistanceAllowancePerNauticalMile);
}
@@ -1,33 +1,33 @@
package com.sap.sailing.domain.base;
import java.io.Serializable;
import java.net.URI;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
/**
* Base interface for classes managing a set of {@link Competitor} objects.
*/
public interface CompetitorFactory {
/**
* If a valid competitor is returned and the caller has information available that could be used to update the competitor,
* the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if <code>true</code>,
* must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the
* competitor's values.
*/
Competitor getExistingCompetitorById(Serializable competitorId);
/**
* Checks if the <code>competitor</code> shall be updated from the default provided by, e.g., a tracking infrastructure.
* Callers of {@link #getExistingCompetitorById(Serializable)} or {@link #getExistingCompetitorByIdAsString(String)}
* must call this method in case they retrieve a valid competitor by ID and have data available that can be used to update
* the competitor.
*/
boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result);
Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email,
URI flagImageURI, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile);
}
package com.sap.sailing.domain.base;
import java.io.Serializable;
import java.net.URI;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
/**
* Base interface for classes managing a set of {@link Competitor} objects.
*/
public interface CompetitorFactory {
/**
* If a valid competitor is returned and the caller has information available that could be used to update the competitor,
* the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if <code>true</code>,
* must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the
* competitor's values.
*/
Competitor getExistingCompetitorById(Serializable competitorId);
/**
* Checks if the <code>competitor</code> shall be updated from the default provided by, e.g., a tracking infrastructure.
* Callers of {@link #getExistingCompetitorById(Serializable)} or {@link #getExistingCompetitorByIdAsString(String)}
* must call this method in case they retrieve a valid competitor by ID and have data available that can be used to update
* the competitor.
*/
boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result);
Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email,
URI flagImageURI, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag);
}
@@ -1,80 +1,80 @@
package com.sap.sailing.domain.base;
import java.io.Serializable;
import java.net.URI;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
/**
* Manages a set of {@link Competitor} objects. There may be a transient implementation based on a simple cache,
* and there may be persistent implementations.
*
* @author Axel Uhl (d043530)
*
*/
public interface CompetitorStore extends CompetitorFactory {
public interface CompetitorUpdateListener {
void competitorUpdated(Competitor competitor);
}
/**
* If a valid competitor is returned and the caller has information available that could be used to update the competitor,
* the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if <code>true</code>,
* must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the
* competitor's values.
*/
Competitor getExistingCompetitorByIdAsString(String idAsString);
/**
* When a competitor is queried using {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)}
* , and the competitor object for that ID already exists, it is generally returned unchanged, and the name, team
* and boat parameters are not evaluated. This makes the data in this competitor store generally "write-once." This
* method can be used to reset a competitor object to what a tracking provider or an external system supplies to
* {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)}. After calling this method, the
* next call to {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} with
* <code>competitor</code>'s {@link Competitor#getId() ID} will
* {@link #updateCompetitor(String, String, String, Nationality)} the competitor in its updatable properties such as
* the name, the sail ID and the nationality.
*/
void allowCompetitorResetToDefaults(Competitor competitor);
int size();
/**
* Removes all competitors from this store. Use with due care.
*/
void clear();
/**
* Obtains a non-live snapshot of the list of competitors managed by this store.
*/
Iterable<? extends Competitor> getCompetitors();
void removeCompetitor(Competitor competitor);
/**
* Updates the competitor with {@link Competitor#getId() ID} <code>id</code> by setting the name, sail ID and nationality to
* the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas.
* The calling client has to make sure that the changes applied will reach replicas and all other interested clients. It will
* be sufficient to ensure that subsequent DTOs produced from the competitor modified will reflect the changes.<p>
*
* If no competitor with the ID requested is found, the call is a no-op, doing nothing, not even throwing an exception.
*/
Competitor updateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail,
String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri,
Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile);
CompetitorDTO convertToCompetitorDTO(Competitor c);
/**
* Listeners added here are notified whenever {@link #updateCompetitor(String, String, Color, String, Nationality)} is called
* for any competitor in this store.
*/
void addCompetitorUpdateListener(CompetitorUpdateListener listener);
void removeCompetitorUpdateListener(CompetitorUpdateListener listener);
}
package com.sap.sailing.domain.base;
import java.io.Serializable;
import java.net.URI;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
/**
* Manages a set of {@link Competitor} objects. There may be a transient implementation based on a simple cache,
* and there may be persistent implementations.
*
* @author Axel Uhl (d043530)
*
*/
public interface CompetitorStore extends CompetitorFactory {
public interface CompetitorUpdateListener {
void competitorUpdated(Competitor competitor);
}
/**
* If a valid competitor is returned and the caller has information available that could be used to update the competitor,
* the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if <code>true</code>,
* must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the
* competitor's values.
*/
Competitor getExistingCompetitorByIdAsString(String idAsString);
/**
* When a competitor is queried using {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)}
* , and the competitor object for that ID already exists, it is generally returned unchanged, and the name, team
* and boat parameters are not evaluated. This makes the data in this competitor store generally "write-once." This
* method can be used to reset a competitor object to what a tracking provider or an external system supplies to
* {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)}. After calling this method, the
* next call to {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} with
* <code>competitor</code>'s {@link Competitor#getId() ID} will
* {@link #updateCompetitor(String, String, String, Nationality)} the competitor in its updatable properties such as
* the name, the sail ID and the nationality.
*/
void allowCompetitorResetToDefaults(Competitor competitor);
int size();
/**
* Removes all competitors from this store. Use with due care.
*/
void clear();
/**
* Obtains a non-live snapshot of the list of competitors managed by this store.
*/
Iterable<? extends Competitor> getCompetitors();
void removeCompetitor(Competitor competitor);
/**
* Updates the competitor with {@link Competitor#getId() ID} <code>id</code> by setting the name, sail ID and nationality to
* the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas.
* The calling client has to make sure that the changes applied will reach replicas and all other interested clients. It will
* be sufficient to ensure that subsequent DTOs produced from the competitor modified will reflect the changes.<p>
*
* If no competitor with the ID requested is found, the call is a no-op, doing nothing, not even throwing an exception.
*/
Competitor updateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail,
String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri,
Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag);
CompetitorDTO convertToCompetitorDTO(Competitor c);
/**
* Listeners added here are notified whenever {@link #updateCompetitor(String, String, Color, String, Nationality)} is called
* for any competitor in this store.
*/
void addCompetitorUpdateListener(CompetitorUpdateListener listener);
void removeCompetitorUpdateListener(CompetitorUpdateListener listener);
}
@@ -20,6 +20,7 @@ public class CompetitorImpl implements DynamicCompetitor {
private final DynamicBoat boat;
private final Serializable id;
private String name;
private String searchTag;
private Color color;
private transient Set<CompetitorChangeListener> listeners;
private String email;
@@ -27,7 +28,7 @@ public class CompetitorImpl implements DynamicCompetitor {
private Double timeOnTimeFactor;
private Duration timeOnDistanceAllowancePerNauticalMile;
public CompetitorImpl(Serializable id, String name, Color color, String email, URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) {
public CompetitorImpl(Serializable id, String name, Color color, String email, URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) {
this.id = id;
this.name = name;
this.team = team;
@@ -37,6 +38,7 @@ public class CompetitorImpl implements DynamicCompetitor {
this.flagImage = flagImage;
this.timeOnTimeFactor = timeOnTimeFactor;
this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile;
this.searchTag = searchTag;
this.listeners = new HashSet<CompetitorChangeListener>();
}
@@ -85,10 +87,11 @@ public class CompetitorImpl implements DynamicCompetitor {
public Competitor resolve(SharedDomainFactory domainFactory) {
Competitor result = domainFactory
.getOrCreateCompetitor(getId(), getName(), getColor(), getEmail(), getFlagImage(), getTeam(),
getBoat(), getTimeOnTimeFactor(), getTimeOnDistanceAllowancePerNauticalMile());
getBoat(), getTimeOnTimeFactor(), getTimeOnDistanceAllowancePerNauticalMile(), searchTag);
return result;
}
@Override
public Color getColor() {
return color;
}
@@ -127,6 +130,22 @@ public class CompetitorImpl implements DynamicCompetitor {
}
}
@Override
public String getSearchTag() {
return searchTag;
}
public void setSearchTag(String newSearchTag) {
final String oldSearchTag = this.searchTag;
if (!Util.equalsWithNull(oldSearchTag, newSearchTag)) {
this.searchTag = newSearchTag;
for (CompetitorChangeListener listener : getListeners()) {
listener.searchTagChanged(oldSearchTag, newSearchTag);
}
}
}
@Override
public String getEmail() {
return email;
}
@@ -141,6 +160,7 @@ public class CompetitorImpl implements DynamicCompetitor {
}
}
@Override
public boolean hasEmail(){
return email != null && !email.isEmpty();
}
@@ -1,24 +1,26 @@
package com.sap.sailing.domain.base.impl;
import java.net.URI;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.Renamable;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
public interface DynamicCompetitor extends Competitor, Renamable {
DynamicBoat getBoat();
DynamicTeam getTeam();
void setColor(Color displayColor);
void setEmail(String email);
void setFlagImage(URI flagImage);
void setTimeOnTimeFactor(Double timeOnTimeFactor);
void setTimeOnDistanceAllowancePerNauticalMile(Duration timeOnDistanceAllowancePerNauticalMile);
}
package com.sap.sailing.domain.base.impl;
import java.net.URI;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.Renamable;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
public interface DynamicCompetitor extends Competitor, Renamable {
DynamicBoat getBoat();
DynamicTeam getTeam();
void setColor(Color displayColor);
void setEmail(String email);
void setSearchTag(String searchTag);
void setFlagImage(URI flagImage);
void setTimeOnTimeFactor(Double timeOnTimeFactor);
void setTimeOnDistanceAllowancePerNauticalMile(Duration timeOnDistanceAllowancePerNauticalMile);
}
@@ -1,379 +1,379 @@
package com.sap.sailing.domain.base.impl;
import java.io.Serializable;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.ControlPointWithTwoMarks;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherSingle;
import com.sap.sailing.domain.common.BoatClassMasterdata;
import com.sap.sailing.domain.common.MarkType;
import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
import com.sap.sse.common.WithID;
public class SharedDomainFactoryImpl implements SharedDomainFactory {
private static final Logger logger = Logger.getLogger(SharedDomainFactoryImpl.class.getName());
/**
* Ensure that the <em>same</em> string is used as key that is also used to set the {@link Nationality}
* object's {@link Nationality#getThreeLetterIOCAcronym() IOC code}.
*/
private final Map<String, Nationality> nationalityCache;
private final Map<Serializable, Mark> markCache;
private final Map<Serializable, ControlPointWithTwoMarks> controlPointWithTwoMarksCache;
/**
* For all marks ever created by this factory, the mark {@link WithID#getId() ID}'s string representation
* is mapped here to the actual ID. This allows clients to send only the string representation to the server
* and still be able to identify a mark uniquely this way.
*/
private final Map<String, Serializable> markIdCache;
/**
* For all ControlPoints ever created by this factory, the mark {@link WithID#getId() ID}'s string representation
* is mapped here to the actual ID. This allows clients to send only the string representation to the server
* and still be able to identify a ControlPoint uniquely this way.
*/
private final Map<String, Serializable> controlPointWithTwoMarksIdCache;
private final Map<String, BoatClass> boatClassCache;
protected final CompetitorStore competitorStore;
private final Map<Serializable, CourseArea> courseAreaCache;
/**
* Weakly references the waypoints. If a waypoint is no longer strongly referenced, the corresponding reference contained
* as value will have its referred object be <code>null</code>. In this case, the methods reading from this cache will purge
* the record and behave as if the record hadn't existed at the time of the read operation.
*/
private final ConcurrentHashMap<Serializable, WeakWaypointReference> waypointCache;
private final ReferenceQueue<Waypoint> waypointCacheReferenceQueue;
private final Map<Serializable, DeviceConfigurationMatcher> configurationMatcherCache;
/**
* Weak references to {@link Waypoint} objects of this type are registered with
* {@link DomainFactoryImpl#waypointCacheReferenceQueue} upon construction so that when their referents are no
* longer strongly referenced and the reference was nulled, they are entered into that queue.
* Methods managing the {@link #waypointCache} can poll the queue and then remove cache entries based on
* the {@link #id} stored in the reference.
*
* @author Axel Uhl (D043530)
*
*/
private class WeakWaypointReference extends WeakReference<Waypoint> {
private final Serializable id;
public WeakWaypointReference(Waypoint waypoint) {
super(waypoint, waypointCacheReferenceQueue);
this.id = waypoint.getId();
}
public void removeCacheEntry() {
waypointCache.remove(id);
}
}
/**
* Holds the canonicalized boat class names which are known to maybe start other than with an upwind leg.
* The boat class name used here is obtained by using {@link BoatClassMasterdata#unifyBoatClassName(String)}.
*/
private final Set<String> mayStartWithNoUpwindLeg;
private final RaceLogResolver raceLogResolver;
/**
* Uses a transient competitor store
*/
public SharedDomainFactoryImpl(RaceLogResolver raceLogResolver) {
this(new TransientCompetitorStoreImpl(), raceLogResolver);
}
public SharedDomainFactoryImpl(CompetitorStore competitorStore, RaceLogResolver raceLogResolver) {
this.raceLogResolver = raceLogResolver;
waypointCacheReferenceQueue = new ReferenceQueue<Waypoint>();
nationalityCache = new HashMap<String, Nationality>();
markCache = new HashMap<Serializable, Mark>();
markIdCache = new HashMap<String, Serializable>();
controlPointWithTwoMarksCache = new HashMap<Serializable, ControlPointWithTwoMarks>();
controlPointWithTwoMarksIdCache = new HashMap<String, Serializable>();
boatClassCache = new HashMap<String, BoatClass>();
this.competitorStore = competitorStore;
waypointCache = new ConcurrentHashMap<Serializable, WeakWaypointReference>();
// FIXME ass also bug 3347: mapping to lower case should rather work through a common unification / canonicalization of boat class names
mayStartWithNoUpwindLeg = Collections.singleton(BoatClassMasterdata.unifyBoatClassName(BoatClassMasterdata.EXTREME_40.getDisplayName()));
courseAreaCache = new HashMap<Serializable, CourseArea>();
configurationMatcherCache = new HashMap<Serializable, DeviceConfigurationMatcher>();
}
@Override
public Nationality getOrCreateNationality(String threeLetterIOCCode) {
if (threeLetterIOCCode == null) {
threeLetterIOCCode = " ";
}
synchronized (nationalityCache) {
Nationality result = nationalityCache.get(threeLetterIOCCode);
if (result == null) {
result = new NationalityImpl(threeLetterIOCCode);
nationalityCache.put(threeLetterIOCCode, result);
}
return result;
}
}
@Override
public Mark getOrCreateMark(String name) {
return getOrCreateMark(name, name);
}
@Override
public Mark getOrCreateMark(Serializable id, String name) {
return getOrCreateMark(id, name, null, null, null, null);
}
@Override
public Mark getOrCreateMark(String toStringRepresentationOfID, String name) {
return getOrCreateMark(toStringRepresentationOfID, name, null, null, null, null);
}
@Override
public Mark getOrCreateMark(Serializable id, String name, MarkType type, String color, String shape, String pattern) {
Mark result = markCache.get(id);
if (result == null) {
result = new MarkImpl(id, name, type, color, shape, pattern);
cacheMark(id, result);
}
return result;
}
@Override
public Mark getOrCreateMark(String toStringRepresentationOfID, String name, MarkType type,
String color, String shape, String pattern) {
Serializable id = toStringRepresentationOfID;
if (markIdCache.containsKey(toStringRepresentationOfID)) {
id = markIdCache.get(toStringRepresentationOfID);
}
return getOrCreateMark(id, name, type, color, shape, pattern);
}
@Override
public ControlPointWithTwoMarks getOrCreateControlPointWithTwoMarks(Serializable id, String name, Mark left, Mark right) {
final ControlPointWithTwoMarks result;
final ControlPointWithTwoMarks fromCache = controlPointWithTwoMarksCache.get(id);
if (fromCache != null) {
result = fromCache;
} else {
result = createControlPointWithTwoMarks(id, left, right, name);
}
return result;
}
@Override
public ControlPointWithTwoMarks getOrCreateControlPointWithTwoMarks(
String toStringRepresentationOfID, String name, Mark left, Mark right) {
Serializable id = toStringRepresentationOfID;
if (controlPointWithTwoMarksIdCache.containsKey(toStringRepresentationOfID)) {
id = controlPointWithTwoMarksIdCache.get(toStringRepresentationOfID);
}
return getOrCreateControlPointWithTwoMarks(id, name, left, right);
}
private void cacheMark(Serializable id, Mark result) {
markCache.put(id, result);
markIdCache.put(id.toString(), id);
}
@Override
public ControlPointWithTwoMarks createControlPointWithTwoMarks(Mark left, Mark right, String name) {
return createControlPointWithTwoMarks(name, left, right, name);
}
@Override
public ControlPointWithTwoMarks createControlPointWithTwoMarks(Serializable id, Mark left, Mark right, String name) {
ControlPointWithTwoMarks result = new ControlPointWithTwoMarksImpl(id, left, right, name);
controlPointWithTwoMarksCache.put(id, result);
controlPointWithTwoMarksIdCache.put(id.toString(), id);
return result;
}
@Override
public Waypoint createWaypoint(ControlPoint controlPoint, PassingInstruction passingInstruction) {
synchronized (waypointCache) {
expungeStaleWaypointCacheEntries();
Waypoint result = passingInstruction == null ?
new WaypointImpl(controlPoint) : new WaypointImpl(controlPoint, passingInstruction);
waypointCache.put(result.getId(), new WeakWaypointReference(result));
return result;
}
}
@Override
public Waypoint getExistingWaypointById(Waypoint waypointPrototype) {
synchronized (waypointCache) {
expungeStaleWaypointCacheEntries();
Waypoint result = null;
Reference<Waypoint> ref = waypointCache.get(waypointPrototype.getId());
if (ref != null) {
result = ref.get();
if (result == null) {
// waypoint was finalized; remove entry from cache
waypointCache.remove(waypointPrototype.getId());
}
}
return result;
}
}
@Override
public Waypoint getExistingWaypointByIdOrCache(Waypoint waypoint) {
synchronized (waypointCache) {
expungeStaleWaypointCacheEntries();
Waypoint result = null;
Reference<Waypoint> ref = waypointCache.get(waypoint.getId());
if (ref != null) {
result = ref.get();
if (result == null) {
// waypoint was finalized; remove entry from cache and add anew
result = waypoint;
waypointCache.put(waypoint.getId(), new WeakWaypointReference(waypoint));
} // else, result is the waypoint found in the cache; return it
} else {
// No entry found in the cache; not even a stale, finalized one. Create a new entry:
result = waypoint;
waypointCache.put(waypoint.getId(), new WeakWaypointReference(waypoint));
}
return result;
}
}
private void expungeStaleWaypointCacheEntries() {
Reference<? extends Waypoint> ref;
while ((ref=waypointCacheReferenceQueue.poll()) != null) {
((WeakWaypointReference) ref).removeCacheEntry();
}
}
@Override
public BoatClass getOrCreateBoatClass(String name, boolean typicallyStartsUpwind) {
final BoatClassMasterdata boatClassMasterdata = BoatClassMasterdata.resolveBoatClass(name);
final String unifiedBoatClassName = BoatClassMasterdata.unifyBoatClassNameBasedOnExistingMasterdata(name);
BoatClass result;
synchronized (boatClassCache) {
result = boatClassCache.get(unifiedBoatClassName);
if (result == null) {
if (unifiedBoatClassName != null && boatClassMasterdata != null) {
result = new BoatClassImpl(boatClassMasterdata.getDisplayName(), boatClassMasterdata);
} else {
result = new BoatClassImpl(unifiedBoatClassName, typicallyStartsUpwind);
}
boatClassCache.put(unifiedBoatClassName, result);
}
return result;
}
}
@Override
public BoatClass getOrCreateBoatClass(final String name) {
final String unifiedBoatClassName = BoatClassMasterdata.unifyBoatClassNameBasedOnExistingMasterdata(name);
return getOrCreateBoatClass(name, name == null || /* typicallyStartsUpwind */ !mayStartWithNoUpwindLeg.contains(unifiedBoatClassName));
}
@Override
public CourseArea getOrCreateCourseArea(UUID courseAreaId, String name) {
CourseArea result = getExistingCourseAreaById(courseAreaId);
if (result == null) {
result = new CourseAreaImpl(name, courseAreaId);
courseAreaCache.put(courseAreaId, result);
}
return result;
}
@Override
public CourseArea getExistingCourseAreaById(Serializable courseAreaId) {
return courseAreaCache.get(courseAreaId);
}
@Override
public CompetitorStore getCompetitorStore() {
return competitorStore;
}
@Override
public Competitor getExistingCompetitorById(Serializable competitorId) {
return getCompetitorStore().getExistingCompetitorById(competitorId);
}
@Override
public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result) {
return getCompetitorStore().isCompetitorToUpdateDuringGetOrCreate(result);
}
@Override
public Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email,
URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor,
Duration timeOnDistanceAllowancePerNauticalMile) {
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "getting or creating competitor "+name+" with ID "+competitorId+" in domain factory "+this);
}
return getCompetitorStore().getOrCreateCompetitor(competitorId, name, displayColor, email, flagImage, team,
boat, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile);
}
@Override
public DeviceConfigurationMatcher getOrCreateDeviceConfigurationMatcher(List<String> clientIdentifiers) {
DeviceConfigurationMatcher probe = createMatcher(clientIdentifiers);
DeviceConfigurationMatcher matcher = configurationMatcherCache.get(probe.getMatcherIdentifier());
if (matcher == null) {
configurationMatcherCache.put(probe.getMatcherIdentifier(), probe);
matcher = probe;
}
return matcher;
}
private DeviceConfigurationMatcher createMatcher(List<String> clientIdentifiers) {
return new DeviceConfigurationMatcherSingle(clientIdentifiers.get(0));
}
@Override
public Mark getExistingMarkById(Serializable id) {
return markCache.get(id);
}
@Override
public Mark getExistingMarkByIdAsString(String toStringRepresentationOfID) {
return markCache.get(markIdCache.get(toStringRepresentationOfID));
}
@Override
public RaceLogResolver getRaceLogResolver() {
return raceLogResolver;
}
}
package com.sap.sailing.domain.base.impl;
import java.io.Serializable;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.ControlPointWithTwoMarks;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher;
import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherSingle;
import com.sap.sailing.domain.common.BoatClassMasterdata;
import com.sap.sailing.domain.common.MarkType;
import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
import com.sap.sse.common.WithID;
public class SharedDomainFactoryImpl implements SharedDomainFactory {
private static final Logger logger = Logger.getLogger(SharedDomainFactoryImpl.class.getName());
/**
* Ensure that the <em>same</em> string is used as key that is also used to set the {@link Nationality}
* object's {@link Nationality#getThreeLetterIOCAcronym() IOC code}.
*/
private final Map<String, Nationality> nationalityCache;
private final Map<Serializable, Mark> markCache;
private final Map<Serializable, ControlPointWithTwoMarks> controlPointWithTwoMarksCache;
/**
* For all marks ever created by this factory, the mark {@link WithID#getId() ID}'s string representation
* is mapped here to the actual ID. This allows clients to send only the string representation to the server
* and still be able to identify a mark uniquely this way.
*/
private final Map<String, Serializable> markIdCache;
/**
* For all ControlPoints ever created by this factory, the mark {@link WithID#getId() ID}'s string representation
* is mapped here to the actual ID. This allows clients to send only the string representation to the server
* and still be able to identify a ControlPoint uniquely this way.
*/
private final Map<String, Serializable> controlPointWithTwoMarksIdCache;
private final Map<String, BoatClass> boatClassCache;
protected final CompetitorStore competitorStore;
private final Map<Serializable, CourseArea> courseAreaCache;
/**
* Weakly references the waypoints. If a waypoint is no longer strongly referenced, the corresponding reference contained
* as value will have its referred object be <code>null</code>. In this case, the methods reading from this cache will purge
* the record and behave as if the record hadn't existed at the time of the read operation.
*/
private final ConcurrentHashMap<Serializable, WeakWaypointReference> waypointCache;
private final ReferenceQueue<Waypoint> waypointCacheReferenceQueue;
private final Map<Serializable, DeviceConfigurationMatcher> configurationMatcherCache;
/**
* Weak references to {@link Waypoint} objects of this type are registered with
* {@link DomainFactoryImpl#waypointCacheReferenceQueue} upon construction so that when their referents are no
* longer strongly referenced and the reference was nulled, they are entered into that queue.
* Methods managing the {@link #waypointCache} can poll the queue and then remove cache entries based on
* the {@link #id} stored in the reference.
*
* @author Axel Uhl (D043530)
*
*/
private class WeakWaypointReference extends WeakReference<Waypoint> {
private final Serializable id;
public WeakWaypointReference(Waypoint waypoint) {
super(waypoint, waypointCacheReferenceQueue);
this.id = waypoint.getId();
}
public void removeCacheEntry() {
waypointCache.remove(id);
}
}
/**
* Holds the canonicalized boat class names which are known to maybe start other than with an upwind leg.
* The boat class name used here is obtained by using {@link BoatClassMasterdata#unifyBoatClassName(String)}.
*/
private final Set<String> mayStartWithNoUpwindLeg;
private final RaceLogResolver raceLogResolver;
/**
* Uses a transient competitor store
*/
public SharedDomainFactoryImpl(RaceLogResolver raceLogResolver) {
this(new TransientCompetitorStoreImpl(), raceLogResolver);
}
public SharedDomainFactoryImpl(CompetitorStore competitorStore, RaceLogResolver raceLogResolver) {
this.raceLogResolver = raceLogResolver;
waypointCacheReferenceQueue = new ReferenceQueue<Waypoint>();
nationalityCache = new HashMap<String, Nationality>();
markCache = new HashMap<Serializable, Mark>();
markIdCache = new HashMap<String, Serializable>();
controlPointWithTwoMarksCache = new HashMap<Serializable, ControlPointWithTwoMarks>();
controlPointWithTwoMarksIdCache = new HashMap<String, Serializable>();
boatClassCache = new HashMap<String, BoatClass>();
this.competitorStore = competitorStore;
waypointCache = new ConcurrentHashMap<Serializable, WeakWaypointReference>();
// FIXME ass also bug 3347: mapping to lower case should rather work through a common unification / canonicalization of boat class names
mayStartWithNoUpwindLeg = Collections.singleton(BoatClassMasterdata.unifyBoatClassName(BoatClassMasterdata.EXTREME_40.getDisplayName()));
courseAreaCache = new HashMap<Serializable, CourseArea>();
configurationMatcherCache = new HashMap<Serializable, DeviceConfigurationMatcher>();
}
@Override
public Nationality getOrCreateNationality(String threeLetterIOCCode) {
if (threeLetterIOCCode == null) {
threeLetterIOCCode = " ";
}
synchronized (nationalityCache) {
Nationality result = nationalityCache.get(threeLetterIOCCode);
if (result == null) {
result = new NationalityImpl(threeLetterIOCCode);
nationalityCache.put(threeLetterIOCCode, result);
}
return result;
}
}
@Override
public Mark getOrCreateMark(String name) {
return getOrCreateMark(name, name);
}
@Override
public Mark getOrCreateMark(Serializable id, String name) {
return getOrCreateMark(id, name, null, null, null, null);
}
@Override
public Mark getOrCreateMark(String toStringRepresentationOfID, String name) {
return getOrCreateMark(toStringRepresentationOfID, name, null, null, null, null);
}
@Override
public Mark getOrCreateMark(Serializable id, String name, MarkType type, String color, String shape, String pattern) {
Mark result = markCache.get(id);
if (result == null) {
result = new MarkImpl(id, name, type, color, shape, pattern);
cacheMark(id, result);
}
return result;
}
@Override
public Mark getOrCreateMark(String toStringRepresentationOfID, String name, MarkType type,
String color, String shape, String pattern) {
Serializable id = toStringRepresentationOfID;
if (markIdCache.containsKey(toStringRepresentationOfID)) {
id = markIdCache.get(toStringRepresentationOfID);
}
return getOrCreateMark(id, name, type, color, shape, pattern);
}
@Override
public ControlPointWithTwoMarks getOrCreateControlPointWithTwoMarks(Serializable id, String name, Mark left, Mark right) {
final ControlPointWithTwoMarks result;
final ControlPointWithTwoMarks fromCache = controlPointWithTwoMarksCache.get(id);
if (fromCache != null) {
result = fromCache;
} else {
result = createControlPointWithTwoMarks(id, left, right, name);
}
return result;
}
@Override
public ControlPointWithTwoMarks getOrCreateControlPointWithTwoMarks(
String toStringRepresentationOfID, String name, Mark left, Mark right) {
Serializable id = toStringRepresentationOfID;
if (controlPointWithTwoMarksIdCache.containsKey(toStringRepresentationOfID)) {
id = controlPointWithTwoMarksIdCache.get(toStringRepresentationOfID);
}
return getOrCreateControlPointWithTwoMarks(id, name, left, right);
}
private void cacheMark(Serializable id, Mark result) {
markCache.put(id, result);
markIdCache.put(id.toString(), id);
}
@Override
public ControlPointWithTwoMarks createControlPointWithTwoMarks(Mark left, Mark right, String name) {
return createControlPointWithTwoMarks(name, left, right, name);
}
@Override
public ControlPointWithTwoMarks createControlPointWithTwoMarks(Serializable id, Mark left, Mark right, String name) {
ControlPointWithTwoMarks result = new ControlPointWithTwoMarksImpl(id, left, right, name);
controlPointWithTwoMarksCache.put(id, result);
controlPointWithTwoMarksIdCache.put(id.toString(), id);
return result;
}
@Override
public Waypoint createWaypoint(ControlPoint controlPoint, PassingInstruction passingInstruction) {
synchronized (waypointCache) {
expungeStaleWaypointCacheEntries();
Waypoint result = passingInstruction == null ?
new WaypointImpl(controlPoint) : new WaypointImpl(controlPoint, passingInstruction);
waypointCache.put(result.getId(), new WeakWaypointReference(result));
return result;
}
}
@Override
public Waypoint getExistingWaypointById(Waypoint waypointPrototype) {
synchronized (waypointCache) {
expungeStaleWaypointCacheEntries();
Waypoint result = null;
Reference<Waypoint> ref = waypointCache.get(waypointPrototype.getId());
if (ref != null) {
result = ref.get();
if (result == null) {
// waypoint was finalized; remove entry from cache
waypointCache.remove(waypointPrototype.getId());
}
}
return result;
}
}
@Override
public Waypoint getExistingWaypointByIdOrCache(Waypoint waypoint) {
synchronized (waypointCache) {
expungeStaleWaypointCacheEntries();
Waypoint result = null;
Reference<Waypoint> ref = waypointCache.get(waypoint.getId());
if (ref != null) {
result = ref.get();
if (result == null) {
// waypoint was finalized; remove entry from cache and add anew
result = waypoint;
waypointCache.put(waypoint.getId(), new WeakWaypointReference(waypoint));
} // else, result is the waypoint found in the cache; return it
} else {
// No entry found in the cache; not even a stale, finalized one. Create a new entry:
result = waypoint;
waypointCache.put(waypoint.getId(), new WeakWaypointReference(waypoint));
}
return result;
}
}
private void expungeStaleWaypointCacheEntries() {
Reference<? extends Waypoint> ref;
while ((ref=waypointCacheReferenceQueue.poll()) != null) {
((WeakWaypointReference) ref).removeCacheEntry();
}
}
@Override
public BoatClass getOrCreateBoatClass(String name, boolean typicallyStartsUpwind) {
final BoatClassMasterdata boatClassMasterdata = BoatClassMasterdata.resolveBoatClass(name);
final String unifiedBoatClassName = BoatClassMasterdata.unifyBoatClassNameBasedOnExistingMasterdata(name);
BoatClass result;
synchronized (boatClassCache) {
result = boatClassCache.get(unifiedBoatClassName);
if (result == null) {
if (unifiedBoatClassName != null && boatClassMasterdata != null) {
result = new BoatClassImpl(boatClassMasterdata.getDisplayName(), boatClassMasterdata);
} else {
result = new BoatClassImpl(unifiedBoatClassName, typicallyStartsUpwind);
}
boatClassCache.put(unifiedBoatClassName, result);
}
return result;
}
}
@Override
public BoatClass getOrCreateBoatClass(final String name) {
final String unifiedBoatClassName = BoatClassMasterdata.unifyBoatClassNameBasedOnExistingMasterdata(name);
return getOrCreateBoatClass(name, name == null || /* typicallyStartsUpwind */ !mayStartWithNoUpwindLeg.contains(unifiedBoatClassName));
}
@Override
public CourseArea getOrCreateCourseArea(UUID courseAreaId, String name) {
CourseArea result = getExistingCourseAreaById(courseAreaId);
if (result == null) {
result = new CourseAreaImpl(name, courseAreaId);
courseAreaCache.put(courseAreaId, result);
}
return result;
}
@Override
public CourseArea getExistingCourseAreaById(Serializable courseAreaId) {
return courseAreaCache.get(courseAreaId);
}
@Override
public CompetitorStore getCompetitorStore() {
return competitorStore;
}
@Override
public Competitor getExistingCompetitorById(Serializable competitorId) {
return getCompetitorStore().getExistingCompetitorById(competitorId);
}
@Override
public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result) {
return getCompetitorStore().isCompetitorToUpdateDuringGetOrCreate(result);
}
@Override
public Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email,
URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor,
Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) {
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "getting or creating competitor "+name+" with ID "+competitorId+" in domain factory "+this);
}
return getCompetitorStore().getOrCreateCompetitor(competitorId, name, displayColor, email, flagImage, team,
boat, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag);
}
@Override
public DeviceConfigurationMatcher getOrCreateDeviceConfigurationMatcher(List<String> clientIdentifiers) {
DeviceConfigurationMatcher probe = createMatcher(clientIdentifiers);
DeviceConfigurationMatcher matcher = configurationMatcherCache.get(probe.getMatcherIdentifier());
if (matcher == null) {
configurationMatcherCache.put(probe.getMatcherIdentifier(), probe);
matcher = probe;
}
return matcher;
}
private DeviceConfigurationMatcher createMatcher(List<String> clientIdentifiers) {
return new DeviceConfigurationMatcherSingle(clientIdentifiers.get(0));
}
@Override
public Mark getExistingMarkById(Serializable id) {
return markCache.get(id);
}
@Override
public Mark getExistingMarkByIdAsString(String toStringRepresentationOfID) {
return markCache.get(markIdCache.get(toStringRepresentationOfID));
}
@Override
public RaceLogResolver getRaceLogResolver() {
return raceLogResolver;
}
}
@@ -1,276 +1,277 @@
package com.sap.sailing.domain.base.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.common.dto.BoatClassDTO;
import com.sap.sailing.domain.common.dto.BoatDTO;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.domain.common.dto.CompetitorDTOImpl;
import com.sap.sse.common.Color;
import com.sap.sse.common.CountryCode;
import com.sap.sse.common.Duration;
import com.sap.sse.concurrent.LockUtil;
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
public class TransientCompetitorStoreImpl implements CompetitorStore, Serializable {
private static final Logger logger = Logger.getLogger(TransientCompetitorStoreImpl.class.getName());
private static final long serialVersionUID = -4198298775476586931L;
private final Map<Serializable, Competitor> competitorCache;
private final Map<String, Competitor> competitorsByIdAsString;
private transient Set<CompetitorUpdateListener> listeners;
/**
* The competitors contained in this map will have their changeable properties
* {@link #updateCompetitor(String, String, String, Nationality) updated} upon the next call to
* {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} for their ID.
*/
private final Set<Competitor> competitorsToUpdateDuringGetOrCreate;
private transient WeakHashMap<Competitor, CompetitorDTO> weakCompetitorDTOCache;
private final NamedReentrantReadWriteLock lock;
public TransientCompetitorStoreImpl() {
lock = new NamedReentrantReadWriteLock("CompetitorStore", /* fair */ false);
competitorCache = new HashMap<Serializable, Competitor>();
competitorsByIdAsString = new HashMap<String, Competitor>();
competitorsToUpdateDuringGetOrCreate = new HashSet<Competitor>();
weakCompetitorDTOCache = new WeakHashMap<Competitor, CompetitorDTO>();
listeners = Collections.synchronizedSet(new HashSet<CompetitorStore.CompetitorUpdateListener>());
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
weakCompetitorDTOCache = new WeakHashMap<Competitor, CompetitorDTO>();
listeners = Collections.synchronizedSet(new HashSet<CompetitorStore.CompetitorUpdateListener>());
}
@Override
public void addCompetitorUpdateListener(CompetitorUpdateListener listener) {
listeners.add(listener);
}
@Override
public void removeCompetitorUpdateListener(CompetitorUpdateListener listener) {
listeners.remove(listener);
}
private Competitor createCompetitor(Serializable id, String name, Color displayColor, String email, URI flagImage,
DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) {
Competitor result = new CompetitorImpl(id, name, displayColor, email, flagImage, team, boat,
timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile);
addNewCompetitor(id, result);
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "Created competitor "+name+" with ID "+id, new Exception("Here is where it happened"));
}
return result;
}
/**
* Adds the <code>competitor</code> to this transient competitor collection so that it is available in
* {@link #getExistingCompetitorById(Serializable)}. Subclasses may override in case they need to take additional
* measures such as durably storing the competitor. Overriding implementations must call this implementation.
*/
protected void addNewCompetitor(Serializable id, Competitor competitor) {
LockUtil.lockForWrite(lock);
try {
competitorCache.put(id, competitor);
competitorsByIdAsString.put(id.toString(), competitor);
} finally {
LockUtil.unlockAfterWrite(lock);
}
}
@Override
public Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email,
URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor,
Duration timeOnDistanceAllowancePerNauticalMile) {
Competitor result = getExistingCompetitorById(competitorId); // avoid synchronization for successful read access
if (result == null) {
LockUtil.lockForWrite(lock);
try {
result = getExistingCompetitorById(competitorId); // try again, now while holding the write lock
if (result == null) {
result = createCompetitor(competitorId, name, displayColor, email, flagImage, team, boat,
timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile);
}
} finally {
LockUtil.unlockAfterWrite(lock);
}
} else if (isCompetitorToUpdateDuringGetOrCreate(result)) {
updateCompetitor(result.getId().toString(), name, displayColor, email, boat.getSailID(), team.getNationality(),
team.getImage(), flagImage, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile);
competitorNoLongerToUpdateDuringGetOrCreate(result);
}
return result;
}
private void competitorNoLongerToUpdateDuringGetOrCreate(Competitor result) {
competitorsToUpdateDuringGetOrCreate.remove(result);
}
@Override
public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result) {
return competitorsToUpdateDuringGetOrCreate.contains(result);
}
@Override
public Competitor getExistingCompetitorById(Serializable competitorId) {
LockUtil.lockForRead(lock);
try {
return competitorCache.get(competitorId);
} finally {
LockUtil.unlockAfterRead(lock);
}
}
@Override
public Competitor getExistingCompetitorByIdAsString(String competitorIdAsString) {
LockUtil.lockForRead(lock);
try {
return competitorsByIdAsString.get(competitorIdAsString);
} finally {
LockUtil.unlockAfterRead(lock);
}
}
@Override
public int size() {
LockUtil.lockForRead(lock);
try {
return competitorCache.size();
} finally {
LockUtil.unlockAfterRead(lock);
}
}
@Override
public void clear() {
LockUtil.lockForWrite(lock);
try {
competitorCache.clear();
competitorsByIdAsString.clear();
competitorsToUpdateDuringGetOrCreate.clear();
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "Clearing competitor store "+this, new Exception("here is where it happened"));
}
} finally {
LockUtil.unlockAfterWrite(lock);
}
}
@Override
public Iterable<Competitor> getCompetitors() {
LockUtil.lockForRead(lock);
try {
return new ArrayList<Competitor>(competitorCache.values());
} finally {
LockUtil.unlockAfterRead(lock);
}
}
@Override
public void removeCompetitor(Competitor competitor) {
LockUtil.lockForWrite(lock);
try {
logger.fine("removing competitor "+competitor+" from competitor store "+this);
competitorCache.remove(competitor.getId());
competitorsByIdAsString.remove(competitor.getId().toString());
weakCompetitorDTOCache.remove(competitor);
} finally {
LockUtil.unlockAfterWrite(lock);
}
}
@Override
public Competitor updateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail,
String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri,
Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) {
DynamicCompetitor competitor = (DynamicCompetitor) getExistingCompetitorByIdAsString(idAsString);
if (competitor != null) {
LockUtil.lockForWrite(lock);
try {
competitor.setName(newName);
competitor.setColor(newDisplayColor);
competitor.setEmail(newEmail);
competitor.setFlagImage(newFlagImageUri);
competitor.getBoat().setSailId(newSailId);
competitor.getTeam().setNationality(newNationality);
competitor.getTeam().setImage(newTeamImageUri);
competitor.setTimeOnTimeFactor(timeOnTimeFactor);
competitor.setTimeOnDistanceAllowancePerNauticalMile(timeOnDistanceAllowancePerNauticalMile);
weakCompetitorDTOCache.remove(competitor);
} finally {
LockUtil.unlockAfterWrite(lock);
}
}
synchronized (listeners) {
for (CompetitorUpdateListener listener : listeners) {
listener.competitorUpdated(competitor);
}
}
return competitor;
}
@Override
public CompetitorDTO convertToCompetitorDTO(Competitor c) {
LockUtil.lockForRead(lock);
boolean needToUnlockReadLock = true;
try {
CompetitorDTO competitorDTO = weakCompetitorDTOCache.get(c);
if (competitorDTO == null) {
LockUtil.unlockAfterRead(lock);
needToUnlockReadLock = false;
LockUtil.lockForWrite(lock);
competitorDTO = weakCompetitorDTOCache.get(c);
if (competitorDTO == null) {
final Nationality nationality = c.getTeam().getNationality();
CountryCode countryCode = nationality == null ? null : nationality.getCountryCode();
competitorDTO = new CompetitorDTOImpl(c.getName(), c.getColor(), c.getEmail(), countryCode == null ? ""
: countryCode.getTwoLetterISOCode(), countryCode == null ? ""
: countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(),
c.getId().toString(),
c.getTeam().getImage() == null ? null : c.getTeam().getImage().toString(),
c.getFlagImage() == null ? null : c.getFlagImage().toString(),
new BoatDTO(c.getBoat().getName(), c.getBoat().getSailID(), c.getBoat().getColor()),
new BoatClassDTO(c.getBoat().getBoatClass()
.getName(), c.getBoat().getBoatClass().getDisplayName(), c.getBoat().getBoatClass().getHullLength().getMeters()),
c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile());
weakCompetitorDTOCache.put(c, competitorDTO);
}
}
return competitorDTO;
} finally {
if (needToUnlockReadLock) {
LockUtil.unlockAfterRead(lock);
} else {
LockUtil.unlockAfterWrite(lock);
}
}
}
@Override
public void allowCompetitorResetToDefaults(Competitor competitor) {
LockUtil.lockForWrite(lock);
try {
competitorsToUpdateDuringGetOrCreate.add(competitor);
} finally {
LockUtil.unlockAfterWrite(lock);
}
}
}
package com.sap.sailing.domain.base.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.common.dto.BoatClassDTO;
import com.sap.sailing.domain.common.dto.BoatDTO;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.domain.common.dto.CompetitorDTOImpl;
import com.sap.sse.common.Color;
import com.sap.sse.common.CountryCode;
import com.sap.sse.common.Duration;
import com.sap.sse.concurrent.LockUtil;
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
public class TransientCompetitorStoreImpl implements CompetitorStore, Serializable {
private static final Logger logger = Logger.getLogger(TransientCompetitorStoreImpl.class.getName());
private static final long serialVersionUID = -4198298775476586931L;
private final Map<Serializable, Competitor> competitorCache;
private final Map<String, Competitor> competitorsByIdAsString;
private transient Set<CompetitorUpdateListener> listeners;
/**
* The competitors contained in this map will have their changeable properties
* {@link #updateCompetitor(String, String, String, Nationality) updated} upon the next call to
* {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} for their ID.
*/
private final Set<Competitor> competitorsToUpdateDuringGetOrCreate;
private transient WeakHashMap<Competitor, CompetitorDTO> weakCompetitorDTOCache;
private final NamedReentrantReadWriteLock lock;
public TransientCompetitorStoreImpl() {
lock = new NamedReentrantReadWriteLock("CompetitorStore", /* fair */ false);
competitorCache = new HashMap<Serializable, Competitor>();
competitorsByIdAsString = new HashMap<String, Competitor>();
competitorsToUpdateDuringGetOrCreate = new HashSet<Competitor>();
weakCompetitorDTOCache = new WeakHashMap<Competitor, CompetitorDTO>();
listeners = Collections.synchronizedSet(new HashSet<CompetitorStore.CompetitorUpdateListener>());
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
weakCompetitorDTOCache = new WeakHashMap<Competitor, CompetitorDTO>();
listeners = Collections.synchronizedSet(new HashSet<CompetitorStore.CompetitorUpdateListener>());
}
@Override
public void addCompetitorUpdateListener(CompetitorUpdateListener listener) {
listeners.add(listener);
}
@Override
public void removeCompetitorUpdateListener(CompetitorUpdateListener listener) {
listeners.remove(listener);
}
private Competitor createCompetitor(Serializable id, String name, Color displayColor, String email, URI flagImage,
DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) {
Competitor result = new CompetitorImpl(id, name, displayColor, email, flagImage, team, boat,
timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag);
addNewCompetitor(id, result);
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "Created competitor "+name+" with ID "+id, new Exception("Here is where it happened"));
}
return result;
}
/**
* Adds the <code>competitor</code> to this transient competitor collection so that it is available in
* {@link #getExistingCompetitorById(Serializable)}. Subclasses may override in case they need to take additional
* measures such as durably storing the competitor. Overriding implementations must call this implementation.
*/
protected void addNewCompetitor(Serializable id, Competitor competitor) {
LockUtil.lockForWrite(lock);
try {
competitorCache.put(id, competitor);
competitorsByIdAsString.put(id.toString(), competitor);
} finally {
LockUtil.unlockAfterWrite(lock);
}
}
@Override
public Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email,
URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor,
Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) {
Competitor result = getExistingCompetitorById(competitorId); // avoid synchronization for successful read access
if (result == null) {
LockUtil.lockForWrite(lock);
try {
result = getExistingCompetitorById(competitorId); // try again, now while holding the write lock
if (result == null) {
result = createCompetitor(competitorId, name, displayColor, email, flagImage, team, boat,
timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag);
}
} finally {
LockUtil.unlockAfterWrite(lock);
}
} else if (isCompetitorToUpdateDuringGetOrCreate(result)) {
updateCompetitor(result.getId().toString(), name, displayColor, email, boat.getSailID(), team.getNationality(),
team.getImage(), flagImage, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag);
competitorNoLongerToUpdateDuringGetOrCreate(result);
}
return result;
}
private void competitorNoLongerToUpdateDuringGetOrCreate(Competitor result) {
competitorsToUpdateDuringGetOrCreate.remove(result);
}
@Override
public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result) {
return competitorsToUpdateDuringGetOrCreate.contains(result);
}
@Override
public Competitor getExistingCompetitorById(Serializable competitorId) {
LockUtil.lockForRead(lock);
try {
return competitorCache.get(competitorId);
} finally {
LockUtil.unlockAfterRead(lock);
}
}
@Override
public Competitor getExistingCompetitorByIdAsString(String competitorIdAsString) {
LockUtil.lockForRead(lock);
try {
return competitorsByIdAsString.get(competitorIdAsString);
} finally {
LockUtil.unlockAfterRead(lock);
}
}
@Override
public int size() {
LockUtil.lockForRead(lock);
try {
return competitorCache.size();
} finally {
LockUtil.unlockAfterRead(lock);
}
}
@Override
public void clear() {
LockUtil.lockForWrite(lock);
try {
competitorCache.clear();
competitorsByIdAsString.clear();
competitorsToUpdateDuringGetOrCreate.clear();
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "Clearing competitor store "+this, new Exception("here is where it happened"));
}
} finally {
LockUtil.unlockAfterWrite(lock);
}
}
@Override
public Iterable<Competitor> getCompetitors() {
LockUtil.lockForRead(lock);
try {
return new ArrayList<Competitor>(competitorCache.values());
} finally {
LockUtil.unlockAfterRead(lock);
}
}
@Override
public void removeCompetitor(Competitor competitor) {
LockUtil.lockForWrite(lock);
try {
logger.fine("removing competitor "+competitor+" from competitor store "+this);
competitorCache.remove(competitor.getId());
competitorsByIdAsString.remove(competitor.getId().toString());
weakCompetitorDTOCache.remove(competitor);
} finally {
LockUtil.unlockAfterWrite(lock);
}
}
@Override
public Competitor updateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail,
String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri,
Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String newSearchTag) {
DynamicCompetitor competitor = (DynamicCompetitor) getExistingCompetitorByIdAsString(idAsString);
if (competitor != null) {
LockUtil.lockForWrite(lock);
try {
competitor.setName(newName);
competitor.setColor(newDisplayColor);
competitor.setEmail(newEmail);
competitor.setFlagImage(newFlagImageUri);
competitor.getBoat().setSailId(newSailId);
competitor.getTeam().setNationality(newNationality);
competitor.getTeam().setImage(newTeamImageUri);
competitor.setTimeOnTimeFactor(timeOnTimeFactor);
competitor.setTimeOnDistanceAllowancePerNauticalMile(timeOnDistanceAllowancePerNauticalMile);
competitor.setSearchTag(newSearchTag);
weakCompetitorDTOCache.remove(competitor);
} finally {
LockUtil.unlockAfterWrite(lock);
}
}
synchronized (listeners) {
for (CompetitorUpdateListener listener : listeners) {
listener.competitorUpdated(competitor);
}
}
return competitor;
}
@Override
public CompetitorDTO convertToCompetitorDTO(Competitor c) {
LockUtil.lockForRead(lock);
boolean needToUnlockReadLock = true;
try {
CompetitorDTO competitorDTO = weakCompetitorDTOCache.get(c);
if (competitorDTO == null) {
LockUtil.unlockAfterRead(lock);
needToUnlockReadLock = false;
LockUtil.lockForWrite(lock);
competitorDTO = weakCompetitorDTOCache.get(c);
if (competitorDTO == null) {
final Nationality nationality = c.getTeam().getNationality();
CountryCode countryCode = nationality == null ? null : nationality.getCountryCode();
competitorDTO = new CompetitorDTOImpl(c.getName(), c.getColor(), c.getEmail(), countryCode == null ? ""
: countryCode.getTwoLetterISOCode(), countryCode == null ? ""
: countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(),
c.getId().toString(),
c.getTeam().getImage() == null ? null : c.getTeam().getImage().toString(),
c.getFlagImage() == null ? null : c.getFlagImage().toString(),
new BoatDTO(c.getBoat().getName(), c.getBoat().getSailID(), c.getBoat().getColor()),
new BoatClassDTO(c.getBoat().getBoatClass()
.getName(), c.getBoat().getBoatClass().getDisplayName(), c.getBoat().getBoatClass().getHullLength().getMeters()),
c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag());
weakCompetitorDTOCache.put(c, competitorDTO);
}
}
return competitorDTO;
} finally {
if (needToUnlockReadLock) {
LockUtil.unlockAfterRead(lock);
} else {
LockUtil.unlockAfterWrite(lock);
}
}
}
@Override
public void allowCompetitorResetToDefaults(Competitor competitor) {
LockUtil.lockForWrite(lock);
try {
competitorsToUpdateDuringGetOrCreate.add(competitor);
} finally {
LockUtil.unlockAfterWrite(lock);
}
}
}
@@ -126,7 +126,7 @@ public class DomainFactoryImpl implements DomainFactory {
}
DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null);
result = competitorStore.getOrCreateCompetitor(competitor.getID(), competitor.getName(), null /*displayColor*/, null /*email*/, null, team, boat,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
}
return result;
}
@@ -143,7 +143,7 @@ public class DomainFactoryImpl implements DomainFactory {
DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null);
result = baseDomainFactory.getCompetitorStore().getOrCreateCompetitor(getCompetitorID(competitor.getBoatID(), raceId, boatClass),
competitor.getName(), null /*displayColor*/, null /*email*/, null, team, boat,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
return result;
}
@@ -1,372 +1,372 @@
package com.sap.sailing.domain.common.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.common.dto.BoatClassDTO;
import com.sap.sailing.domain.common.dto.BoatDTO;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.domain.common.dto.CompetitorDTOImpl;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.IncrementalLeaderboardDTO;
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
import com.sap.sailing.domain.common.dto.LeaderboardEntryDTO;
import com.sap.sailing.domain.common.dto.LeaderboardRowDTO;
import com.sap.sailing.domain.common.dto.LegEntryDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.domain.common.dto.RaceDTO;
import com.sap.sailing.domain.test.StoredTrackBasedTest;
import com.sap.sse.common.Cloner;
import com.sap.sse.common.Color;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.util.ClonerImpl;
/**
* Tests the compressing / de-compressing functionality of {@link LeaderboardDTO} and {@link IncrementalLeaderboardDTO}.
* See also bug 1417.<p>
*
* The data of a meaningful and non-trivial {@link LeaderboardDTO} is obtained by using an instrumented version of
* <code>SailingServiceImpl.getLeaderboardByName(...)</code> which serializes the leaderboard at the end of the method
* to a file used by this test. The leaderboard that this test wants to use is that of the 505 Worlds 2013, obtained
* for an expanded Race R9 at time 2013-05-03T17:21:40Z.
*
* @author Axel Uhl (d043530)
*
*/
public class LeaderboardDTODiffingTest {
private LeaderboardDTO previousVersion;
private IncrementalLeaderboardDTO newVersion;
private final Cloner cloner = new ClonerImpl();
@Before
public void setUp() throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream ois = StoredTrackBasedTest.getObjectInputStream("IncrementalLeaderboardDTO.ser");
previousVersion = (LeaderboardDTO) ois.readObject();
ois.close();
newVersion = new IncrementalLeaderboardDTO("12345", cloner);
cloner.clone(previousVersion, newVersion);
}
private CompetitorDTO getPreviousCompetitorByName(String name) {
for (CompetitorDTO competitor : previousVersion.competitors) {
if (competitor.getName().equals(name)) {
return competitor;
}
}
return null;
}
@Test
public void testEmptyLegDetailsGetFilled() throws FileNotFoundException, IOException, ClassNotFoundException {
// remove legDetails for R9 for all competitors from previousVersion; remember which ones did contain data
Set<CompetitorDTO> hadLegDetailsInR9 = new HashSet<>();
Map<CompetitorDTO, LeaderboardRowDTO> newRows = new HashMap<>();
for (CompetitorDTO competitor : previousVersion.rows.keySet()) {
LeaderboardRowDTO competitorRow = new LeaderboardRowDTO();
cloner.clone(newVersion.rows.get(competitor), competitorRow);
Map<String, LeaderboardEntryDTO> newFieldsByRaceColumnName = new HashMap<>();
for (Entry<String, LeaderboardEntryDTO> e : competitorRow.fieldsByRaceColumnName.entrySet()) {
LeaderboardEntryDTO newEntry = new LeaderboardEntryDTO();
cloner.clone(e.getValue(), newEntry);
newFieldsByRaceColumnName.put(e.getKey(), newEntry);
}
competitorRow.fieldsByRaceColumnName = newFieldsByRaceColumnName;
newRows.put(competitor, competitorRow); // use a copy of the row so we can null out legDetails for R9 in previousVersion only
LeaderboardRowDTO previousRow = previousVersion.rows.get(competitor);
assertNotSame(previousRow, competitorRow);
if (previousRow.fieldsByRaceColumnName.get("R9").legDetails != null) {
hadLegDetailsInR9.add(competitor);
previousRow.fieldsByRaceColumnName.get("R9").legDetails = null;
assertNotNull(competitorRow.fieldsByRaceColumnName.get("R9").legDetails != null);
}
}
newVersion.rows = newRows;
newVersion.strip(previousVersion); // should contain the leg details now
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
// now applied must contain the leg details
for (CompetitorDTO competitor : hadLegDetailsInR9) {
assertNotNull(applied.rows.get(competitor).fieldsByRaceColumnName.get("R9").legDetails);
}
}
@Test
public void testLeaderboardSuccessfullyRead() {
assertNotNull(previousVersion);
assertNotNull(newVersion);
}
@Test
public void testPreviousAndNewVersionHaveEqualRows() {
assertEquals(previousVersion.rows, newVersion.rows);
}
@Test
public void testTotalStripping() {
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertNull(newVersion.rows);
}
@Test
public void testMajorStripping() {
newVersion.rows = new HashMap<CompetitorDTO, LeaderboardRowDTO>(newVersion.rows);
List<RaceColumnDTO> raceListBeforeStripping = new ArrayList<RaceColumnDTO>(newVersion.getRaceList());
CompetitorDTO wolfgang = getPreviousCompetitorByName("HUNGER +JESS");
assertNotNull(wolfgang);
LeaderboardRowDTO wolfgangsRow = new LeaderboardRowDTO();
cloner.clone(newVersion.rows.get(wolfgang), wolfgangsRow);
newVersion.rows.put(wolfgang, wolfgangsRow);
wolfgangsRow.totalDistanceTraveledInMeters += 1;
Map<CompetitorDTO, LeaderboardRowDTO> rowsBeforeStripping = newVersion.rows;
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertNotNull(newVersion.rows);
assertEquals(1, newVersion.rows.size()); // only wolfgang's row should show
assertEquals(wolfgang, newVersion.rows.keySet().iterator().next().getCompetitorFromPrevious(previousVersion));
assertTrue(newVersion.rows.values().iterator().next().fieldsByRaceColumnName.isEmpty());
for (RaceColumnDTO nullRaceColumn : newVersion.getRaceList()) {
assertNull(nullRaceColumn); // there were no changes to the columns; expect all of them to have been eliminiated
}
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(rowsBeforeStripping, applied.rows);
assertNotSame(raceListBeforeStripping, applied.getRaceList());
assertEquals(raceListBeforeStripping, applied.getRaceList());
}
@Test
public void testStrippingExceptOneColumnInOneRace() {
HashMap<CompetitorDTO, LeaderboardRowDTO> newRows = new HashMap<CompetitorDTO, LeaderboardRowDTO>(newVersion.rows);
double newDistance = 1234;
String nameOfRaceColumnToChange = "R9";
int indexOfLegToChange = 7; // ( zero based: ) 8th leg is the last leg
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : newVersion.rows.entrySet()) {
LeaderboardRowDTO newRow = new LeaderboardRowDTO();
cloner.clone(e.getValue(), newRow);
newRows.put(e.getKey(), newRow);
newRow.fieldsByRaceColumnName = new HashMap<String, LeaderboardEntryDTO>(newRow.fieldsByRaceColumnName); // clone entry map
LeaderboardEntryDTO newEntry = new LeaderboardEntryDTO();
cloner.clone(newRow.fieldsByRaceColumnName.get(nameOfRaceColumnToChange), newEntry);
newRow.fieldsByRaceColumnName.put(nameOfRaceColumnToChange, newEntry);
if (newEntry.legDetails != null) {
newEntry.legDetails = new ArrayList<LegEntryDTO>(newEntry.legDetails); // clone leg details list
if (newEntry.legDetails.get(indexOfLegToChange) != null) {
LegEntryDTO newLegDetail = new LegEntryDTO();
cloner.clone(newEntry.legDetails.get(indexOfLegToChange), newLegDetail);
newEntry.legDetails.set(indexOfLegToChange, newLegDetail);
newLegDetail.distanceTraveledInMeters = newDistance;
newDistance += 1;
}
}
}
newVersion.rows = newRows;
Map<CompetitorDTO, LeaderboardRowDTO> rowsBeforeStripping = newVersion.rows;
Map<com.sap.sse.common.Util.Pair<CompetitorDTO, String>, List<LegEntryDTO>> previousLegDetailsBeforeStripping = new HashMap<>();
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : rowsBeforeStripping.entrySet()) {
for (Map.Entry<String, LeaderboardEntryDTO> e2 : e.getValue().fieldsByRaceColumnName.entrySet()) {
if (e2.getValue().legDetails != null) {
previousLegDetailsBeforeStripping.put(new com.sap.sse.common.Util.Pair<CompetitorDTO, String>(e.getKey(), e2.getKey()),
new ArrayList<>(e2.getValue().legDetails));
}
}
}
newVersion.strip(previousVersion);
// see bug 1455; check that the stripping doesn't kill the previous leaderboard's legDetails lists
for (Map.Entry<com.sap.sse.common.Util.Pair<CompetitorDTO, String>, List<LegEntryDTO>> e : previousLegDetailsBeforeStripping.entrySet()) {
final LeaderboardRowDTO leaderboardRowDTO = rowsBeforeStripping.get(e.getKey().getA());
if (leaderboardRowDTO != null) {
List<LegEntryDTO> newLegDetails = leaderboardRowDTO.fieldsByRaceColumnName.get(e.getKey().getB()).legDetails;
assertEquals(e.getValue(), newLegDetails);
}
}
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertNotNull(newVersion.rows);
assertEquals(previousVersion.rows.size()-17, newVersion.rows.size()); // all rows have changed except for 17 that have no leg details in leg 8
// now assert that for all rows there is no leaderboard entry for all races but R9 and
// for R9 there either are no leg details or all leg details for all legs other than L8 are null
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : newVersion.rows.entrySet()) {
if (e.getValue().fieldsByRaceColumnName != null) {
assertTrue(e.getValue().fieldsByRaceColumnName.size() <= 1);
for (Map.Entry<String, LeaderboardEntryDTO> e2 : e.getValue().fieldsByRaceColumnName.entrySet()) {
if (e2.getKey().equals(nameOfRaceColumnToChange)) {
List<LegEntryDTO> r9LegDetails = e2.getValue().legDetails;
if (r9LegDetails != null) {
for (int i=0; i<r9LegDetails.size(); i++) {
if (i != indexOfLegToChange) {
assertNull(r9LegDetails.get(i));
} else {
assertNotNull(r9LegDetails.get(i));
}
}
}
} else {
// if there is an entry for any column other than R9 (which is not really expected) then the entry is expected to be null
assertNull(e2.getValue());
}
}
}
}
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(rowsBeforeStripping, applied.rows);
}
@Test
public void testCompetitorListChange() {
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
/* timeOnDistanceAllowancePerNauticalMile */ null);
newVersion.competitors.add(13, somebodyNew); // insert a competitor; this should mess up all others' indexes; check if this works
CompetitorDTO wolfgang = getPreviousCompetitorByName("HUNGER +JESS");
newVersion.competitors.remove(wolfgang);
newVersion.rows.remove(wolfgang); // remove another competitor
List<CompetitorDTO> newCompetitorsBeforeStripping = new ArrayList<CompetitorDTO>(newVersion.competitors);
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertNull(newVersion.competitors); // but there should be an added competitor that we can't see through the public interface
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(newCompetitorsBeforeStripping, applied.competitors);
}
@Test
public void testSuppressionChange() {
final List<CompetitorDTO> newSuppressedCompetitors = new ArrayList<CompetitorDTO>();
Util.addAll(newVersion.getSuppressedCompetitors(), newSuppressedCompetitors);
newVersion.setSuppressedCompetitors(newSuppressedCompetitors);
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
/* timeOnDistanceAllowancePerNauticalMile */ null);
newVersion.setSuppressed(newVersion.competitors.get(13), true); // suppress an existing competitor; compaction should reduce this to a single number only
newVersion.setSuppressed(somebodyNew, true); // check that mixed mode with existing and new competitors works as well
List<CompetitorDTO> newSuppressedCompetitorsBeforeStripping = new ArrayList<CompetitorDTO>();
Util.addAll(newVersion.getSuppressedCompetitors(), newSuppressedCompetitorsBeforeStripping);
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertEquals(2, Util.size(newVersion.getSuppressedCompetitors()));
assertTrue(Util.contains(newVersion.getSuppressedCompetitors(), somebodyNew));
for (CompetitorDTO compactSuppressedCompetitor : newVersion.getSuppressedCompetitors()) {
if (compactSuppressedCompetitor != somebodyNew) {
assertFalse(compactSuppressedCompetitor instanceof CompetitorDTOImpl); // assert that the existing competitor was compacted
}
}
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(newSuppressedCompetitorsBeforeStripping, applied.getSuppressedCompetitors());
}
@Test
public void testDisplayNameChange() {
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
/* timeOnDistanceAllowancePerNauticalMile */ null);
newVersion.competitors.add(somebodyNew);
newVersion.competitorDisplayNames = new HashMap<CompetitorDTO, String>(newVersion.competitorDisplayNames);
newVersion.competitorDisplayNames.put(newVersion.competitors.get(13), "Humba");
newVersion.competitorDisplayNames.put(somebodyNew, "Trala");
final HashMap<CompetitorDTO, String> newDisplayNamesBeforeStripping = new HashMap<CompetitorDTO, String>();
newDisplayNamesBeforeStripping.putAll(newVersion.competitorDisplayNames);
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertEquals(2, newVersion.competitorDisplayNames.size());
assertTrue(newVersion.competitorDisplayNames.keySet().contains(somebodyNew));
for (CompetitorDTO compactSuppressedCompetitor : newVersion.competitorDisplayNames.keySet()) {
if (compactSuppressedCompetitor != somebodyNew) {
assertFalse(compactSuppressedCompetitor instanceof CompetitorDTOImpl); // assert that the existing competitor was compacted
}
}
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(newDisplayNamesBeforeStripping, applied.competitorDisplayNames);
}
@Test
public void testCompetitorOrderingInRaceChange() {
RaceColumnDTO r9 = newVersion.getRaceColumnByName("R9");
Map<String, List<CompetitorDTO>> newCompetitorOrderingPerRace = new HashMap<String, List<CompetitorDTO>>(newVersion.getCompetitorOrderingPerRaceColumnName());
newVersion.setCompetitorOrderingPerRace(newCompetitorOrderingPerRace);
List<CompetitorDTO> newOrdering = new ArrayList<CompetitorDTO>(newVersion.getCompetitorsFromBestToWorst(r9));
newVersion.setCompetitorsFromBestToWorst(r9, newOrdering);
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
/* timeOnDistanceAllowancePerNauticalMile */ null);
newVersion.competitors.add(somebodyNew);
newOrdering.add(somebodyNew);
CompetitorDTO formerRank13 = newOrdering.remove(13);
newOrdering.add(12, formerRank13);
List<CompetitorDTO> newOrderBeforeStripping = new ArrayList<CompetitorDTO>(newOrdering);
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
for (int i=1; i<9; i++) {
assertNull(newVersion.getCompetitorsFromBestToWorst("R"+i));
}
assertEquals(newVersion.getCompetitorsFromBestToWorst(r9).size()-1, newVersion.getCompetitorsFromBestToWorst(r9).indexOf(somebodyNew));
for (CompetitorDTO compactSuppressedCompetitor : newVersion.getCompetitorsFromBestToWorst(r9)) {
if (compactSuppressedCompetitor != somebodyNew) {
assertFalse(compactSuppressedCompetitor instanceof CompetitorDTOImpl); // assert that the existing competitor was compacted
}
}
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(newOrderBeforeStripping, applied.getCompetitorsFromBestToWorst(applied.getRaceColumnByName("R9")));
}
private void assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(LeaderboardDTO leaderboard) {
if (leaderboard.rows != null) {
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : leaderboard.rows.entrySet()) {
assertSame(e.getKey(), e.getValue().competitor);
}
}
}
@Test
public void testPartialRaceColumnDTOCompaction() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
// create a modified R9 RaceDTO clone in newVersion to make sure that even changing a property in the RaceDTO will keep the RaceColumnDTO from being omitted
RaceColumnDTO r9 = newVersion.getRaceColumnByName("R9");
RaceColumnDTO clonedR9 = new RaceColumnDTO();
cloner.clone(r9, clonedR9);
// also clone the racesPerFleet map, or else we'd be modifying the previous version's one too
final Field racesPerFleetField = clonedR9.getClass().getDeclaredField("racesPerFleet");
racesPerFleetField.setAccessible(true);
@SuppressWarnings("unchecked")
final Map<FleetDTO, RaceDTO> m = (Map<FleetDTO, RaceDTO>) racesPerFleetField.get(clonedR9);
racesPerFleetField.set(clonedR9, new HashMap<FleetDTO, RaceDTO>(m));
final FleetDTO defaultFleet = r9.getFleets().iterator().next();
RaceDTO r9Race = r9.getRace(defaultFleet);
RaceDTO clonedR9Race = new RaceDTO();
cloner.clone(r9Race, clonedR9Race);
clonedR9.setRace(defaultFleet, clonedR9Race);
clonedR9Race.endOfRace = new MillisecondsTimePoint(r9Race.endOfRace).plus(1234).asDate();
List<RaceColumnDTO> clonedRaceList = new ArrayList<RaceColumnDTO>(newVersion.getRaceList());
clonedRaceList.set(clonedRaceList.indexOf(r9), clonedR9);
newVersion.setRaceList(clonedRaceList);
List<RaceColumnDTO> raceListBeforeStripping = new ArrayList<RaceColumnDTO>(clonedRaceList);
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
for (int i=0; i<8; i++) {
assertNull(newVersion.getRaceList().get(i));
}
assertNotNull(newVersion.getRaceList().get(8));
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(raceListBeforeStripping, applied.getRaceList());
}
}
package com.sap.sailing.domain.common.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.common.dto.BoatClassDTO;
import com.sap.sailing.domain.common.dto.BoatDTO;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.domain.common.dto.CompetitorDTOImpl;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.IncrementalLeaderboardDTO;
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
import com.sap.sailing.domain.common.dto.LeaderboardEntryDTO;
import com.sap.sailing.domain.common.dto.LeaderboardRowDTO;
import com.sap.sailing.domain.common.dto.LegEntryDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.domain.common.dto.RaceDTO;
import com.sap.sailing.domain.test.StoredTrackBasedTest;
import com.sap.sse.common.Cloner;
import com.sap.sse.common.Color;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.util.ClonerImpl;
/**
* Tests the compressing / de-compressing functionality of {@link LeaderboardDTO} and {@link IncrementalLeaderboardDTO}.
* See also bug 1417.<p>
*
* The data of a meaningful and non-trivial {@link LeaderboardDTO} is obtained by using an instrumented version of
* <code>SailingServiceImpl.getLeaderboardByName(...)</code> which serializes the leaderboard at the end of the method
* to a file used by this test. The leaderboard that this test wants to use is that of the 505 Worlds 2013, obtained
* for an expanded Race R9 at time 2013-05-03T17:21:40Z.
*
* @author Axel Uhl (d043530)
*
*/
public class LeaderboardDTODiffingTest {
private LeaderboardDTO previousVersion;
private IncrementalLeaderboardDTO newVersion;
private final Cloner cloner = new ClonerImpl();
@Before
public void setUp() throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream ois = StoredTrackBasedTest.getObjectInputStream("IncrementalLeaderboardDTO.ser");
previousVersion = (LeaderboardDTO) ois.readObject();
ois.close();
newVersion = new IncrementalLeaderboardDTO("12345", cloner);
cloner.clone(previousVersion, newVersion);
}
private CompetitorDTO getPreviousCompetitorByName(String name) {
for (CompetitorDTO competitor : previousVersion.competitors) {
if (competitor.getName().equals(name)) {
return competitor;
}
}
return null;
}
@Test
public void testEmptyLegDetailsGetFilled() throws FileNotFoundException, IOException, ClassNotFoundException {
// remove legDetails for R9 for all competitors from previousVersion; remember which ones did contain data
Set<CompetitorDTO> hadLegDetailsInR9 = new HashSet<>();
Map<CompetitorDTO, LeaderboardRowDTO> newRows = new HashMap<>();
for (CompetitorDTO competitor : previousVersion.rows.keySet()) {
LeaderboardRowDTO competitorRow = new LeaderboardRowDTO();
cloner.clone(newVersion.rows.get(competitor), competitorRow);
Map<String, LeaderboardEntryDTO> newFieldsByRaceColumnName = new HashMap<>();
for (Entry<String, LeaderboardEntryDTO> e : competitorRow.fieldsByRaceColumnName.entrySet()) {
LeaderboardEntryDTO newEntry = new LeaderboardEntryDTO();
cloner.clone(e.getValue(), newEntry);
newFieldsByRaceColumnName.put(e.getKey(), newEntry);
}
competitorRow.fieldsByRaceColumnName = newFieldsByRaceColumnName;
newRows.put(competitor, competitorRow); // use a copy of the row so we can null out legDetails for R9 in previousVersion only
LeaderboardRowDTO previousRow = previousVersion.rows.get(competitor);
assertNotSame(previousRow, competitorRow);
if (previousRow.fieldsByRaceColumnName.get("R9").legDetails != null) {
hadLegDetailsInR9.add(competitor);
previousRow.fieldsByRaceColumnName.get("R9").legDetails = null;
assertNotNull(competitorRow.fieldsByRaceColumnName.get("R9").legDetails != null);
}
}
newVersion.rows = newRows;
newVersion.strip(previousVersion); // should contain the leg details now
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
// now applied must contain the leg details
for (CompetitorDTO competitor : hadLegDetailsInR9) {
assertNotNull(applied.rows.get(competitor).fieldsByRaceColumnName.get("R9").legDetails);
}
}
@Test
public void testLeaderboardSuccessfullyRead() {
assertNotNull(previousVersion);
assertNotNull(newVersion);
}
@Test
public void testPreviousAndNewVersionHaveEqualRows() {
assertEquals(previousVersion.rows, newVersion.rows);
}
@Test
public void testTotalStripping() {
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertNull(newVersion.rows);
}
@Test
public void testMajorStripping() {
newVersion.rows = new HashMap<CompetitorDTO, LeaderboardRowDTO>(newVersion.rows);
List<RaceColumnDTO> raceListBeforeStripping = new ArrayList<RaceColumnDTO>(newVersion.getRaceList());
CompetitorDTO wolfgang = getPreviousCompetitorByName("HUNGER +JESS");
assertNotNull(wolfgang);
LeaderboardRowDTO wolfgangsRow = new LeaderboardRowDTO();
cloner.clone(newVersion.rows.get(wolfgang), wolfgangsRow);
newVersion.rows.put(wolfgang, wolfgangsRow);
wolfgangsRow.totalDistanceTraveledInMeters += 1;
Map<CompetitorDTO, LeaderboardRowDTO> rowsBeforeStripping = newVersion.rows;
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertNotNull(newVersion.rows);
assertEquals(1, newVersion.rows.size()); // only wolfgang's row should show
assertEquals(wolfgang, newVersion.rows.keySet().iterator().next().getCompetitorFromPrevious(previousVersion));
assertTrue(newVersion.rows.values().iterator().next().fieldsByRaceColumnName.isEmpty());
for (RaceColumnDTO nullRaceColumn : newVersion.getRaceList()) {
assertNull(nullRaceColumn); // there were no changes to the columns; expect all of them to have been eliminiated
}
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(rowsBeforeStripping, applied.rows);
assertNotSame(raceListBeforeStripping, applied.getRaceList());
assertEquals(raceListBeforeStripping, applied.getRaceList());
}
@Test
public void testStrippingExceptOneColumnInOneRace() {
HashMap<CompetitorDTO, LeaderboardRowDTO> newRows = new HashMap<CompetitorDTO, LeaderboardRowDTO>(newVersion.rows);
double newDistance = 1234;
String nameOfRaceColumnToChange = "R9";
int indexOfLegToChange = 7; // ( zero based: ) 8th leg is the last leg
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : newVersion.rows.entrySet()) {
LeaderboardRowDTO newRow = new LeaderboardRowDTO();
cloner.clone(e.getValue(), newRow);
newRows.put(e.getKey(), newRow);
newRow.fieldsByRaceColumnName = new HashMap<String, LeaderboardEntryDTO>(newRow.fieldsByRaceColumnName); // clone entry map
LeaderboardEntryDTO newEntry = new LeaderboardEntryDTO();
cloner.clone(newRow.fieldsByRaceColumnName.get(nameOfRaceColumnToChange), newEntry);
newRow.fieldsByRaceColumnName.put(nameOfRaceColumnToChange, newEntry);
if (newEntry.legDetails != null) {
newEntry.legDetails = new ArrayList<LegEntryDTO>(newEntry.legDetails); // clone leg details list
if (newEntry.legDetails.get(indexOfLegToChange) != null) {
LegEntryDTO newLegDetail = new LegEntryDTO();
cloner.clone(newEntry.legDetails.get(indexOfLegToChange), newLegDetail);
newEntry.legDetails.set(indexOfLegToChange, newLegDetail);
newLegDetail.distanceTraveledInMeters = newDistance;
newDistance += 1;
}
}
}
newVersion.rows = newRows;
Map<CompetitorDTO, LeaderboardRowDTO> rowsBeforeStripping = newVersion.rows;
Map<com.sap.sse.common.Util.Pair<CompetitorDTO, String>, List<LegEntryDTO>> previousLegDetailsBeforeStripping = new HashMap<>();
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : rowsBeforeStripping.entrySet()) {
for (Map.Entry<String, LeaderboardEntryDTO> e2 : e.getValue().fieldsByRaceColumnName.entrySet()) {
if (e2.getValue().legDetails != null) {
previousLegDetailsBeforeStripping.put(new com.sap.sse.common.Util.Pair<CompetitorDTO, String>(e.getKey(), e2.getKey()),
new ArrayList<>(e2.getValue().legDetails));
}
}
}
newVersion.strip(previousVersion);
// see bug 1455; check that the stripping doesn't kill the previous leaderboard's legDetails lists
for (Map.Entry<com.sap.sse.common.Util.Pair<CompetitorDTO, String>, List<LegEntryDTO>> e : previousLegDetailsBeforeStripping.entrySet()) {
final LeaderboardRowDTO leaderboardRowDTO = rowsBeforeStripping.get(e.getKey().getA());
if (leaderboardRowDTO != null) {
List<LegEntryDTO> newLegDetails = leaderboardRowDTO.fieldsByRaceColumnName.get(e.getKey().getB()).legDetails;
assertEquals(e.getValue(), newLegDetails);
}
}
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertNotNull(newVersion.rows);
assertEquals(previousVersion.rows.size()-17, newVersion.rows.size()); // all rows have changed except for 17 that have no leg details in leg 8
// now assert that for all rows there is no leaderboard entry for all races but R9 and
// for R9 there either are no leg details or all leg details for all legs other than L8 are null
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : newVersion.rows.entrySet()) {
if (e.getValue().fieldsByRaceColumnName != null) {
assertTrue(e.getValue().fieldsByRaceColumnName.size() <= 1);
for (Map.Entry<String, LeaderboardEntryDTO> e2 : e.getValue().fieldsByRaceColumnName.entrySet()) {
if (e2.getKey().equals(nameOfRaceColumnToChange)) {
List<LegEntryDTO> r9LegDetails = e2.getValue().legDetails;
if (r9LegDetails != null) {
for (int i=0; i<r9LegDetails.size(); i++) {
if (i != indexOfLegToChange) {
assertNull(r9LegDetails.get(i));
} else {
assertNotNull(r9LegDetails.get(i));
}
}
}
} else {
// if there is an entry for any column other than R9 (which is not really expected) then the entry is expected to be null
assertNull(e2.getValue());
}
}
}
}
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(rowsBeforeStripping, applied.rows);
}
@Test
public void testCompetitorListChange() {
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
/* timeOnDistanceAllowancePerNauticalMile */ null, null);
newVersion.competitors.add(13, somebodyNew); // insert a competitor; this should mess up all others' indexes; check if this works
CompetitorDTO wolfgang = getPreviousCompetitorByName("HUNGER +JESS");
newVersion.competitors.remove(wolfgang);
newVersion.rows.remove(wolfgang); // remove another competitor
List<CompetitorDTO> newCompetitorsBeforeStripping = new ArrayList<CompetitorDTO>(newVersion.competitors);
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertNull(newVersion.competitors); // but there should be an added competitor that we can't see through the public interface
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(newCompetitorsBeforeStripping, applied.competitors);
}
@Test
public void testSuppressionChange() {
final List<CompetitorDTO> newSuppressedCompetitors = new ArrayList<CompetitorDTO>();
Util.addAll(newVersion.getSuppressedCompetitors(), newSuppressedCompetitors);
newVersion.setSuppressedCompetitors(newSuppressedCompetitors);
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
/* timeOnDistanceAllowancePerNauticalMile */ null, null);
newVersion.setSuppressed(newVersion.competitors.get(13), true); // suppress an existing competitor; compaction should reduce this to a single number only
newVersion.setSuppressed(somebodyNew, true); // check that mixed mode with existing and new competitors works as well
List<CompetitorDTO> newSuppressedCompetitorsBeforeStripping = new ArrayList<CompetitorDTO>();
Util.addAll(newVersion.getSuppressedCompetitors(), newSuppressedCompetitorsBeforeStripping);
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertEquals(2, Util.size(newVersion.getSuppressedCompetitors()));
assertTrue(Util.contains(newVersion.getSuppressedCompetitors(), somebodyNew));
for (CompetitorDTO compactSuppressedCompetitor : newVersion.getSuppressedCompetitors()) {
if (compactSuppressedCompetitor != somebodyNew) {
assertFalse(compactSuppressedCompetitor instanceof CompetitorDTOImpl); // assert that the existing competitor was compacted
}
}
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(newSuppressedCompetitorsBeforeStripping, applied.getSuppressedCompetitors());
}
@Test
public void testDisplayNameChange() {
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
/* timeOnDistanceAllowancePerNauticalMile */ null, null);
newVersion.competitors.add(somebodyNew);
newVersion.competitorDisplayNames = new HashMap<CompetitorDTO, String>(newVersion.competitorDisplayNames);
newVersion.competitorDisplayNames.put(newVersion.competitors.get(13), "Humba");
newVersion.competitorDisplayNames.put(somebodyNew, "Trala");
final HashMap<CompetitorDTO, String> newDisplayNamesBeforeStripping = new HashMap<CompetitorDTO, String>();
newDisplayNamesBeforeStripping.putAll(newVersion.competitorDisplayNames);
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertEquals(2, newVersion.competitorDisplayNames.size());
assertTrue(newVersion.competitorDisplayNames.keySet().contains(somebodyNew));
for (CompetitorDTO compactSuppressedCompetitor : newVersion.competitorDisplayNames.keySet()) {
if (compactSuppressedCompetitor != somebodyNew) {
assertFalse(compactSuppressedCompetitor instanceof CompetitorDTOImpl); // assert that the existing competitor was compacted
}
}
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(newDisplayNamesBeforeStripping, applied.competitorDisplayNames);
}
@Test
public void testCompetitorOrderingInRaceChange() {
RaceColumnDTO r9 = newVersion.getRaceColumnByName("R9");
Map<String, List<CompetitorDTO>> newCompetitorOrderingPerRace = new HashMap<String, List<CompetitorDTO>>(newVersion.getCompetitorOrderingPerRaceColumnName());
newVersion.setCompetitorOrderingPerRace(newCompetitorOrderingPerRace);
List<CompetitorDTO> newOrdering = new ArrayList<CompetitorDTO>(newVersion.getCompetitorsFromBestToWorst(r9));
newVersion.setCompetitorsFromBestToWorst(r9, newOrdering);
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
/* timeOnDistanceAllowancePerNauticalMile */ null, null);
newVersion.competitors.add(somebodyNew);
newOrdering.add(somebodyNew);
CompetitorDTO formerRank13 = newOrdering.remove(13);
newOrdering.add(12, formerRank13);
List<CompetitorDTO> newOrderBeforeStripping = new ArrayList<CompetitorDTO>(newOrdering);
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
for (int i=1; i<9; i++) {
assertNull(newVersion.getCompetitorsFromBestToWorst("R"+i));
}
assertEquals(newVersion.getCompetitorsFromBestToWorst(r9).size()-1, newVersion.getCompetitorsFromBestToWorst(r9).indexOf(somebodyNew));
for (CompetitorDTO compactSuppressedCompetitor : newVersion.getCompetitorsFromBestToWorst(r9)) {
if (compactSuppressedCompetitor != somebodyNew) {
assertFalse(compactSuppressedCompetitor instanceof CompetitorDTOImpl); // assert that the existing competitor was compacted
}
}
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(newOrderBeforeStripping, applied.getCompetitorsFromBestToWorst(applied.getRaceColumnByName("R9")));
}
private void assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(LeaderboardDTO leaderboard) {
if (leaderboard.rows != null) {
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : leaderboard.rows.entrySet()) {
assertSame(e.getKey(), e.getValue().competitor);
}
}
}
@Test
public void testPartialRaceColumnDTOCompaction() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
// create a modified R9 RaceDTO clone in newVersion to make sure that even changing a property in the RaceDTO will keep the RaceColumnDTO from being omitted
RaceColumnDTO r9 = newVersion.getRaceColumnByName("R9");
RaceColumnDTO clonedR9 = new RaceColumnDTO();
cloner.clone(r9, clonedR9);
// also clone the racesPerFleet map, or else we'd be modifying the previous version's one too
final Field racesPerFleetField = clonedR9.getClass().getDeclaredField("racesPerFleet");
racesPerFleetField.setAccessible(true);
@SuppressWarnings("unchecked")
final Map<FleetDTO, RaceDTO> m = (Map<FleetDTO, RaceDTO>) racesPerFleetField.get(clonedR9);
racesPerFleetField.set(clonedR9, new HashMap<FleetDTO, RaceDTO>(m));
final FleetDTO defaultFleet = r9.getFleets().iterator().next();
RaceDTO r9Race = r9.getRace(defaultFleet);
RaceDTO clonedR9Race = new RaceDTO();
cloner.clone(r9Race, clonedR9Race);
clonedR9.setRace(defaultFleet, clonedR9Race);
clonedR9Race.endOfRace = new MillisecondsTimePoint(r9Race.endOfRace).plus(1234).asDate();
List<RaceColumnDTO> clonedRaceList = new ArrayList<RaceColumnDTO>(newVersion.getRaceList());
clonedRaceList.set(clonedRaceList.indexOf(r9), clonedR9);
newVersion.setRaceList(clonedRaceList);
List<RaceColumnDTO> raceListBeforeStripping = new ArrayList<RaceColumnDTO>(clonedRaceList);
newVersion.strip(previousVersion);
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
for (int i=0; i<8; i++) {
assertNull(newVersion.getRaceList().get(i));
}
assertNotNull(newVersion.getRaceList().get(8));
LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion);
assertEquals(raceListBeforeStripping, applied.getRaceList());
}
}
@@ -20,7 +20,7 @@ public abstract class AbstractLeaderboardTest {
/* dateOfBirth */ null, "This is famous "+competitorName)),
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
}
public static Competitor createCompetitor(String competitorName, CompetitorFactory competitorFactory) {
@@ -30,7 +30,7 @@ public abstract class AbstractLeaderboardTest {
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null);
}
public static CompetitorImpl createCompetitor(String competitorName, Serializable id) {
@@ -39,6 +39,6 @@ public abstract class AbstractLeaderboardTest {
/* dateOfBirth */ null, "This is famous "+competitorName)),
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
}
}
@@ -1,299 +1,320 @@
package com.sap.sailing.domain.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.CompetitorChangeListener;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.WithNationality;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
import com.sap.sse.common.impl.RGBColor;
/**
* Tests the {@link CompetitorChangeListener} stuff including the serialization of the transitive listener
* pattern on the {@link Team} structure.
*
* @author Axel Uhl (D043530)
*
*/
public class CompetitorListenerTest extends AbstractSerializationTest {
private CompetitorChangeListener listener;
private boolean nationalityChanged;
private Object whatChangedNationality;
private Object oldNationality;
private Object newNationality;
private boolean sailIdChanged;
private String oldSailId;
private String newSailId;
private boolean nameChanged;
private String oldName;
private String newName;
private boolean colorChanged;
private Color oldColor;
private Color newColor;
private DynamicCompetitor competitor;
private DomainFactoryImpl baseDomainFactory;
private boolean emailChanged;
private String oldEmail;
private String newEmail;
private boolean flagImageChanged;
private URI oldFlagImageURL;
private URI newFlagImageURL;
private boolean timeOnTimeFactorChanged;
private Double oldTimeOnTimeFactor;
private Double newTimeOnTimeFactor;
private boolean timeOnDistanceAllowancePerNauticalMileChanged;
private Duration oldTimeOnDistanceAllowancePerNauticalMile;
private Duration newTimeOnDistanceAllowancePerNauticalMile;
@Before
public void setUp() {
baseDomainFactory = new DomainFactoryImpl((srlid)->null);
competitor = TrackBasedTest.createCompetitor("Hasso");
nationalityChanged = false;
whatChangedNationality = null;
oldNationality = null;
newNationality = null;
sailIdChanged = false;
oldSailId = null;
newSailId = null;
nameChanged = false;
oldName = null;
newName = null;
colorChanged = false;
oldColor = null;
newColor = null;
emailChanged = false;
oldEmail = null;
newEmail = null;
flagImageChanged = false;
oldFlagImageURL = null;
newFlagImageURL = null;
timeOnTimeFactorChanged = false;
oldTimeOnTimeFactor = null;
newTimeOnTimeFactor = null;
timeOnDistanceAllowancePerNauticalMileChanged = false;
oldTimeOnDistanceAllowancePerNauticalMile = null;
newTimeOnDistanceAllowancePerNauticalMile = null;
listener = new CompetitorChangeListener() {
private static final long serialVersionUID = 4581029778988240209L;
@Override
public void nationalityChanged(WithNationality what, Nationality oldNationality, Nationality newNationality) {
nationalityChanged = true;
whatChangedNationality = what;
CompetitorListenerTest.this.oldNationality = oldNationality;
CompetitorListenerTest.this.newNationality = newNationality;
}
@Override
public void sailIdChanged(String oldSailId, String newSailId) {
sailIdChanged = true;
CompetitorListenerTest.this.oldSailId = oldSailId;
CompetitorListenerTest.this.newSailId = newSailId;
}
@Override
public void nameChanged(String oldName, String newName) {
nameChanged = true;
CompetitorListenerTest.this.oldName = oldName;
CompetitorListenerTest.this.newName = newName;
}
@Override
public void colorChanged(Color oldColor, Color newColor) {
colorChanged = true;
CompetitorListenerTest.this.oldColor = oldColor;
CompetitorListenerTest.this.newColor = newColor;
}
@Override
public void emailChanged(String oldEmail, String newEmail) {
emailChanged = true;
CompetitorListenerTest.this.oldEmail = oldEmail;
CompetitorListenerTest.this.newEmail = newEmail;
}
@Override
public void flagImageChanged(URI oldFlagImageURL, URI newFlagImageURL) {
flagImageChanged = true;
CompetitorListenerTest.this.oldFlagImageURL = oldFlagImageURL;
CompetitorListenerTest.this.newFlagImageURL = newFlagImageURL;
}
@Override
public void timeOnTimeFactorChanged(Double oldTimeOnTimeFactor, Double newTimeOnTimeFactor) {
timeOnTimeFactorChanged = true;
CompetitorListenerTest.this.oldTimeOnTimeFactor = oldTimeOnTimeFactor;
CompetitorListenerTest.this.newTimeOnTimeFactor = newTimeOnTimeFactor;
}
@Override
public void timeOnDistanceAllowancePerNauticalMileChanged(
Duration oldTimeOnDistanceAllowancePerNauticalMile,
Duration newTimeOnDistanceAllowancePerNauticalMile) {
timeOnDistanceAllowancePerNauticalMileChanged = true;
CompetitorListenerTest.this.oldTimeOnDistanceAllowancePerNauticalMile = oldTimeOnDistanceAllowancePerNauticalMile;
CompetitorListenerTest.this.newTimeOnDistanceAllowancePerNauticalMile = newTimeOnDistanceAllowancePerNauticalMile;
}
};
competitor.addCompetitorChangeListener(listener);
}
@Test
public void testNullNationality() {
competitor.getTeam().setNationality(null);
assertNull(competitor.getTeam().getNationality());
competitor.getTeam().setNationality(null);
assertNull(competitor.getTeam().getNationality());
competitor.getTeam().setNationality(baseDomainFactory.getOrCreateNationality("GER"));
assertEquals(baseDomainFactory.getOrCreateNationality("GER"), competitor.getTeam().getNationality());
competitor.getTeam().setNationality(null);
assertNull(competitor.getTeam().getNationality());
}
@Test
public void testChangeTimeOnTimeFactor() {
competitor.setTimeOnTimeFactor(1.209);
assertTrue(timeOnTimeFactorChanged);
assertNull(oldTimeOnTimeFactor);
assertEquals(1.209, newTimeOnTimeFactor, 0.00000001);
}
@Test
public void testChangeTimeOnDistanceAllowancePerNauticalMile() {
competitor.setTimeOnDistanceAllowancePerNauticalMile(Duration.ONE_HOUR);
assertTrue(timeOnDistanceAllowancePerNauticalMileChanged);
assertNull(oldTimeOnDistanceAllowancePerNauticalMile);
assertEquals(Duration.ONE_HOUR.asMillis(), newTimeOnDistanceAllowancePerNauticalMile.asMillis());
}
@Test
public void testSimpleCompetitorListenerPatternForName() {
competitor.setName("Dr. Hasso Plattner");
assertTrue(nameChanged);
assertEquals("Hasso", oldName);
assertEquals("Dr. Hasso Plattner", newName);
assertFalse(sailIdChanged);
assertFalse(colorChanged);
assertFalse(nationalityChanged);
}
@Test
public void testFlagChange() throws URISyntaxException {
competitor.setFlagImage(new URI("http://www.something.de/pic.png"));
assertTrue(flagImageChanged);
assertNull(oldFlagImageURL);
assertEquals(new URI("http://www.something.de/pic.png"), newFlagImageURL);
}
@Test
public void testEmailChange() throws URISyntaxException {
competitor.setEmail("hasso.plattner@sap.com");
assertTrue(emailChanged);
assertNull(oldEmail);
assertEquals("hasso.plattner@sap.com", newEmail);
}
@Test
public void testSimpleCompetitorListenerPatternForSailId() {
final String myOldSailId = competitor.getBoat().getSailID();
competitor.getBoat().setSailId("POR 40");
assertFalse(nameChanged);
assertTrue(sailIdChanged);
assertEquals(myOldSailId, oldSailId);
assertEquals("POR 40", newSailId);
assertFalse(colorChanged);
assertFalse(nationalityChanged);
}
@Test
public void testSimpleCompetitorListenerPatternForColor() {
final Color myOldColor = competitor.getColor();
final RGBColor myNewColor = new RGBColor(123, 12, 234);
competitor.setColor(myNewColor);
assertFalse(nameChanged);
assertFalse(sailIdChanged);
assertTrue(colorChanged);
assertEquals(myOldColor, oldColor);
assertEquals(myNewColor, newColor);
assertFalse(nationalityChanged);
}
@Test
public void testSimpleCompetitorListenerPatternForNationality() {
final Nationality myOldNationality = competitor.getTeam().getNationality();
final Nationality myNewNationality = DomainFactory.INSTANCE.getOrCreateNationality("POR");
competitor.getTeam().setNationality(myNewNationality);
assertFalse(nameChanged);
assertFalse(sailIdChanged);
assertFalse(colorChanged);
assertTrue(nationalityChanged);
assertEquals(myOldNationality, oldNationality);
assertEquals(myNewNationality, newNationality);
assertSame(competitor.getTeam(), whatChangedNationality);
}
@Test
public void testCompetitorSerializationLosesAllExternalListeners() throws ClassNotFoundException, IOException {
DomainFactory baseDomainFactory = new DomainFactoryImpl((srlid)->null);
DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory);
clonedCompetitor.setName("Dr. Hasso Plattner");
clonedCompetitor.getBoat().setSailId("POR 40");
final RGBColor myNewColor = new RGBColor(123, 12, 234);
clonedCompetitor.setColor(myNewColor);
final Nationality myNewNationality = baseDomainFactory.getOrCreateNationality("POR");
clonedCompetitor.getTeam().setNationality(myNewNationality);
assertFalse(nameChanged);
assertFalse(sailIdChanged);
assertFalse(colorChanged);
assertFalse(nationalityChanged);
}
@Test
public void testCompetitorSerializationListenerPatternForNameOnSerializedCompetitor() throws ClassNotFoundException, IOException {
DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory);
competitor = clonedCompetitor;
competitor.addCompetitorChangeListener(listener);
testSimpleCompetitorListenerPatternForName();
}
@Test
public void testCompetitorSerializationListenerPatternForColorOnSerializedCompetitor() throws ClassNotFoundException, IOException {
DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory);
competitor = clonedCompetitor;
competitor.addCompetitorChangeListener(listener);
testSimpleCompetitorListenerPatternForColor();
}
@Test
public void testCompetitorSerializationListenerPatternForSailIdOnSerializedCompetitor() throws ClassNotFoundException, IOException {
DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory);
competitor = clonedCompetitor;
competitor.addCompetitorChangeListener(listener);
testSimpleCompetitorListenerPatternForSailId();
}
@Test
public void testCompetitorSerializationListenerPatternForNationalityOnSerializedCompetitor() throws ClassNotFoundException, IOException {
DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory);
competitor = clonedCompetitor;
competitor.addCompetitorChangeListener(listener);
testSimpleCompetitorListenerPatternForNationality();
}
}
package com.sap.sailing.domain.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.CompetitorChangeListener;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.WithNationality;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
import com.sap.sse.common.impl.RGBColor;
/**
* Tests the {@link CompetitorChangeListener} stuff including the serialization of the transitive listener
* pattern on the {@link Team} structure.
*
* @author Axel Uhl (D043530)
*
*/
public class CompetitorListenerTest extends AbstractSerializationTest {
private CompetitorChangeListener listener;
private boolean nationalityChanged;
private Object whatChangedNationality;
private Object oldNationality;
private Object newNationality;
private boolean sailIdChanged;
private String oldSailId;
private String newSailId;
private boolean nameChanged;
private String oldName;
private String newName;
private boolean colorChanged;
private Color oldColor;
private Color newColor;
private DynamicCompetitor competitor;
private DomainFactoryImpl baseDomainFactory;
private boolean emailChanged;
private String oldEmail;
private String newEmail;
private boolean searchTagChanged;
private String oldSearchTag;
private String newSearchTag;
private boolean flagImageChanged;
private URI oldFlagImageURL;
private URI newFlagImageURL;
private boolean timeOnTimeFactorChanged;
private Double oldTimeOnTimeFactor;
private Double newTimeOnTimeFactor;
private boolean timeOnDistanceAllowancePerNauticalMileChanged;
private Duration oldTimeOnDistanceAllowancePerNauticalMile;
private Duration newTimeOnDistanceAllowancePerNauticalMile;
@Before
public void setUp() {
baseDomainFactory = new DomainFactoryImpl((srlid)->null);
competitor = TrackBasedTest.createCompetitor("Hasso");
nationalityChanged = false;
whatChangedNationality = null;
oldNationality = null;
newNationality = null;
sailIdChanged = false;
oldSailId = null;
newSailId = null;
nameChanged = false;
oldName = null;
newName = null;
colorChanged = false;
oldColor = null;
newColor = null;
emailChanged = false;
oldEmail = null;
newEmail = null;
searchTagChanged = false;
oldSearchTag = null;
newSearchTag = null;
flagImageChanged = false;
oldFlagImageURL = null;
newFlagImageURL = null;
timeOnTimeFactorChanged = false;
oldTimeOnTimeFactor = null;
newTimeOnTimeFactor = null;
timeOnDistanceAllowancePerNauticalMileChanged = false;
oldTimeOnDistanceAllowancePerNauticalMile = null;
newTimeOnDistanceAllowancePerNauticalMile = null;
listener = new CompetitorChangeListener() {
private static final long serialVersionUID = 4581029778988240209L;
@Override
public void nationalityChanged(WithNationality what, Nationality oldNationality, Nationality newNationality) {
nationalityChanged = true;
whatChangedNationality = what;
CompetitorListenerTest.this.oldNationality = oldNationality;
CompetitorListenerTest.this.newNationality = newNationality;
}
@Override
public void sailIdChanged(String oldSailId, String newSailId) {
sailIdChanged = true;
CompetitorListenerTest.this.oldSailId = oldSailId;
CompetitorListenerTest.this.newSailId = newSailId;
}
@Override
public void nameChanged(String oldName, String newName) {
nameChanged = true;
CompetitorListenerTest.this.oldName = oldName;
CompetitorListenerTest.this.newName = newName;
}
@Override
public void colorChanged(Color oldColor, Color newColor) {
colorChanged = true;
CompetitorListenerTest.this.oldColor = oldColor;
CompetitorListenerTest.this.newColor = newColor;
}
@Override
public void emailChanged(String oldEmail, String newEmail) {
emailChanged = true;
CompetitorListenerTest.this.oldEmail = oldEmail;
CompetitorListenerTest.this.newEmail = newEmail;
}
@Override
public void searchTagChanged(String oldSearchTag, String newSearchTag) {
searchTagChanged = true;
CompetitorListenerTest.this.oldSearchTag = oldSearchTag;
CompetitorListenerTest.this.newSearchTag = newSearchTag;
}
@Override
public void flagImageChanged(URI oldFlagImageURL, URI newFlagImageURL) {
flagImageChanged = true;
CompetitorListenerTest.this.oldFlagImageURL = oldFlagImageURL;
CompetitorListenerTest.this.newFlagImageURL = newFlagImageURL;
}
@Override
public void timeOnTimeFactorChanged(Double oldTimeOnTimeFactor, Double newTimeOnTimeFactor) {
timeOnTimeFactorChanged = true;
CompetitorListenerTest.this.oldTimeOnTimeFactor = oldTimeOnTimeFactor;
CompetitorListenerTest.this.newTimeOnTimeFactor = newTimeOnTimeFactor;
}
@Override
public void timeOnDistanceAllowancePerNauticalMileChanged(
Duration oldTimeOnDistanceAllowancePerNauticalMile,
Duration newTimeOnDistanceAllowancePerNauticalMile) {
timeOnDistanceAllowancePerNauticalMileChanged = true;
CompetitorListenerTest.this.oldTimeOnDistanceAllowancePerNauticalMile = oldTimeOnDistanceAllowancePerNauticalMile;
CompetitorListenerTest.this.newTimeOnDistanceAllowancePerNauticalMile = newTimeOnDistanceAllowancePerNauticalMile;
}
};
competitor.addCompetitorChangeListener(listener);
}
@Test
public void testNullNationality() {
competitor.getTeam().setNationality(null);
assertNull(competitor.getTeam().getNationality());
competitor.getTeam().setNationality(null);
assertNull(competitor.getTeam().getNationality());
competitor.getTeam().setNationality(baseDomainFactory.getOrCreateNationality("GER"));
assertEquals(baseDomainFactory.getOrCreateNationality("GER"), competitor.getTeam().getNationality());
competitor.getTeam().setNationality(null);
assertNull(competitor.getTeam().getNationality());
}
@Test
public void testChangeTimeOnTimeFactor() {
competitor.setTimeOnTimeFactor(1.209);
assertTrue(timeOnTimeFactorChanged);
assertNull(oldTimeOnTimeFactor);
assertEquals(1.209, newTimeOnTimeFactor, 0.00000001);
}
@Test
public void testChangeTimeOnDistanceAllowancePerNauticalMile() {
competitor.setTimeOnDistanceAllowancePerNauticalMile(Duration.ONE_HOUR);
assertTrue(timeOnDistanceAllowancePerNauticalMileChanged);
assertNull(oldTimeOnDistanceAllowancePerNauticalMile);
assertEquals(Duration.ONE_HOUR.asMillis(), newTimeOnDistanceAllowancePerNauticalMile.asMillis());
}
@Test
public void testSimpleCompetitorListenerPatternForName() {
competitor.setName("Dr. Hasso Plattner");
assertTrue(nameChanged);
assertEquals("Hasso", oldName);
assertEquals("Dr. Hasso Plattner", newName);
assertFalse(sailIdChanged);
assertFalse(colorChanged);
assertFalse(nationalityChanged);
}
@Test
public void testFlagChange() throws URISyntaxException {
competitor.setFlagImage(new URI("http://www.something.de/pic.png"));
assertTrue(flagImageChanged);
assertNull(oldFlagImageURL);
assertEquals(new URI("http://www.something.de/pic.png"), newFlagImageURL);
}
@Test
public void testEmailChange() throws URISyntaxException {
competitor.setEmail("hasso.plattner@sap.com");
assertTrue(emailChanged);
assertNull(oldEmail);
assertEquals("hasso.plattner@sap.com", newEmail);
}
@Test
public void testSearchTagChange() throws URISyntaxException {
competitor.setSearchTag("hasso");
assertTrue(searchTagChanged);
assertNull(oldSearchTag);
assertEquals("hasso", newSearchTag);
}
@Test
public void testSimpleCompetitorListenerPatternForSailId() {
final String myOldSailId = competitor.getBoat().getSailID();
competitor.getBoat().setSailId("POR 40");
assertFalse(nameChanged);
assertTrue(sailIdChanged);
assertEquals(myOldSailId, oldSailId);
assertEquals("POR 40", newSailId);
assertFalse(colorChanged);
assertFalse(nationalityChanged);
}
@Test
public void testSimpleCompetitorListenerPatternForColor() {
final Color myOldColor = competitor.getColor();
final RGBColor myNewColor = new RGBColor(123, 12, 234);
competitor.setColor(myNewColor);
assertFalse(nameChanged);
assertFalse(sailIdChanged);
assertTrue(colorChanged);
assertEquals(myOldColor, oldColor);
assertEquals(myNewColor, newColor);
assertFalse(nationalityChanged);
}
@Test
public void testSimpleCompetitorListenerPatternForNationality() {
final Nationality myOldNationality = competitor.getTeam().getNationality();
final Nationality myNewNationality = DomainFactory.INSTANCE.getOrCreateNationality("POR");
competitor.getTeam().setNationality(myNewNationality);
assertFalse(nameChanged);
assertFalse(sailIdChanged);
assertFalse(colorChanged);
assertTrue(nationalityChanged);
assertEquals(myOldNationality, oldNationality);
assertEquals(myNewNationality, newNationality);
assertSame(competitor.getTeam(), whatChangedNationality);
}
@Test
public void testCompetitorSerializationLosesAllExternalListeners() throws ClassNotFoundException, IOException {
DomainFactory baseDomainFactory = new DomainFactoryImpl((srlid)->null);
DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory);
clonedCompetitor.setName("Dr. Hasso Plattner");
clonedCompetitor.getBoat().setSailId("POR 40");
final RGBColor myNewColor = new RGBColor(123, 12, 234);
clonedCompetitor.setColor(myNewColor);
final Nationality myNewNationality = baseDomainFactory.getOrCreateNationality("POR");
clonedCompetitor.getTeam().setNationality(myNewNationality);
assertFalse(nameChanged);
assertFalse(sailIdChanged);
assertFalse(colorChanged);
assertFalse(nationalityChanged);
}
@Test
public void testCompetitorSerializationListenerPatternForNameOnSerializedCompetitor() throws ClassNotFoundException, IOException {
DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory);
competitor = clonedCompetitor;
competitor.addCompetitorChangeListener(listener);
testSimpleCompetitorListenerPatternForName();
}
@Test
public void testCompetitorSerializationListenerPatternForColorOnSerializedCompetitor() throws ClassNotFoundException, IOException {
DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory);
competitor = clonedCompetitor;
competitor.addCompetitorChangeListener(listener);
testSimpleCompetitorListenerPatternForColor();
}
@Test
public void testCompetitorSerializationListenerPatternForSailIdOnSerializedCompetitor() throws ClassNotFoundException, IOException {
DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory);
competitor = clonedCompetitor;
competitor.addCompetitorChangeListener(listener);
testSimpleCompetitorListenerPatternForSailId();
}
@Test
public void testCompetitorSerializationListenerPatternForNationalityOnSerializedCompetitor() throws ClassNotFoundException, IOException {
DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory);
competitor = clonedCompetitor;
competitor.addCompetitorChangeListener(listener);
testSimpleCompetitorListenerPatternForNationality();
}
}
@@ -1,182 +1,182 @@
package com.sap.sailing.domain.test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.base.impl.MarkImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.SeriesImpl;
import com.sap.sailing.domain.base.impl.WaypointImpl;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore;
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class LeaderboardCourseChangeTest {
/**
* See bug 2011
*
* @throws NoWindException
* @throws InterruptedException
* @throws ExecutionException
*/
@Test
public void testLeaderboardDTOCreationForCourseChange() throws NoWindException, InterruptedException, ExecutionException {
Date date = Calendar.getInstance().getTime();
TimePoint timePoint = new MillisecondsTimePoint(date);
TrackedRegattaRegistry trackedRegattaRegistry = mock(TrackedRegattaRegistry.class);
Fleet fleet = new FleetImpl("TestFleet");
Series series = createSeries(trackedRegattaRegistry, fleet);
Set<Series> seriesSet = new HashSet<>();
seriesSet.add(series);
BoatClass boatClass = new BoatClassImpl("TestClass", true);
String raceColumnName = "TestRace";
RaceColumn raceColumn = series.addRaceColumn(raceColumnName, trackedRegattaRegistry);
ScoringScheme scoringScheme = new LowPoint();
Regatta mockedRegatta = new RegattaImpl(RegattaImpl.getDefaultName("TestRegatta", boatClass.getName()), boatClass,
/*startDate*/ null, /*endDate*/ null, seriesSet, false, scoringScheme,
UUID.randomUUID(), mock(CourseArea.class), OneDesignRankingMetric::new);
ControlPoint start = new MarkImpl("Start");
ControlPoint m1 = new MarkImpl("M1");
ControlPoint m2 = new MarkImpl("M2");
ControlPoint finish = new MarkImpl("Finish");
Set<Waypoint> waypoints = new HashSet<>();
Waypoint startWaypoint = new WaypointImpl(start);
waypoints.add(startWaypoint);
Waypoint m1Waypoint1 = new WaypointImpl(m1);
Waypoint m2Waypoint1 = new WaypointImpl(m2);
Waypoint m1Waypoint2 = new WaypointImpl(m1);
Waypoint m2Waypoint2 = new WaypointImpl(m2);
Waypoint m1Waypoint3 = new WaypointImpl(m1);
waypoints.add(m1Waypoint1);
waypoints.add(m2Waypoint1);
waypoints.add(m1Waypoint2);
waypoints.add(m2Waypoint2);
waypoints.add(m1Waypoint3);
Waypoint finishWaypoint = new WaypointImpl(finish);
waypoints.add(finishWaypoint);
Course course = new CourseImpl(raceColumnName, waypoints);
TrackedRace mockedTrackedRace = createSpyedTrackedRace(mockedRegatta, course, timePoint, boatClass);
raceColumn.setTrackedRace(fleet, mockedTrackedRace);
Set<String> raceColumnNames = new HashSet<>();
raceColumnNames.add(raceColumnName);
int[] ruleRaw = { 5, 3, 2 };
ThresholdBasedResultDiscardingRule rule = new ThresholdBasedResultDiscardingRuleImpl(ruleRaw);
Leaderboard leaderboard = new RegattaLeaderboardImpl(mockedRegatta, rule);
DomainFactory baseDomainFactory = new DomainFactoryImpl((srlid)->null);
LeaderboardDTO leaderboardDTO = leaderboard.getLeaderboardDTO(timePoint, raceColumnNames, false,
trackedRegattaRegistry, baseDomainFactory, /* fillNetPointsUncorrected */ false);
assertEquals(6, leaderboardDTO.rows.values().iterator().next().fieldsByRaceColumnName.values().iterator()
.next().legDetails.size());
course.removeWaypoint(2);
course.removeWaypoint(3);
leaderboardDTO = leaderboard.getLeaderboardDTO(timePoint, raceColumnNames, false, trackedRegattaRegistry,
baseDomainFactory, /* fillNetPointsUncorrected */ false);
assertEquals(4, leaderboardDTO.rows.values().iterator().next().fieldsByRaceColumnName.values().iterator()
.next().legDetails.size());
}
private TrackedRace createSpyedTrackedRace(Regatta regatta, Course course, TimePoint timePoint, BoatClass boatClass) {
TrackedRegatta mockedTrackedRegatta = createMockedTrackedRegatta(regatta);
RaceDefinition mockedRace = createMockedRace(course, boatClass);
TrackedRace spyedTrackedRace = spy(new DynamicTrackedRaceImpl(mockedTrackedRegatta, mockedRace,
new HashSet<Sideline>(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, 5000, 20000, 20000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new,
mock(RaceLogResolver.class)));
return spyedTrackedRace;
}
private RaceDefinition createMockedRace(Course course, BoatClass boatClass) {
RaceDefinition mockedRaceDefinition = mock(RaceDefinition.class);
when(mockedRaceDefinition.getCompetitors()).thenReturn(new HashSet<Competitor>());
when(mockedRaceDefinition.getCourse()).thenReturn(course);
when(mockedRaceDefinition.getBoatClass()).thenReturn(new BoatClassImpl("TestClass", true));
when(mockedRaceDefinition.getName()).thenReturn("TestRace");
Iterable<Competitor> competitorSet = createCompetitorSet(boatClass);
when(mockedRaceDefinition.getCompetitors()).thenReturn(competitorSet);
return mockedRaceDefinition;
}
private Iterable<Competitor> createCompetitorSet(BoatClass boatClass) {
Set<Competitor> competitors = new HashSet<>();
DynamicBoat mockedBoat = mock(DynamicBoat.class);
when(mockedBoat.getBoatClass()).thenReturn(boatClass);
competitors.add(new CompetitorImpl(UUID.randomUUID(), "TestCompetitor", Color.BLACK, null, null,
mock(DynamicTeam.class), mockedBoat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null));
return competitors;
}
private TrackedRegatta createMockedTrackedRegatta(Regatta regatta) {
TrackedRegatta mockedTrackedRegatta = mock(DynamicTrackedRegatta.class);
when(mockedTrackedRegatta.getRegatta()).thenReturn(regatta);
return mockedTrackedRegatta;
}
private Series createSeries(TrackedRegattaRegistry trackedRegattaRegistry, Fleet fleet) {
Set<Fleet> fleets = new HashSet<>();
fleets.add(fleet);
Series series = new SeriesImpl("TestSeries", false, fleets, new HashSet<String>(), trackedRegattaRegistry);
return series;
}
}
package com.sap.sailing.domain.test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.base.impl.MarkImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.SeriesImpl;
import com.sap.sailing.domain.base.impl.WaypointImpl;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore;
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class LeaderboardCourseChangeTest {
/**
* See bug 2011
*
* @throws NoWindException
* @throws InterruptedException
* @throws ExecutionException
*/
@Test
public void testLeaderboardDTOCreationForCourseChange() throws NoWindException, InterruptedException, ExecutionException {
Date date = Calendar.getInstance().getTime();
TimePoint timePoint = new MillisecondsTimePoint(date);
TrackedRegattaRegistry trackedRegattaRegistry = mock(TrackedRegattaRegistry.class);
Fleet fleet = new FleetImpl("TestFleet");
Series series = createSeries(trackedRegattaRegistry, fleet);
Set<Series> seriesSet = new HashSet<>();
seriesSet.add(series);
BoatClass boatClass = new BoatClassImpl("TestClass", true);
String raceColumnName = "TestRace";
RaceColumn raceColumn = series.addRaceColumn(raceColumnName, trackedRegattaRegistry);
ScoringScheme scoringScheme = new LowPoint();
Regatta mockedRegatta = new RegattaImpl(RegattaImpl.getDefaultName("TestRegatta", boatClass.getName()), boatClass,
/*startDate*/ null, /*endDate*/ null, seriesSet, false, scoringScheme,
UUID.randomUUID(), mock(CourseArea.class), OneDesignRankingMetric::new);
ControlPoint start = new MarkImpl("Start");
ControlPoint m1 = new MarkImpl("M1");
ControlPoint m2 = new MarkImpl("M2");
ControlPoint finish = new MarkImpl("Finish");
Set<Waypoint> waypoints = new HashSet<>();
Waypoint startWaypoint = new WaypointImpl(start);
waypoints.add(startWaypoint);
Waypoint m1Waypoint1 = new WaypointImpl(m1);
Waypoint m2Waypoint1 = new WaypointImpl(m2);
Waypoint m1Waypoint2 = new WaypointImpl(m1);
Waypoint m2Waypoint2 = new WaypointImpl(m2);
Waypoint m1Waypoint3 = new WaypointImpl(m1);
waypoints.add(m1Waypoint1);
waypoints.add(m2Waypoint1);
waypoints.add(m1Waypoint2);
waypoints.add(m2Waypoint2);
waypoints.add(m1Waypoint3);
Waypoint finishWaypoint = new WaypointImpl(finish);
waypoints.add(finishWaypoint);
Course course = new CourseImpl(raceColumnName, waypoints);
TrackedRace mockedTrackedRace = createSpyedTrackedRace(mockedRegatta, course, timePoint, boatClass);
raceColumn.setTrackedRace(fleet, mockedTrackedRace);
Set<String> raceColumnNames = new HashSet<>();
raceColumnNames.add(raceColumnName);
int[] ruleRaw = { 5, 3, 2 };
ThresholdBasedResultDiscardingRule rule = new ThresholdBasedResultDiscardingRuleImpl(ruleRaw);
Leaderboard leaderboard = new RegattaLeaderboardImpl(mockedRegatta, rule);
DomainFactory baseDomainFactory = new DomainFactoryImpl((srlid)->null);
LeaderboardDTO leaderboardDTO = leaderboard.getLeaderboardDTO(timePoint, raceColumnNames, false,
trackedRegattaRegistry, baseDomainFactory, /* fillNetPointsUncorrected */ false);
assertEquals(6, leaderboardDTO.rows.values().iterator().next().fieldsByRaceColumnName.values().iterator()
.next().legDetails.size());
course.removeWaypoint(2);
course.removeWaypoint(3);
leaderboardDTO = leaderboard.getLeaderboardDTO(timePoint, raceColumnNames, false, trackedRegattaRegistry,
baseDomainFactory, /* fillNetPointsUncorrected */ false);
assertEquals(4, leaderboardDTO.rows.values().iterator().next().fieldsByRaceColumnName.values().iterator()
.next().legDetails.size());
}
private TrackedRace createSpyedTrackedRace(Regatta regatta, Course course, TimePoint timePoint, BoatClass boatClass) {
TrackedRegatta mockedTrackedRegatta = createMockedTrackedRegatta(regatta);
RaceDefinition mockedRace = createMockedRace(course, boatClass);
TrackedRace spyedTrackedRace = spy(new DynamicTrackedRaceImpl(mockedTrackedRegatta, mockedRace,
new HashSet<Sideline>(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, 5000, 20000, 20000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new,
mock(RaceLogResolver.class)));
return spyedTrackedRace;
}
private RaceDefinition createMockedRace(Course course, BoatClass boatClass) {
RaceDefinition mockedRaceDefinition = mock(RaceDefinition.class);
when(mockedRaceDefinition.getCompetitors()).thenReturn(new HashSet<Competitor>());
when(mockedRaceDefinition.getCourse()).thenReturn(course);
when(mockedRaceDefinition.getBoatClass()).thenReturn(new BoatClassImpl("TestClass", true));
when(mockedRaceDefinition.getName()).thenReturn("TestRace");
Iterable<Competitor> competitorSet = createCompetitorSet(boatClass);
when(mockedRaceDefinition.getCompetitors()).thenReturn(competitorSet);
return mockedRaceDefinition;
}
private Iterable<Competitor> createCompetitorSet(BoatClass boatClass) {
Set<Competitor> competitors = new HashSet<>();
DynamicBoat mockedBoat = mock(DynamicBoat.class);
when(mockedBoat.getBoatClass()).thenReturn(boatClass);
competitors.add(new CompetitorImpl(UUID.randomUUID(), "TestCompetitor", Color.BLACK, null, null,
mock(DynamicTeam.class), mockedBoat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
return competitors;
}
private TrackedRegatta createMockedTrackedRegatta(Regatta regatta) {
TrackedRegatta mockedTrackedRegatta = mock(DynamicTrackedRegatta.class);
when(mockedTrackedRegatta.getRegatta()).thenReturn(regatta);
return mockedTrackedRegatta;
}
private Series createSeries(TrackedRegattaRegistry trackedRegattaRegistry, Fleet fleet) {
Set<Fleet> fleets = new HashSet<>();
fleets.add(fleet);
Series series = new SeriesImpl("TestSeries", false, fleets, new HashSet<String>(), trackedRegattaRegistry);
return series;
}
}
@@ -193,7 +193,7 @@ public class OfflineSerializationTest extends AbstractSerializationTest {
/* dateOfBirth */ null, "This is famous "+competitorName)),
new PersonImpl("Rigo van Maas", senderDomainFactory.getOrCreateNationality("GER"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
senderDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
senderDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
Competitor receiversCompetitor1 = cloneBySerialization(sendersCompetitor1, receiverDomainFactory);
Competitor receiversSecondCopyOfCompetitor1 = cloneBySerialization(sendersCompetitor1, receiverDomainFactory);
assertSame(receiversCompetitor1, receiversSecondCopyOfCompetitor1);
@@ -118,7 +118,7 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest {
DynamicPerson p = new PersonImpl(competitorName, /* nationality */ null, /* dateOfBirth */ null, /* description */ null);
DynamicTeam t = new TeamImpl(competitorName, Collections.singleton(p), /* coach */ null);
Competitor c = new CompetitorImpl(competitorName, competitorName, Color.RED, null, null, t, new BoatImpl(competitorName,
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = readTrack(c, KIELER_WOCHE);
if (track != null) {
tracks.put(c, track);
@@ -40,7 +40,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace {
/* dateOfBirth */null, "This is famous Wolfgang Hunger")), new PersonImpl("Rigo van Maas",
new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("Wolfgang Hunger's boat",
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", Collections.singleton(competitor),
new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime())));
}
@@ -69,7 +69,7 @@ public abstract class TrackBasedTest {
/* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas",
new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
new BoatClassImpl("505", /* typicallyStartsUpwind */true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
new BoatClassImpl("505", /* typicallyStartsUpwind */true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
}
/**
@@ -278,7 +278,7 @@ public class WindTest {
/* dateOfBirth */null, "This is famous " + "Test Competitor")), new PersonImpl("Rigo van Maas",
new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("Test Competitor" + "'s boat",
new BoatClassImpl("505", /* typicallyStartsUpwind */true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
new BoatClassImpl("505", /* typicallyStartsUpwind */true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
final BoatClass boatClass = domainFactory.getOrCreateBoatClass("ESS40");
DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl(
new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE,
@@ -46,9 +46,9 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
public class AbstractMockedRaceMarkPassingTest {
final BoatClassImpl boatClass = new BoatClassImpl("boat", true, "boat", new MeterDistance(10), new MeterDistance(5), null);
protected Competitor ron = new CompetitorImpl("Ron", "Ron", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
protected Competitor tom = new CompetitorImpl("Tom", "Tom", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
protected Competitor ben = new CompetitorImpl("Ben", "Ben", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
protected Competitor ron = new CompetitorImpl("Ron", "Ron", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
protected Competitor tom = new CompetitorImpl("Tom", "Tom", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
protected Competitor ben = new CompetitorImpl("Ben", "Ben", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
protected Mark m = new MarkImpl("Mark");
protected Mark gate1 = new MarkImpl("Gate1");
@@ -79,7 +79,7 @@ public interface DomainFactory {
com.sap.sailing.domain.base.Competitor getOrCreateCompetitor(ICompetitor competitor);
com.sap.sailing.domain.base.Competitor getOrCreateCompetitor(UUID competitorId, String competitorClassName,
String nationalityAsString, String name, String shortName, float timeOnTimeFactor, float timeOnDistanceAllowanceInSecondsPerNauticalMile);
String nationalityAsString, String name, String shortName, float timeOnTimeFactor, float timeOnDistanceAllowanceInSecondsPerNauticalMile, String searchTag);
/**
* Looks up or, if not found, creates a {@link Nationality} object and re-uses <code>threeLetterIOCCode</code> also as the
@@ -241,14 +241,14 @@ public class DomainFactoryImpl implements DomainFactory {
final String name = competitor.getName();
final String shortName = competitor.getShortName();
Competitor result = getOrCreateCompetitor(competitorId, competitorClassName, nationalityAsString, name,
shortName, competitor.getHandicapToT(), competitor.getHandicapToD());
shortName, competitor.getHandicapToT(), competitor.getHandicapToD(), null);
return result;
}
@Override
public Competitor getOrCreateCompetitor(final UUID competitorId, final String competitorClassName,
final String nationalityAsString, final String name, final String shortName, float timeOnTimeFactor,
float timeOnDistanceAllowanceInSecondsPerNauticalMile) {
float timeOnDistanceAllowanceInSecondsPerNauticalMile, String searchTag) {
CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore();
Competitor result = competitorStore.getExistingCompetitorById(competitorId);
if (result == null || competitorStore.isCompetitorToUpdateDuringGetOrCreate(result)) {
@@ -265,7 +265,7 @@ public class DomainFactoryImpl implements DomainFactory {
DynamicBoat boat = new BoatImpl(shortName, boatClass, shortName);
result = competitorStore.getOrCreateCompetitor(competitorId, name, null /* displayColor */,
null /* email */, null /* flagImag */, team, boat, (double) timeOnTimeFactor,
new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)));
new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag);
}
return result;
}
@@ -1,21 +1,21 @@
package com.sap.sailing.domain.base.impl;
import java.io.Serializable;
import java.net.URI;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
public interface DynamicCompetitorStore extends CompetitorStore {
@Override
DynamicCompetitor getExistingCompetitorById(Serializable competitorId);
@Override
DynamicCompetitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email, URI flagImage,
DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile);
@Override
Iterable<? extends DynamicCompetitor> getCompetitors();
}
package com.sap.sailing.domain.base.impl;
import java.io.Serializable;
import java.net.URI;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
public interface DynamicCompetitorStore extends CompetitorStore {
@Override
DynamicCompetitor getExistingCompetitorById(Serializable competitorId);
@Override
DynamicCompetitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email, URI flagImage,
DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag);
@Override
Iterable<? extends DynamicCompetitor> getCompetitors();
}
@@ -124,6 +124,11 @@ public class LeaderboardCacheManager {
//ignore (email not shown in leaderboard)
}
@Override
public void searchTagChanged(String oldSearchTag, String newSearchTag) {
//ignore (email not shown in leaderboard)
}
@Override
public void flagImageChanged(URI oldFlagImageURL, URI newFlagImageURL) {
removeFromCache(leaderboard);
@@ -131,7 +131,7 @@ public abstract class AbstractRankingMetric implements RankingMetric {
* Helper instance used to encode <code>null</code> values in {@link ConcurrentHashMap} instances which do not accept
* <code>null</code> as key nor value.
*/
private final static Competitor NULL_COMPETITOR = new CompetitorImpl(null, null, null, null, null, null, null, null, null);
private final static Competitor NULL_COMPETITOR = new CompetitorImpl(null, null, null, null, null, null, null, null, null, null);
public abstract class AbstractRankingInfo implements RankingMetric.RankingInfo {
private static final long serialVersionUID = 6845168655725234325L;
@@ -100,6 +100,11 @@ public class DummyMarkPassingWithTimePointOnly implements MarkPassing {
public Duration getTimeOnDistanceAllowancePerNauticalMile() {
return null;
}
@Override
public String getSearchTag() {
return null;
}
};
}
@@ -72,7 +72,7 @@
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-incremental -workDir &quot;${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work&quot; -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9876 -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/EmbeddedMapAndWindChart com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup -startupUrl /gwt/AutoPlay.html com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -workDir &quot;${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work&quot; -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9876 -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/EmbeddedMapAndWindChart com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup -startupUrl /gwt/AutoPlay.html com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m"/>
</launchConfiguration>
@@ -45,6 +45,7 @@ public class CompetitorEditDialog extends DataEntryDialog<CompetitorDTO> {
private final ListBox threeLetterIocCountryCode;
private final TextBox sailId;
private final TextBox email;
private final TextBox searchTag;
private final StringMessages stringMessages;
private final URLFieldWithFileUpload flagImageURL;
private final URLFieldWithFileUpload imageUrlAndUploadComposite;
@@ -58,7 +59,7 @@ public class CompetitorEditDialog extends DataEntryDialog<CompetitorDTO> {
* The 'competitorToEdit' parameter contains the competitor which should be changed or initialized.
* @param boatClass
* The boat class is the default shown boat class for new competitors. Set <code>null</code> if your competitor is
* already initialized or you don´t want a default boat class.
* already initialized or you don�t want a default boat class.
*/
public CompetitorEditDialog(final StringMessages stringMessages, CompetitorDTO competitorToEdit,
DialogCallback<CompetitorDTO> callback, String boatClass) {
@@ -102,6 +103,7 @@ public class CompetitorEditDialog extends DataEntryDialog<CompetitorDTO> {
this.name = createTextBox(competitorToEdit.getName());
name.ensureDebugId("NameTextBox");
this.email = createTextBox(competitorToEdit.getEmail());
this.searchTag = createTextBox(competitorToEdit.getSearchTag());
this.displayColorTextBox = createTextBox(competitorToEdit.getColor() == null ? "" : competitorToEdit.getColor().getAsHtml());
this.threeLetterIocCountryCode = createListBox(/* isMultipleSelect */ false);
CountryCodeFactory ccf = CountryCodeFactory.INSTANCE;
@@ -198,13 +200,13 @@ public class CompetitorEditDialog extends DataEntryDialog<CompetitorDTO> {
imageUrlAndUploadComposite.getURL(), flagImageURL.getURL(), boat, boatClass,
timeOnTimeFactor.getValue(),
timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue() == null ? null :
new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue()*1000)));
new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue()*1000)), searchTag.getValue());
return result;
}
@Override
protected Widget getAdditionalWidget() {
Grid result = new Grid(10, 2);
Grid result = new Grid(11, 2);
result.setWidget(0, 0, new Label(stringMessages.name()));
result.setWidget(0, 1, name);
result.setWidget(1, 0, new Label(stringMessages.sailNumber()));
@@ -215,16 +217,18 @@ public class CompetitorEditDialog extends DataEntryDialog<CompetitorDTO> {
result.setWidget(3, 1, displayColorTextBox);
result.setWidget(4, 0, new Label(stringMessages.email()));
result.setWidget(4, 1, email);
result.setWidget(5, 0, new Label(stringMessages.boatClass()));
result.setWidget(5, 1, boatClassName);
result.setWidget(6, 0, new Label(stringMessages.flagImageURL()));
result.setWidget(6, 1, flagImageURL);
result.setWidget(7, 0, new Label(stringMessages.imageURL()));
result.setWidget(7, 1, imageUrlAndUploadComposite);
result.setWidget(8, 0, new Label(stringMessages.timeOnTimeFactor()));
result.setWidget(8, 1, timeOnTimeFactor);
result.setWidget(9, 0, new Label(stringMessages.timeOnDistanceAllowanceInSecondsPerNauticalMile()));
result.setWidget(9, 1, timeOnDistanceAllowanceInSecondsPerNauticalMile);
result.setWidget(5, 0, new Label(stringMessages.searchTag()));
result.setWidget(5, 1, searchTag);
result.setWidget(6, 0, new Label(stringMessages.boatClass()));
result.setWidget(6, 1, boatClassName);
result.setWidget(7, 0, new Label(stringMessages.flagImageURL()));
result.setWidget(7, 1, flagImageURL);
result.setWidget(8, 0, new Label(stringMessages.imageURL()));
result.setWidget(8, 1, imageUrlAndUploadComposite);
result.setWidget(9, 0, new Label(stringMessages.timeOnTimeFactor()));
result.setWidget(9, 1, timeOnTimeFactor);
result.setWidget(10, 0, new Label(stringMessages.timeOnDistanceAllowanceInSecondsPerNauticalMile()));
result.setWidget(10, 1, timeOnDistanceAllowanceInSecondsPerNauticalMile);
return result;
}
@@ -170,6 +170,20 @@ public class CompetitorTableWrapper<S extends RefreshableSelectionModel<Competit
}
});
TextColumn<CompetitorDTO> competitorSearchTagColumn = new TextColumn<CompetitorDTO>() {
@Override
public String getValue(CompetitorDTO competitor) {
return competitor.getSearchTag();
}
};
competitorSearchTagColumn.setSortable(true);
competitorColumnListHandler.setComparator(competitorSearchTagColumn, new Comparator<CompetitorDTO>() {
@Override
public int compare(CompetitorDTO o1, CompetitorDTO o2) {
return new NaturalComparator(false).compare(o1.getSearchTag(), o2.getSearchTag());
}
});
TextColumn<CompetitorDTO> timeOnTimeFactorColumn = new TextColumn<CompetitorDTO>() {
@Override
public String getValue(CompetitorDTO competitor) {
@@ -212,6 +226,7 @@ public class CompetitorTableWrapper<S extends RefreshableSelectionModel<Competit
string.add(t.getSailID());
string.add(t.getBoatClass().getName());
string.add(t.getIdAsString());
string.add(t.getSearchTag());
return string;
}
};
@@ -241,6 +256,7 @@ public class CompetitorTableWrapper<S extends RefreshableSelectionModel<Competit
table.addColumn(displayColorColumn, stringMessages.color());
table.addColumn(imageColumn, stringMessages.image());
table.addColumn(competitorEMailColumn, stringMessages.email());
table.addColumn(competitorSearchTagColumn, stringMessages.searchTag());
table.addColumn(competitorIdColumn, stringMessages.id());
table.addColumn(competitorActionColumn, stringMessages.actions());
table.ensureDebugId("CompetitorsTable");
@@ -1006,6 +1006,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c
String eMailMustNotBeEmpty();
String emailAddress();
String password();
String searchTag();
String doYouReallyWantToRemoveLeaderboard(String name);
String metaLeaderboardCannotBeChanged();
String failedToSetNewStartTime();
@@ -977,6 +977,7 @@ successfullyRemoveIgtimiAccount=Successfully removed Igtimi account for user {0}
eMailMustNotBeEmpty=e-Mail address must not be empty
emailAddress=e-mail address
password=Password
searchTag=Search tag
doYouReallyWantToRemoveLeaderboard=Do you really want to remove the leaderboard: ''{0}''?
metaLeaderboardCannotBeChanged=This is a meta leaderboard. It can''t be changed here.
failedToSetNewStartTime=Failed to set new start time. This can happen when the same start time is already present in the race log or someone has added a start time that is newer (in terms of a pass id and logical time) than the one that you just added.
@@ -968,6 +968,7 @@ successfullyRemoveIgtimiAccount=Zugang zum Igtimi-Benutzerkonto {0} erfolgreich
eMailMustNotBeEmpty=e-Mailadresse darf nicht leer sein
emailAddress=e-Mailadresse
password=Kennwort
searchTag=Suchhilfe
doYouReallyWantToRemoveLeaderboard=Möchten Sie wirklich die Ergebnlisliste ''{0}'' löschen?
metaLeaderboardCannotBeChanged=Dies ist ein Meta-Leaderboard, das hier nicht geändert werden kann.
failedToSetNewStartTime=Neue Startzeit konnte nicht gesetzt werden.
@@ -950,6 +950,7 @@ successfullyRemoveIgtimiAccount=Учетная запись Igtimi для пол
eMailMustNotBeEmpty=Адрес электронной почты не должен быть пустым
emailAddress=адрес электронной почты
password=Пароль
searchTag=Search tag
doYouReallyWantToRemoveLeaderboard=Вы действительно хотите удалить таблицу лидеров: ''{0}''?
metaLeaderboardCannotBeChanged=Это мета таблица лидеров. Ее нельзя изменить здесь.
failedToSetNewStartTime=Ошибка при установке нового времени старта.
@@ -973,6 +973,7 @@ successfullyRemoveIgtimiAccount=已成功移除用户{0}的 Igtimi 账户
eMailMustNotBeEmpty=电子邮件地址不得为空
emailAddress=电子邮件地址
password=密码
searchTag=Search tag
doYouReallyWantToRemoveLeaderboard=是否确定移除积分榜: ''{0}''?
metaLeaderboardCannotBeChanged=此为元积分榜。无法在此处更改。
failedToSetNewStartTime=设置新开始时间失败。 相同的开始时间可能已存在于比赛轮次日志中或某人已添加(场次编号和逻辑时间)更新的开始时间。
@@ -973,6 +973,7 @@ successfullyRemoveIgtimiAccount=已成功移除用户{0}的 Igtimi 账户
eMailMustNotBeEmpty=电子邮件地址不得为空
emailAddress=电子邮件地址
password=密码
searchTag=Search tag
doYouReallyWantToRemoveLeaderboard=是否确定移除积分榜: ''{0}''?
metaLeaderboardCannotBeChanged=此为元积分榜。无法在此处更改。
failedToSetNewStartTime=设置新开始时间失败。 相同的开始时间可能已存在于比赛轮次日志中或某人已添加(场次编号和逻辑时间)更新的开始时间。
@@ -4718,7 +4718,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
competitor.getColor(), competitor.getEmail(),
competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, boat,
competitor.getTimeOnTimeFactor(),
competitor.getTimeOnDistanceAllowancePerNauticalMile()));
competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag()));
} else {
result = getBaseDomainFactory().convertToCompetitorDTO(
getService().apply(
@@ -4727,7 +4727,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()),
competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()),
competitor.getTimeOnTimeFactor(),
competitor.getTimeOnDistanceAllowancePerNauticalMile())));
competitor.getTimeOnDistanceAllowancePerNauticalMile(),
competitor.getSearchTag())));
}
return result;
}
@@ -75,7 +75,7 @@ public class StoreAndLoadDeviceIdentifierTest extends AbstractMongoDBTest {
private DeviceIdentifier storeAndLoad(DeviceIdentifier device, TypeBasedServiceFinderFactory forStoring, TypeBasedServiceFinderFactory forLoading) {
createFactories(forStoring);
Competitor c = DomainFactory.INSTANCE.getOrCreateCompetitor("a", "a", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
Competitor c = DomainFactory.INSTANCE.getOrCreateCompetitor("a", "a", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(now(), now(), author, 0,
c, device, now(), now()));
createFactories(forLoading);
@@ -213,7 +213,7 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest {
RaceLogRegisterCompetitorEvent expectedEvent = new RaceLogRegisterCompetitorEventImpl(expectedEventTime,
expectedEventTime, author, expectedId, expectedPassId, DomainFactory.INSTANCE.getOrCreateCompetitor(
"comp", "comp", null, null, null, null, null,
/* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null));
/* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null));
DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent);
RaceLogRegisterCompetitorEvent actualEvent = loadEvent(dbObject);
@@ -1,122 +1,122 @@
package com.sap.sailing.mongodb.test;
import static org.junit.Assert.assertEquals;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.MongoException;
import com.mongodb.WriteConcern;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sailing.domain.persistence.impl.CollectionNames;
import com.sap.sailing.domain.test.AbstractLeaderboardTest;
import com.sap.sse.common.Util;
public class StoreCompetitorTest extends AbstractMongoDBTest {
private DomainFactory domainFactory;
public StoreCompetitorTest() throws UnknownHostException, MongoException {
super();
}
@Before
public void setUp() {
// clear the domainFactory competitor store for a clean start:
domainFactory = new DomainFactoryImpl((srlid)->null);
}
private void dropCompetitorCollection() {
DB db = getMongoService().getDB();
DBCollection competitorCollection = db.getCollection(CollectionNames.COMPETITORS.name());
competitorCollection.setWriteConcern(WriteConcern.SAFE); // ensure that the drop() has happened
competitorCollection.drop();
}
@Test
public void testStoreAndUpdateCompetitor() throws URISyntaxException {
URI flagImageURI1 = new URI("http://www.sapsailing/flagimage1.jpg");
URI flagImageURI2 = new URI("http://www.sapsailing/flagimage2.jpg");
String competitorName1 = "Hasso";
String competitorName2 = "Hasso Plattner";
MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService());
DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory);
dropCompetitorCollection();
DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor(competitorName1);
c.setFlagImage(flagImageURI1);
mongoObjectFactory.storeCompetitor(c);
Collection<Competitor> allCompetitors = domainObjectFactory.loadAllCompetitors();
assertEquals(1, Util.size(allCompetitors));
DynamicCompetitor loadedCompetitor = (DynamicCompetitor) allCompetitors.iterator().next();
assertEquals(flagImageURI1, loadedCompetitor.getFlagImage());
assertEquals(competitorName1, loadedCompetitor.getName());
loadedCompetitor.setName(competitorName2);
loadedCompetitor.setFlagImage(flagImageURI2);
mongoObjectFactory.storeCompetitor(loadedCompetitor);
allCompetitors = domainObjectFactory.loadAllCompetitors();
assertEquals(1, Util.size(allCompetitors));
loadedCompetitor = (DynamicCompetitor) allCompetitors.iterator().next();
assertEquals(flagImageURI2, loadedCompetitor.getFlagImage());
assertEquals(competitorName2, loadedCompetitor.getName());
}
@Test
public void testStoreAndUpdateCompetitorWithUUIDAsId() {
MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService());
DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory);
dropCompetitorCollection();
DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor("Hasso", UUID.randomUUID());
mongoObjectFactory.storeCompetitor(c);
assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors()));
c.setName("Hasso Plattner");
mongoObjectFactory.storeCompetitor(c);
assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors()));
}
@Test
public void testStoreAndRemoveCompetitor() {
MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService());
DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory);
dropCompetitorCollection();
DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor("Hasso");
mongoObjectFactory.storeCompetitor(c);
assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors()));
mongoObjectFactory.removeCompetitor(c);
assertEquals(0, Util.size(domainObjectFactory.loadAllCompetitors()));
}
@Test
public void testStoreAndRemoveCompetitorWithUUIDAsId() {
MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService());
DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory);
dropCompetitorCollection();
DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor("Hasso", UUID.randomUUID());
mongoObjectFactory.storeCompetitor(c);
assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors()));
mongoObjectFactory.removeCompetitor(c);
assertEquals(0, Util.size(domainObjectFactory.loadAllCompetitors()));
}
}
package com.sap.sailing.mongodb.test;
import static org.junit.Assert.assertEquals;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.MongoException;
import com.mongodb.WriteConcern;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sailing.domain.persistence.impl.CollectionNames;
import com.sap.sailing.domain.test.AbstractLeaderboardTest;
import com.sap.sse.common.Util;
public class StoreCompetitorTest extends AbstractMongoDBTest {
private DomainFactory domainFactory;
public StoreCompetitorTest() throws UnknownHostException, MongoException {
super();
}
@Before
public void setUp() {
// clear the domainFactory competitor store for a clean start:
domainFactory = new DomainFactoryImpl((srlid)->null);
}
private void dropCompetitorCollection() {
DB db = getMongoService().getDB();
DBCollection competitorCollection = db.getCollection(CollectionNames.COMPETITORS.name());
competitorCollection.setWriteConcern(WriteConcern.SAFE); // ensure that the drop() has happened
competitorCollection.drop();
}
@Test
public void testStoreAndUpdateCompetitor() throws URISyntaxException {
URI flagImageURI1 = new URI("http://www.sapsailing/flagimage1.jpg");
URI flagImageURI2 = new URI("http://www.sapsailing/flagimage2.jpg");
String competitorName1 = "Hasso";
String competitorName2 = "Hasso Plattner";
MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService());
DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory);
dropCompetitorCollection();
DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor(competitorName1);
c.setFlagImage(flagImageURI1);
mongoObjectFactory.storeCompetitor(c);
Collection<Competitor> allCompetitors = domainObjectFactory.loadAllCompetitors();
assertEquals(1, Util.size(allCompetitors));
DynamicCompetitor loadedCompetitor = (DynamicCompetitor) allCompetitors.iterator().next();
assertEquals(flagImageURI1, loadedCompetitor.getFlagImage());
assertEquals(competitorName1, loadedCompetitor.getName());
loadedCompetitor.setName(competitorName2);
loadedCompetitor.setFlagImage(flagImageURI2);
mongoObjectFactory.storeCompetitor(loadedCompetitor);
allCompetitors = domainObjectFactory.loadAllCompetitors();
assertEquals(1, Util.size(allCompetitors));
loadedCompetitor = (DynamicCompetitor) allCompetitors.iterator().next();
assertEquals(flagImageURI2, loadedCompetitor.getFlagImage());
assertEquals(competitorName2, loadedCompetitor.getName());
}
@Test
public void testStoreAndUpdateCompetitorWithUUIDAsId() {
MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService());
DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory);
dropCompetitorCollection();
DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor("Hasso", UUID.randomUUID());
mongoObjectFactory.storeCompetitor(c);
assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors()));
c.setName("Hasso Plattner");
mongoObjectFactory.storeCompetitor(c);
assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors()));
}
@Test
public void testStoreAndRemoveCompetitor() {
MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService());
DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory);
dropCompetitorCollection();
DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor("Hasso");
mongoObjectFactory.storeCompetitor(c);
assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors()));
mongoObjectFactory.removeCompetitor(c);
assertEquals(0, Util.size(domainObjectFactory.loadAllCompetitors()));
}
@Test
public void testStoreAndRemoveCompetitorWithUUIDAsId() {
MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService());
DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory);
dropCompetitorCollection();
DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor("Hasso", UUID.randomUUID());
mongoObjectFactory.storeCompetitor(c);
assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors()));
mongoObjectFactory.removeCompetitor(c);
assertEquals(0, Util.size(domainObjectFactory.loadAllCompetitors()));
}
}
@@ -60,7 +60,7 @@ public class StoreGPSFixTrackTest extends AbstractMongoDBTest {
TypeBasedServiceFinderFactory factory = new MockSmartphoneImeiServiceFinderFactory();
AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0);
Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark");
MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService(), factory);
DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE, factory);
@@ -820,7 +820,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest
regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new);
List<Competitor> competitors = new ArrayList<Competitor>();
competitors.add(new CompetitorImpl("Axel", "Axel Uhl", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null));
competitors.add(new CompetitorImpl("Axel", "Axel Uhl", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
Iterable<Waypoint> waypoints = Collections.emptyList();
Course course = new CourseImpl("Course", waypoints);
@@ -116,12 +116,12 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe
Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, null, new TeamImpl("STG", Collections.singleton(
new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null, null,
new TeamImpl("STG", Collections.singleton(
new PersonImpl("Hasso Plattner", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
final String raceColumnName1 = "My First Race 1";
MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true);
raceWithTwoCompetitors.addCompetitor(hasso);
@@ -172,12 +172,12 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe
Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, null, new TeamImpl("STG", Collections.singleton(
new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null, null,
new TeamImpl("STG", Collections.singleton(
new PersonImpl("Hasso Plattner", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
final String raceColumnName1 = "My First Race 1";
MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true);
raceWithTwoCompetitors.addCompetitor(hasso);
@@ -228,12 +228,12 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe
Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, null, new TeamImpl("STG", Collections.singleton(
new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null,null,
new TeamImpl("STG", Collections.singleton(
new PersonImpl("Hasso Plattner", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
final String raceColumnName1 = "My First Race 1";
MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true);
raceWithTwoCompetitors.addCompetitor(hasso);
@@ -81,7 +81,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
new TeamImpl("STG", Collections.singleton(
new PersonImpl("Hasso Plattner", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
final String raceColumnName1 = "My First Race 1";
MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true);
raceWithTwoCompetitors.addCompetitor(hasso);
@@ -355,7 +355,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true);
TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true);
leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false);
@@ -382,7 +382,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
Competitor competitor = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, null, new TeamImpl("STG", Collections.singleton(
new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
return competitor;
}
@@ -298,7 +298,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD
public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningConfirmedEvent() {
Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team",
Color.RED, "someone@nowhere.de", null, null, null,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
CompetitorResults storedPositioningList = new CompetitorResultsImpl();
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */
1, MaxPointsReason.NONE, /* score */ null, /* finishingTimePoint */null, /* comment */null));
@@ -322,7 +322,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD
public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningConfirmedEventWithContents() {
Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team",
Color.RED, "someone@nowhere.de", null, null, null,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
CompetitorResults storedPositioningList = new CompetitorResultsImpl();
final TimePoint finishingTimePoint = MillisecondsTimePoint.now();
final String comment = "This is a comment";
@@ -392,7 +392,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD
@Test
public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningListChangeEvent() {
Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED,
"someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
"someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
CompetitorResults storedPositioningList = new CompetitorResultsImpl();
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */
1, MaxPointsReason.NONE, /* score */ null, /* finishingTimePoint */null, /* comment */null));
@@ -200,7 +200,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin
@Test
public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningListChangeEvent() {
Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED,
"someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
"someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
CompetitorResults storedPositioningList = new CompetitorResultsImpl();
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null));
RaceLogFinishPositioningListChangedEvent event = new RaceLogFinishPositioningListChangedEventImpl(now, author, 0, storedPositioningList);
@@ -224,7 +224,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin
@Test
public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningConfirmedEvent() {
Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED,
"someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
"someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
CompetitorResults storedPositioningList = new CompetitorResultsImpl();
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null));
RaceLogFinishPositioningConfirmedEvent event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, storedPositioningList);
@@ -1,99 +1,100 @@
package com.sap.sailing.server.gateway.deserialization.impl;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.UUID;
import java.util.logging.Logger;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorFactory;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer;
import com.sap.sse.common.Color;
import com.sap.sse.common.impl.MillisecondsDurationImpl;
import com.sap.sse.common.impl.RGBColor;
public class CompetitorJsonDeserializer implements JsonDeserializer<Competitor> {
protected final CompetitorFactory competitorStore;
protected final JsonDeserializer<DynamicTeam> teamJsonDeserializer;
protected final JsonDeserializer<DynamicBoat> boatJsonDeserializer;
private static final Logger logger = Logger.getLogger(CompetitorJsonDeserializer.class.getName());
public static CompetitorJsonDeserializer create(SharedDomainFactory baseDomainFactory) {
return new CompetitorJsonDeserializer(baseDomainFactory, new TeamJsonDeserializer(new PersonJsonDeserializer(
new NationalityJsonDeserializer(baseDomainFactory))), new BoatJsonDeserializer(new BoatClassJsonDeserializer(baseDomainFactory)));
}
public CompetitorJsonDeserializer(CompetitorStore store) {
this(store, null, /* boatDeserializer */ null);
}
public CompetitorJsonDeserializer(CompetitorFactory competitorStore, JsonDeserializer<DynamicTeam> teamJsonDeserializer, JsonDeserializer<DynamicBoat> boatDeserializer) {
this.competitorStore = competitorStore;
this.teamJsonDeserializer = teamJsonDeserializer;
this.boatJsonDeserializer = boatDeserializer;
}
@Override
public Competitor deserialize(JSONObject object) throws JsonDeserializationException {
Serializable competitorId = (Serializable) object.get(CompetitorJsonSerializer.FIELD_ID);
try {
Class<?> idClass = Class.forName((String) object.get(CompetitorJsonConstants.FIELD_ID_TYPE));
if (Number.class.isAssignableFrom(idClass)) {
Constructor<?> constructorFromString = idClass.getConstructor(String.class);
competitorId = (Serializable) constructorFromString.newInstance(competitorId.toString());
} else if (UUID.class.isAssignableFrom(idClass)) {
competitorId = Helpers.tryUuidConversion(competitorId);
}
String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME);
String displayColorAsString = (String) object.get(CompetitorJsonConstants.FIELD_DISPLAY_COLOR);
String email = (String) object.get(CompetitorJsonConstants.FIELD_EMAIL);
URI flagImageURI = null;
String flagImageURIAsString = (String) object.get(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI);
if (flagImageURIAsString != null) {
try {
flagImageURI = URI.create(flagImageURIAsString);
} catch (IllegalArgumentException e) {
logger.warning("Illegal flag image URI " + e.getMessage());
}
}
final Color displayColor;
if (displayColorAsString == null || displayColorAsString.isEmpty()) {
displayColor = null;
} else {
displayColor = new RGBColor(displayColorAsString);
}
DynamicTeam team = null;
DynamicBoat boat = null;
if (teamJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_TEAM) != null) {
team = teamJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object,
CompetitorJsonConstants.FIELD_TEAM));
}
if (boatJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_BOAT) != null) {
boat = boatJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object,
CompetitorJsonConstants.FIELD_BOAT));
}
final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR);
final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object
.get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE);
Competitor competitor = competitorStore.getOrCreateCompetitor(competitorId, name, displayColor, email,
flagImageURI, team, boat, timeOnTimeFactor,
timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null :
new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)));
return competitor;
} catch (Exception e) {
throw new JsonDeserializationException(e);
}
}
}
package com.sap.sailing.server.gateway.deserialization.impl;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.UUID;
import java.util.logging.Logger;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorFactory;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer;
import com.sap.sse.common.Color;
import com.sap.sse.common.impl.MillisecondsDurationImpl;
import com.sap.sse.common.impl.RGBColor;
public class CompetitorJsonDeserializer implements JsonDeserializer<Competitor> {
protected final CompetitorFactory competitorStore;
protected final JsonDeserializer<DynamicTeam> teamJsonDeserializer;
protected final JsonDeserializer<DynamicBoat> boatJsonDeserializer;
private static final Logger logger = Logger.getLogger(CompetitorJsonDeserializer.class.getName());
public static CompetitorJsonDeserializer create(SharedDomainFactory baseDomainFactory) {
return new CompetitorJsonDeserializer(baseDomainFactory, new TeamJsonDeserializer(new PersonJsonDeserializer(
new NationalityJsonDeserializer(baseDomainFactory))), new BoatJsonDeserializer(new BoatClassJsonDeserializer(baseDomainFactory)));
}
public CompetitorJsonDeserializer(CompetitorStore store) {
this(store, null, /* boatDeserializer */ null);
}
public CompetitorJsonDeserializer(CompetitorFactory competitorStore, JsonDeserializer<DynamicTeam> teamJsonDeserializer, JsonDeserializer<DynamicBoat> boatDeserializer) {
this.competitorStore = competitorStore;
this.teamJsonDeserializer = teamJsonDeserializer;
this.boatJsonDeserializer = boatDeserializer;
}
@Override
public Competitor deserialize(JSONObject object) throws JsonDeserializationException {
Serializable competitorId = (Serializable) object.get(CompetitorJsonSerializer.FIELD_ID);
try {
Class<?> idClass = Class.forName((String) object.get(CompetitorJsonConstants.FIELD_ID_TYPE));
if (Number.class.isAssignableFrom(idClass)) {
Constructor<?> constructorFromString = idClass.getConstructor(String.class);
competitorId = (Serializable) constructorFromString.newInstance(competitorId.toString());
} else if (UUID.class.isAssignableFrom(idClass)) {
competitorId = Helpers.tryUuidConversion(competitorId);
}
String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME);
String displayColorAsString = (String) object.get(CompetitorJsonConstants.FIELD_DISPLAY_COLOR);
String email = (String) object.get(CompetitorJsonConstants.FIELD_EMAIL);
String searchTag = (String) object.get(CompetitorJsonConstants.FIELD_SEARCHTAG);
URI flagImageURI = null;
String flagImageURIAsString = (String) object.get(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI);
if (flagImageURIAsString != null) {
try {
flagImageURI = URI.create(flagImageURIAsString);
} catch (IllegalArgumentException e) {
logger.warning("Illegal flag image URI " + e.getMessage());
}
}
final Color displayColor;
if (displayColorAsString == null || displayColorAsString.isEmpty()) {
displayColor = null;
} else {
displayColor = new RGBColor(displayColorAsString);
}
DynamicTeam team = null;
DynamicBoat boat = null;
if (teamJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_TEAM) != null) {
team = teamJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object,
CompetitorJsonConstants.FIELD_TEAM));
}
if (boatJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_BOAT) != null) {
boat = boatJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object,
CompetitorJsonConstants.FIELD_BOAT));
}
final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR);
final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object
.get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE);
Competitor competitor = competitorStore.getOrCreateCompetitor(competitorId, name, displayColor, email,
flagImageURI, team, boat, timeOnTimeFactor,
timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null :
new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag);
return competitor;
} catch (Exception e) {
throw new JsonDeserializationException(e);
}
}
}
@@ -55,6 +55,7 @@ public class CompetitorJsonSerializer implements JsonSerializer<Competitor> {
result.put(CompetitorJsonConstants.FIELD_NAME, competitor.getName());
result.put(CompetitorJsonConstants.FIELD_DISPLAY_COLOR, competitor.getColor() == null ? null : competitor.getColor().getAsHtml());
result.put(CompetitorJsonConstants.FIELD_EMAIL, competitor.getEmail());
result.put(CompetitorJsonConstants.FIELD_SEARCHTAG, competitor.getSearchTag());
result.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitor.getBoat() == null ? "" : competitor.getBoat().getSailID());
final Nationality nationality = competitor.getTeam() == null ? null : competitor.getTeam().getNationality();
result.put(CompetitorJsonConstants.FIELD_NATIONALITY, nationality == null ? "" : nationality.getThreeLetterIOCAcronym());
@@ -1,248 +1,248 @@
package com.sap.sailing.server.gateway.serialization.test.racelog;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseAreaChangeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningListChangedEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPathfinderEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl;
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl;
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl;
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogEventSerializer;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class RaceLogEventSerializerTest {
private RaceLogEventSerializer serializer;
private JsonSerializer<RaceLogEvent> flagEventSerializer;
private JsonSerializer<RaceLogEvent> startTimeSerializer;
private JsonSerializer<RaceLogEvent> raceStatusSerializer;
private JsonSerializer<RaceLogEvent> courseAreaChangedEventSerializer;
private JsonSerializer<RaceLogEvent> passChangedSerializer;
private JsonSerializer<RaceLogEvent> courseDesignChangedEventSerializer;
private JsonSerializer<RaceLogEvent> finishPositioningListChangedEventSerializer;
private JsonSerializer<RaceLogEvent> finishPositioningConfirmedEventSerializer;
private JsonSerializer<RaceLogEvent> pathfinderEventSerializer;
private JsonSerializer<RaceLogEvent> gateLineOpeningTimeEventSerializer;
private JsonSerializer<RaceLogEvent> startProcedureTypeChangedEventSerializer;
private JsonSerializer<RaceLogEvent> protestStartTimeEventSerializer;
private JsonSerializer<RaceLogEvent> windFixEventSerializer;
private JsonSerializer<RaceLogEvent> denoteForTrackingEventSerializer;
private JsonSerializer<RaceLogEvent> startTrackingEventSerializer;
private JsonSerializer<RaceLogEvent> revokeEventSerializer;
private JsonSerializer<RaceLogEvent> registerCompetitorEventSerializer;
private JsonSerializer<RaceLogEvent> additionalScoringInformationSerializer;
private JsonSerializer<RaceLogEvent> fixedMarkPassingEventSerializer;
private JsonSerializer<RaceLogEvent> suppressedMarkPassingsSerializer;
private JsonSerializer<RaceLogEvent> dependentStartTimeEventSerializer;
private JsonSerializer<RaceLogEvent> startOfTrackingEventSerializer;
private JsonSerializer<RaceLogEvent> useCompetitorsFromRaceLogEventSerializer;
private JsonSerializer<RaceLogEvent> endOfTrackingEventSerializer;
private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1);
@SuppressWarnings("unchecked")
@Before
public void setUp() {
flagEventSerializer = mock(JsonSerializer.class);
startTimeSerializer = mock(JsonSerializer.class);
raceStatusSerializer = mock(JsonSerializer.class);
courseAreaChangedEventSerializer = mock(JsonSerializer.class);
passChangedSerializer = mock(JsonSerializer.class);
courseDesignChangedEventSerializer = mock(JsonSerializer.class);
finishPositioningListChangedEventSerializer = mock(JsonSerializer.class);
finishPositioningConfirmedEventSerializer = mock(JsonSerializer.class);
pathfinderEventSerializer = mock(JsonSerializer.class);
gateLineOpeningTimeEventSerializer = mock(JsonSerializer.class);
startProcedureTypeChangedEventSerializer = mock(JsonSerializer.class);
protestStartTimeEventSerializer = mock(JsonSerializer.class);
windFixEventSerializer = mock(JsonSerializer.class);
denoteForTrackingEventSerializer = mock(JsonSerializer.class);
startTrackingEventSerializer = mock(JsonSerializer.class);
revokeEventSerializer = mock(JsonSerializer.class);
registerCompetitorEventSerializer = mock(JsonSerializer.class);
additionalScoringInformationSerializer = mock(JsonSerializer.class);
fixedMarkPassingEventSerializer = mock(JsonSerializer.class);
suppressedMarkPassingsSerializer = mock(JsonSerializer.class);
dependentStartTimeEventSerializer = mock(JsonSerializer.class);
startOfTrackingEventSerializer = mock(JsonSerializer.class);
useCompetitorsFromRaceLogEventSerializer = mock(JsonSerializer.class);
endOfTrackingEventSerializer = mock(JsonSerializer.class);
serializer = new RaceLogEventSerializer(flagEventSerializer, startTimeSerializer, raceStatusSerializer,
courseAreaChangedEventSerializer, passChangedSerializer, courseDesignChangedEventSerializer,
finishPositioningListChangedEventSerializer, finishPositioningConfirmedEventSerializer,
pathfinderEventSerializer, gateLineOpeningTimeEventSerializer,
startProcedureTypeChangedEventSerializer, protestStartTimeEventSerializer, windFixEventSerializer,
denoteForTrackingEventSerializer, startTrackingEventSerializer, revokeEventSerializer,
registerCompetitorEventSerializer, fixedMarkPassingEventSerializer, suppressedMarkPassingsSerializer,
additionalScoringInformationSerializer, dependentStartTimeEventSerializer,
startOfTrackingEventSerializer, useCompetitorsFromRaceLogEventSerializer,
endOfTrackingEventSerializer);
}
@Test
public void testChoosesFlagEventSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogFlagEventImpl(null, author, 0, null, null, false);
serializer.serialize(event);
verify(flagEventSerializer).serialize(event);
}
@Test
public void testChoosesStartTimeSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogStartTimeEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(startTimeSerializer).serialize(event);
}
@Test
public void testChoosesRaceStatusSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogRaceStatusEventImpl(null, author, 0, RaceLogRaceStatus.SCHEDULED);
serializer.serialize(event);
verify(raceStatusSerializer).serialize(event);
}
@Test
public void testChoosesCourseAreaChangedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogCourseAreaChangeEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(courseAreaChangedEventSerializer).serialize(event);
}
@Test
public void testChoosesPassChangedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogPassChangeEventImpl(null, author, 0);
serializer.serialize(event);
verify(passChangedSerializer).serialize(event);
}
@Test
public void testChoosesCourseDesignChangedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogCourseDesignChangedEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(courseDesignChangedEventSerializer).serialize(event);
}
@Test
public void testChoosesFinishPositioningListChangedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogFinishPositioningListChangedEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(finishPositioningListChangedEventSerializer).serialize(event);
}
@Test
public void testChoosesFinishPositioningConfirmedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogFinishPositioningConfirmedEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(finishPositioningConfirmedEventSerializer).serialize(event);
}
@Test
public void testChoosesPathfinderSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogPathfinderEventImpl(null, author, 0, "GER 20");
serializer.serialize(event);
verify(pathfinderEventSerializer).serialize(event);
}
@Test
public void testChoosesGateLineOpeningTimeSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogGateLineOpeningTimeEventImpl(null, author, 0, 2l, 1l);
serializer.serialize(event);
verify(gateLineOpeningTimeEventSerializer).serialize(event);
}
@Test
public void testStartProcedureTypeChangedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogStartProcedureChangedEventImpl(null, author, 0, RacingProcedureType.ESS);
serializer.serialize(event);
verify(startProcedureTypeChangedEventSerializer).serialize(event);
}
@Test
public void testProtestStartTimeSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogProtestStartTimeEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(protestStartTimeEventSerializer).serialize(event);
}
@Test
public void testWindFixSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogWindFixEventImpl(null, author, 0, null, /* isMagnetic */ false);
serializer.serialize(event);
verify(windFixEventSerializer).serialize(event);
}
@Test
public void testDenoteForTrackingSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogDenoteForTrackingEventImpl(null, author, 0, "", null, null);
serializer.serialize(event);
verify(denoteForTrackingEventSerializer).serialize(event);
}
@Test
public void testCreateRaceSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogStartTrackingEventImpl(null, author, 0);
serializer.serialize(event);
verify(startTrackingEventSerializer).serialize(event);
}
@Test
public void testRevokeEventSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogRevokeEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(),
author, 0, 0, UUID.randomUUID(), "type", "short info", "reason");
serializer.serialize(event);
verify(revokeEventSerializer).serialize(event);
}
@Test
public void testRegisterCompetitorEventSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogRegisterCompetitorEventImpl(null, author, 0,
DomainFactory.INSTANCE
.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */
null));
serializer.serialize(event);
verify(registerCompetitorEventSerializer).serialize(event);
}
}
package com.sap.sailing.server.gateway.serialization.test.racelog;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseAreaChangeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningListChangedEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPathfinderEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl;
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl;
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl;
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogEventSerializer;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class RaceLogEventSerializerTest {
private RaceLogEventSerializer serializer;
private JsonSerializer<RaceLogEvent> flagEventSerializer;
private JsonSerializer<RaceLogEvent> startTimeSerializer;
private JsonSerializer<RaceLogEvent> raceStatusSerializer;
private JsonSerializer<RaceLogEvent> courseAreaChangedEventSerializer;
private JsonSerializer<RaceLogEvent> passChangedSerializer;
private JsonSerializer<RaceLogEvent> courseDesignChangedEventSerializer;
private JsonSerializer<RaceLogEvent> finishPositioningListChangedEventSerializer;
private JsonSerializer<RaceLogEvent> finishPositioningConfirmedEventSerializer;
private JsonSerializer<RaceLogEvent> pathfinderEventSerializer;
private JsonSerializer<RaceLogEvent> gateLineOpeningTimeEventSerializer;
private JsonSerializer<RaceLogEvent> startProcedureTypeChangedEventSerializer;
private JsonSerializer<RaceLogEvent> protestStartTimeEventSerializer;
private JsonSerializer<RaceLogEvent> windFixEventSerializer;
private JsonSerializer<RaceLogEvent> denoteForTrackingEventSerializer;
private JsonSerializer<RaceLogEvent> startTrackingEventSerializer;
private JsonSerializer<RaceLogEvent> revokeEventSerializer;
private JsonSerializer<RaceLogEvent> registerCompetitorEventSerializer;
private JsonSerializer<RaceLogEvent> additionalScoringInformationSerializer;
private JsonSerializer<RaceLogEvent> fixedMarkPassingEventSerializer;
private JsonSerializer<RaceLogEvent> suppressedMarkPassingsSerializer;
private JsonSerializer<RaceLogEvent> dependentStartTimeEventSerializer;
private JsonSerializer<RaceLogEvent> startOfTrackingEventSerializer;
private JsonSerializer<RaceLogEvent> useCompetitorsFromRaceLogEventSerializer;
private JsonSerializer<RaceLogEvent> endOfTrackingEventSerializer;
private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1);
@SuppressWarnings("unchecked")
@Before
public void setUp() {
flagEventSerializer = mock(JsonSerializer.class);
startTimeSerializer = mock(JsonSerializer.class);
raceStatusSerializer = mock(JsonSerializer.class);
courseAreaChangedEventSerializer = mock(JsonSerializer.class);
passChangedSerializer = mock(JsonSerializer.class);
courseDesignChangedEventSerializer = mock(JsonSerializer.class);
finishPositioningListChangedEventSerializer = mock(JsonSerializer.class);
finishPositioningConfirmedEventSerializer = mock(JsonSerializer.class);
pathfinderEventSerializer = mock(JsonSerializer.class);
gateLineOpeningTimeEventSerializer = mock(JsonSerializer.class);
startProcedureTypeChangedEventSerializer = mock(JsonSerializer.class);
protestStartTimeEventSerializer = mock(JsonSerializer.class);
windFixEventSerializer = mock(JsonSerializer.class);
denoteForTrackingEventSerializer = mock(JsonSerializer.class);
startTrackingEventSerializer = mock(JsonSerializer.class);
revokeEventSerializer = mock(JsonSerializer.class);
registerCompetitorEventSerializer = mock(JsonSerializer.class);
additionalScoringInformationSerializer = mock(JsonSerializer.class);
fixedMarkPassingEventSerializer = mock(JsonSerializer.class);
suppressedMarkPassingsSerializer = mock(JsonSerializer.class);
dependentStartTimeEventSerializer = mock(JsonSerializer.class);
startOfTrackingEventSerializer = mock(JsonSerializer.class);
useCompetitorsFromRaceLogEventSerializer = mock(JsonSerializer.class);
endOfTrackingEventSerializer = mock(JsonSerializer.class);
serializer = new RaceLogEventSerializer(flagEventSerializer, startTimeSerializer, raceStatusSerializer,
courseAreaChangedEventSerializer, passChangedSerializer, courseDesignChangedEventSerializer,
finishPositioningListChangedEventSerializer, finishPositioningConfirmedEventSerializer,
pathfinderEventSerializer, gateLineOpeningTimeEventSerializer,
startProcedureTypeChangedEventSerializer, protestStartTimeEventSerializer, windFixEventSerializer,
denoteForTrackingEventSerializer, startTrackingEventSerializer, revokeEventSerializer,
registerCompetitorEventSerializer, fixedMarkPassingEventSerializer, suppressedMarkPassingsSerializer,
additionalScoringInformationSerializer, dependentStartTimeEventSerializer,
startOfTrackingEventSerializer, useCompetitorsFromRaceLogEventSerializer,
endOfTrackingEventSerializer);
}
@Test
public void testChoosesFlagEventSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogFlagEventImpl(null, author, 0, null, null, false);
serializer.serialize(event);
verify(flagEventSerializer).serialize(event);
}
@Test
public void testChoosesStartTimeSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogStartTimeEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(startTimeSerializer).serialize(event);
}
@Test
public void testChoosesRaceStatusSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogRaceStatusEventImpl(null, author, 0, RaceLogRaceStatus.SCHEDULED);
serializer.serialize(event);
verify(raceStatusSerializer).serialize(event);
}
@Test
public void testChoosesCourseAreaChangedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogCourseAreaChangeEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(courseAreaChangedEventSerializer).serialize(event);
}
@Test
public void testChoosesPassChangedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogPassChangeEventImpl(null, author, 0);
serializer.serialize(event);
verify(passChangedSerializer).serialize(event);
}
@Test
public void testChoosesCourseDesignChangedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogCourseDesignChangedEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(courseDesignChangedEventSerializer).serialize(event);
}
@Test
public void testChoosesFinishPositioningListChangedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogFinishPositioningListChangedEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(finishPositioningListChangedEventSerializer).serialize(event);
}
@Test
public void testChoosesFinishPositioningConfirmedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogFinishPositioningConfirmedEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(finishPositioningConfirmedEventSerializer).serialize(event);
}
@Test
public void testChoosesPathfinderSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogPathfinderEventImpl(null, author, 0, "GER 20");
serializer.serialize(event);
verify(pathfinderEventSerializer).serialize(event);
}
@Test
public void testChoosesGateLineOpeningTimeSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogGateLineOpeningTimeEventImpl(null, author, 0, 2l, 1l);
serializer.serialize(event);
verify(gateLineOpeningTimeEventSerializer).serialize(event);
}
@Test
public void testStartProcedureTypeChangedSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogStartProcedureChangedEventImpl(null, author, 0, RacingProcedureType.ESS);
serializer.serialize(event);
verify(startProcedureTypeChangedEventSerializer).serialize(event);
}
@Test
public void testProtestStartTimeSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogProtestStartTimeEventImpl(null, author, 0, null);
serializer.serialize(event);
verify(protestStartTimeEventSerializer).serialize(event);
}
@Test
public void testWindFixSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogWindFixEventImpl(null, author, 0, null, /* isMagnetic */ false);
serializer.serialize(event);
verify(windFixEventSerializer).serialize(event);
}
@Test
public void testDenoteForTrackingSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogDenoteForTrackingEventImpl(null, author, 0, "", null, null);
serializer.serialize(event);
verify(denoteForTrackingEventSerializer).serialize(event);
}
@Test
public void testCreateRaceSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogStartTrackingEventImpl(null, author, 0);
serializer.serialize(event);
verify(startTrackingEventSerializer).serialize(event);
}
@Test
public void testRevokeEventSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogRevokeEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(),
author, 0, 0, UUID.randomUUID(), "type", "short info", "reason");
serializer.serialize(event);
verify(revokeEventSerializer).serialize(event);
}
@Test
public void testRegisterCompetitorEventSerializer() {
// we use the real event type here because we do not want to re-implement the dispatching.
RaceLogEvent event = new RaceLogRegisterCompetitorEventImpl(null, author, 0,
DomainFactory.INSTANCE
.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */
null, null));
serializer.serialize(event);
verify(registerCompetitorEventSerializer).serialize(event);
}
}
@@ -1,102 +1,102 @@
package com.sap.sailing.server.gateway.test;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.gateway.AbstractJsonHttpServlet;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.mongodb.MongoDBConfiguration;
import com.sap.sse.mongodb.MongoDBService;
public abstract class AbstractJsonExportTest {
protected RacingEventService racingEventService;
protected MongoDBService service;
protected static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
public void setUp() {
service = MongoDBConfiguration.getDefaultTestConfiguration().getService();
service.getDB().dropDatabase();
racingEventService = new RacingEventServiceImpl();
}
protected String callJsonHttpServlet(AbstractJsonHttpServlet jsonServlet, String GetOrPostMethod, Map<String, String> parameters) throws Exception {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
when(request.getMethod()).thenReturn(GetOrPostMethod);
if(parameters != null) {
for(Map.Entry<String, String> entry: parameters.entrySet()) {
when(request.getParameter(entry.getKey())).thenReturn(entry.getValue());
}
}
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
when(response.getWriter()).thenReturn(writer);
AbstractJsonHttpServlet spyJsonExportServlet = spy(jsonServlet);
doReturn(racingEventService).when(spyJsonExportServlet).getService();
spyJsonExportServlet.service(request, response);
// the writer may not have been flushed yet...
writer.flush();
return stringWriter.toString();
}
protected TimePoint parseTimepointFromJsonString(String timePointAsJsonString) throws ParseException {
TimePoint result = null;
if(timePointAsJsonString != null && !timePointAsJsonString.isEmpty()) {
Date date = TIMEPOINT_FORMATTER.parse(timePointAsJsonString);
result = new MillisecondsTimePoint(date);
}
return result;
}
protected List<Competitor> createCompetitors(int numberOfCompetitorsToCreate) {
List<Competitor> result = new ArrayList<Competitor>();
BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true);
for (int i = 1; i <= numberOfCompetitorsToCreate; i++) {
String competitorName = "C" + i;
Competitor competitor = new CompetitorImpl(UUID.randomUUID(), competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton(
new PersonImpl(competitorName, new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous "+competitorName)),
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
result.add(competitor);
}
return result;
}
}
package com.sap.sailing.server.gateway.test;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.gateway.AbstractJsonHttpServlet;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.mongodb.MongoDBConfiguration;
import com.sap.sse.mongodb.MongoDBService;
public abstract class AbstractJsonExportTest {
protected RacingEventService racingEventService;
protected MongoDBService service;
protected static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
public void setUp() {
service = MongoDBConfiguration.getDefaultTestConfiguration().getService();
service.getDB().dropDatabase();
racingEventService = new RacingEventServiceImpl();
}
protected String callJsonHttpServlet(AbstractJsonHttpServlet jsonServlet, String GetOrPostMethod, Map<String, String> parameters) throws Exception {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
when(request.getMethod()).thenReturn(GetOrPostMethod);
if(parameters != null) {
for(Map.Entry<String, String> entry: parameters.entrySet()) {
when(request.getParameter(entry.getKey())).thenReturn(entry.getValue());
}
}
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
when(response.getWriter()).thenReturn(writer);
AbstractJsonHttpServlet spyJsonExportServlet = spy(jsonServlet);
doReturn(racingEventService).when(spyJsonExportServlet).getService();
spyJsonExportServlet.service(request, response);
// the writer may not have been flushed yet...
writer.flush();
return stringWriter.toString();
}
protected TimePoint parseTimepointFromJsonString(String timePointAsJsonString) throws ParseException {
TimePoint result = null;
if(timePointAsJsonString != null && !timePointAsJsonString.isEmpty()) {
Date date = TIMEPOINT_FORMATTER.parse(timePointAsJsonString);
result = new MillisecondsTimePoint(date);
}
return result;
}
protected List<Competitor> createCompetitors(int numberOfCompetitorsToCreate) {
List<Competitor> result = new ArrayList<Competitor>();
BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true);
for (int i = 1; i <= numberOfCompetitorsToCreate; i++) {
String competitorName = "C" + i;
Competitor competitor = new CompetitorImpl(UUID.randomUUID(), competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton(
new PersonImpl(competitorName, new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous "+competitorName)),
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
result.add(competitor);
}
return result;
}
}
@@ -1,92 +1,92 @@
package com.sap.sailing.server.gateway.test.jaxrs;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.ws.rs.core.Response;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneUuidServiceFinderFactory;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.mongodb.MongoDBConfiguration;
import com.sap.sse.mongodb.MongoDBService;
public abstract class AbstractJaxRsApiTest {
protected RacingEventService racingEventService;
protected MongoDBService service;
protected static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
public void setUp() {
service = MongoDBConfiguration.getDefaultTestConfiguration().getService();
service.getDB().dropDatabase();
racingEventService = new RacingEventServiceImpl(true, new MockSmartphoneUuidServiceFinderFactory());
}
protected <T extends AbstractSailingServerResource> T spyResource(T resource) {
T spyResource = spy(resource);
doReturn(racingEventService).when(spyResource).getService();
return spyResource;
}
protected String decodeResponseFromByteArray(Response response) throws UnsupportedEncodingException {
byte[] entity = (byte[]) response.getEntity();
return new String(entity, "UTF-8");
}
protected TimePoint parseTimepointFromJsonNumber(Long timePointAsJsonNumber) throws ParseException {
TimePoint result = null;
if(timePointAsJsonNumber != null) {
result = new MillisecondsTimePoint(timePointAsJsonNumber);
}
return result;
}
protected TimePoint parseTimepointFromJsonString(String timePointAsJsonString) throws ParseException {
TimePoint result = null;
if(timePointAsJsonString != null && !timePointAsJsonString.isEmpty()) {
Date date = TIMEPOINT_FORMATTER.parse(timePointAsJsonString);
result = new MillisecondsTimePoint(date);
}
return result;
}
protected List<Competitor> createCompetitors(int numberOfCompetitorsToCreate) {
List<Competitor> result = new ArrayList<Competitor>();
BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true);
for (int i = 1; i <= numberOfCompetitorsToCreate; i++) {
String competitorName = "C" + i;
Competitor competitor = new CompetitorImpl(new Integer(i), competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton(
new PersonImpl(competitorName, new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous "+competitorName)),
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
result.add(competitor);
}
return result;
}
}
package com.sap.sailing.server.gateway.test.jaxrs;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.ws.rs.core.Response;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneUuidServiceFinderFactory;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.mongodb.MongoDBConfiguration;
import com.sap.sse.mongodb.MongoDBService;
public abstract class AbstractJaxRsApiTest {
protected RacingEventService racingEventService;
protected MongoDBService service;
protected static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
public void setUp() {
service = MongoDBConfiguration.getDefaultTestConfiguration().getService();
service.getDB().dropDatabase();
racingEventService = new RacingEventServiceImpl(true, new MockSmartphoneUuidServiceFinderFactory());
}
protected <T extends AbstractSailingServerResource> T spyResource(T resource) {
T spyResource = spy(resource);
doReturn(racingEventService).when(spyResource).getService();
return spyResource;
}
protected String decodeResponseFromByteArray(Response response) throws UnsupportedEncodingException {
byte[] entity = (byte[]) response.getEntity();
return new String(entity, "UTF-8");
}
protected TimePoint parseTimepointFromJsonNumber(Long timePointAsJsonNumber) throws ParseException {
TimePoint result = null;
if(timePointAsJsonNumber != null) {
result = new MillisecondsTimePoint(timePointAsJsonNumber);
}
return result;
}
protected TimePoint parseTimepointFromJsonString(String timePointAsJsonString) throws ParseException {
TimePoint result = null;
if(timePointAsJsonString != null && !timePointAsJsonString.isEmpty()) {
Date date = TIMEPOINT_FORMATTER.parse(timePointAsJsonString);
result = new MillisecondsTimePoint(date);
}
return result;
}
protected List<Competitor> createCompetitors(int numberOfCompetitorsToCreate) {
List<Competitor> result = new ArrayList<Competitor>();
BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true);
for (int i = 1; i <= numberOfCompetitorsToCreate; i++) {
String competitorName = "C" + i;
Competitor competitor = new CompetitorImpl(new Integer(i), competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton(
new PersonImpl(competitorName, new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous "+competitorName)),
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
result.add(competitor);
}
return result;
}
}
@@ -1,87 +1,87 @@
package com.sap.sailing.server.gateway.test.jaxrs;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import org.apache.commons.io.IOUtils;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants;
import com.sap.sailing.server.gateway.jaxrs.api.CompetitorsResource;
import com.sap.sse.filestorage.FileStorageManagementService;
import com.sap.sse.filestorage.FileStorageService;
import com.sap.sse.filestorage.InvalidPropertiesException;
import com.sap.sse.filestorage.OperationFailedException;
import com.sap.sse.filestorage.testsupport.AmazonS3TestSupport;
public class CompetitorsResourceTeamImageTest extends AbstractJaxRsApiTest {
private static final String name = "Heiko KRÖGER";
private static final String id = "af855a56-9726-4a9c-a77e-da955bd289be";
private static final String boatClassName = "49er";
private static final String sailID = "GER 1";
private static final String nationality = "GER";
private static final String teamImageFile = "Bundesliga2014_Regatta6_eventteaser.jpg";
private FileStorageService storageService;
@Before
public void setUpSubClass() throws InvalidPropertiesException {
super.setUp();
racingEventService = spy(racingEventService);
storageService = AmazonS3TestSupport.createService();
FileStorageManagementService fsmsMock = mock(FileStorageManagementService.class);
doReturn(fsmsMock).when(racingEventService).getFileStorageManagementService();
doReturn(storageService).when(fsmsMock).getActiveFileStorageService();
DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl(
nationality), null, null)), null);
DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID);
racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, team, boat,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
}
@Test
public void storeAndRemoveTeamImage() throws URISyntaxException, ParseException, MalformedURLException,
IOException, OperationFailedException, InvalidPropertiesException {
//set team image
CompetitorsResource r = spyResource(new CompetitorsResource());
String fileExtension = teamImageFile.substring(teamImageFile.lastIndexOf("."));;
InputStream stream = getClass().getResourceAsStream("/" + teamImageFile);
// this is not ideal, as this #available() is not supposed to be used for getting the file size
// however, working with a File() descriptor does not work, as when running via maven/tycho the
// URL has the bundleresource:// scheme instead of file:, which File() can't handle
long length = stream.available();
String jsonString = r.setTeamImage(id, stream, fileExtension, length);
//now download and compare
JSONObject json = (JSONObject) JSONValue.parseWithException(jsonString);
String imageUriString = (String) json.get(DeviceMappingConstants.JSON_TEAM_IMAGE_URI);
URI imageUri = new URI(imageUriString);
InputStream downloadStream = imageUri.toURL().openStream();
stream = getClass().getResourceAsStream("/" + teamImageFile);
IOUtils.contentEquals(downloadStream, stream);
storageService.removeFile(imageUri);
}
}
package com.sap.sailing.server.gateway.test.jaxrs;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import org.apache.commons.io.IOUtils;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants;
import com.sap.sailing.server.gateway.jaxrs.api.CompetitorsResource;
import com.sap.sse.filestorage.FileStorageManagementService;
import com.sap.sse.filestorage.FileStorageService;
import com.sap.sse.filestorage.InvalidPropertiesException;
import com.sap.sse.filestorage.OperationFailedException;
import com.sap.sse.filestorage.testsupport.AmazonS3TestSupport;
public class CompetitorsResourceTeamImageTest extends AbstractJaxRsApiTest {
private static final String name = "Heiko KRÖGER";
private static final String id = "af855a56-9726-4a9c-a77e-da955bd289be";
private static final String boatClassName = "49er";
private static final String sailID = "GER 1";
private static final String nationality = "GER";
private static final String teamImageFile = "Bundesliga2014_Regatta6_eventteaser.jpg";
private FileStorageService storageService;
@Before
public void setUpSubClass() throws InvalidPropertiesException {
super.setUp();
racingEventService = spy(racingEventService);
storageService = AmazonS3TestSupport.createService();
FileStorageManagementService fsmsMock = mock(FileStorageManagementService.class);
doReturn(fsmsMock).when(racingEventService).getFileStorageManagementService();
doReturn(storageService).when(fsmsMock).getActiveFileStorageService();
DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl(
nationality), null, null)), null);
DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID);
racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, team, boat,
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
}
@Test
public void storeAndRemoveTeamImage() throws URISyntaxException, ParseException, MalformedURLException,
IOException, OperationFailedException, InvalidPropertiesException {
//set team image
CompetitorsResource r = spyResource(new CompetitorsResource());
String fileExtension = teamImageFile.substring(teamImageFile.lastIndexOf("."));;
InputStream stream = getClass().getResourceAsStream("/" + teamImageFile);
// this is not ideal, as this #available() is not supposed to be used for getting the file size
// however, working with a File() descriptor does not work, as when running via maven/tycho the
// URL has the bundleresource:// scheme instead of file:, which File() can't handle
long length = stream.available();
String jsonString = r.setTeamImage(id, stream, fileExtension, length);
//now download and compare
JSONObject json = (JSONObject) JSONValue.parseWithException(jsonString);
String imageUriString = (String) json.get(DeviceMappingConstants.JSON_TEAM_IMAGE_URI);
URI imageUri = new URI(imageUriString);
InputStream downloadStream = imageUri.toURL().openStream();
stream = getClass().getResourceAsStream("/" + teamImageFile);
IOUtils.contentEquals(downloadStream, stream);
storageService.removeFile(imageUri);
}
}
@@ -1,53 +1,53 @@
package com.sap.sailing.server.gateway.test.jaxrs;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import java.util.Collections;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
import com.sap.sailing.server.gateway.jaxrs.api.CompetitorsResource;
public class CompetitorsResourceTest extends AbstractJaxRsApiTest {
private final String name = "Heiko KRÖGER";
private final String id = "af855a56-9726-4a9c-a77e-da955bd289be";
private final String boatClassName = "49er";
private final String sailID = "GER 1";
private final String nationality = "GER";
private final String countryCode = "DE";
@Before
public void setUp() {
super.setUp();
DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl(nationality), null, null)), null);
DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID);
racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
}
@Test
public void testExportRegattasAsJson() throws Exception {
CompetitorsResource resource = spyResource(new CompetitorsResource());
String jsonString = resource.getCompetitor(id).getEntity().toString();
JSONObject json = Helpers.toJSONObjectSafe(JSONValue.parse(jsonString));
assertThat("id is correct", json.get("id"), equalTo(id));
assertThat("name is correct", json.get("name"), equalTo(name));
assertThat("boatClass is correct", json.get("boatClassName"), equalTo(boatClassName));
assertThat("sailID is correct", json.get("sailID"), equalTo(sailID));
assertThat("nationality is correct", json.get("nationality"), equalTo(nationality));
assertThat("nationality is correct", json.get("countryCode"), equalTo(countryCode));
}
}
package com.sap.sailing.server.gateway.test.jaxrs;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import java.util.Collections;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
import com.sap.sailing.server.gateway.jaxrs.api.CompetitorsResource;
public class CompetitorsResourceTest extends AbstractJaxRsApiTest {
private final String name = "Heiko KRÖGER";
private final String id = "af855a56-9726-4a9c-a77e-da955bd289be";
private final String boatClassName = "49er";
private final String sailID = "GER 1";
private final String nationality = "GER";
private final String countryCode = "DE";
@Before
public void setUp() {
super.setUp();
DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl(nationality), null, null)), null);
DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID);
racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
}
@Test
public void testExportRegattasAsJson() throws Exception {
CompetitorsResource resource = spyResource(new CompetitorsResource());
String jsonString = resource.getCompetitor(id).getEntity().toString();
JSONObject json = Helpers.toJSONObjectSafe(JSONValue.parse(jsonString));
assertThat("id is correct", json.get("id"), equalTo(id));
assertThat("name is correct", json.get("name"), equalTo(name));
assertThat("boatClass is correct", json.get("boatClassName"), equalTo(boatClassName));
assertThat("sailID is correct", json.get("sailID"), equalTo(sailID));
assertThat("nationality is correct", json.get("nationality"), equalTo(nationality));
assertThat("nationality is correct", json.get("countryCode"), equalTo(countryCode));
}
}
@@ -1,106 +1,106 @@
package com.sap.sailing.server.gateway.test.jaxrs;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.ws.rs.core.Response;
import org.json.simple.JSONObject;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceCompetitorMappingFinder;
import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.SeriesImpl;
import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
import com.sap.sailing.domain.leaderboard.impl.HighPoint;
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
import com.sap.sailing.domain.racelogtracking.SmartphoneUUIDIdentifier;
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sailing.server.gateway.jaxrs.api.LeaderboardsResource;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest {
private Competitor competitor;
private RegattaLog log;
private RegattaLeaderboard leaderboard;
@Before
public void setUp() {
super.setUp();
Competitor c = createCompetitors(1).get(0);
competitor = racingEventService.getBaseDomainFactory().getOrCreateCompetitor(c.getId(), c.getName(),
c.getColor(), c.getEmail(), c.getFlagImage(), (DynamicTeam) c.getTeam(), (DynamicBoat) c.getBoat(),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), MillisecondsTimePoint.now(),
MillisecondsTimePoint.now(), Collections.singleton(new SeriesImpl("series", false, Collections
.singleton(new FleetImpl("fleet")), Arrays.asList("column"), racingEventService)), false,
new HighPoint(), 0, null, OneDesignRankingMetric::new);
racingEventService.addRegattaWithoutReplication(regatta);
leaderboard = racingEventService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "regatta", new int[] {});
regatta.registerCompetitor(competitor);
log = leaderboard.getRegattaLike().getRegattaLog();
}
@Test
public void testCheckinAndCheckout() throws Exception {
LeaderboardsResource resource = spyResource(new LeaderboardsResource());
UUID deviceUuid = UUID.randomUUID();
// checkin
long fromMillis = 500;
JSONObject json = new JSONObject();
json.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitor.getId().toString());
json.put(DeviceMappingConstants.JSON_DEVICE_UUID, deviceUuid.toString());
json.put(DeviceMappingConstants.JSON_FROM_MILLIS, fromMillis);
Response response = resource.postCheckin(json.toString(), leaderboard.getName());
assertThat("checkin returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode()));
Set<Competitor> registeredCompetitors = new CompetitorsInLogAnalyzer<>(log).analyze();
Map<Competitor, List<DeviceMapping<Competitor>>> mappings = new RegattaLogDeviceCompetitorMappingFinder(log).analyze();
assertThat("competitor was registered", registeredCompetitors.size(), equalTo(1));
assertThat("device mappings for competitor exist", mappings.size(), equalTo(1));
List<DeviceMapping<Competitor>> mappingsForC = mappings.get(competitor);
assertThat("exactly one device mapping for competitor exists", mappingsForC.size(), equalTo(1));
DeviceMapping<Competitor> mappingForC = mappingsForC.get(0);
assertThat("that mapping is for the correct device",
((SmartphoneUUIDIdentifier) mappingForC.getDevice()).getUUID(), equalTo(deviceUuid));
assertThat("that mapping starts at the correct timepoint", mappingForC.getTimeRange().from().asMillis(),
equalTo(fromMillis));
assertThat("that mapping is open-ended", mappingForC.getTimeRange().hasOpenEnd(), equalTo(true));
// checkout
long toMillis = 1000;
json = new JSONObject();
json.put(DeviceMappingConstants.JSON_TO_MILLIS, toMillis);
json.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitor.getId().toString());
json.put(DeviceMappingConstants.JSON_DEVICE_UUID, deviceUuid.toString());
response = resource.postCheckout(json.toString(), leaderboard.getName());
assertThat("checkout returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode()));
mappings = new RegattaLogDeviceCompetitorMappingFinder(log).analyze();
mappingForC = mappings.get(competitor).get(0);
assertThat("mapping now ends at checkout timepoint", mappingForC.getTimeRange().to().asMillis(),
equalTo(toMillis));
}
}
package com.sap.sailing.server.gateway.test.jaxrs;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.ws.rs.core.Response;
import org.json.simple.JSONObject;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceCompetitorMappingFinder;
import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.SeriesImpl;
import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
import com.sap.sailing.domain.leaderboard.impl.HighPoint;
import com.sap.sailing.domain.racelogtracking.DeviceMapping;
import com.sap.sailing.domain.racelogtracking.SmartphoneUUIDIdentifier;
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sailing.server.gateway.jaxrs.api.LeaderboardsResource;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest {
private Competitor competitor;
private RegattaLog log;
private RegattaLeaderboard leaderboard;
@Before
public void setUp() {
super.setUp();
Competitor c = createCompetitors(1).get(0);
competitor = racingEventService.getBaseDomainFactory().getOrCreateCompetitor(c.getId(), c.getName(),
c.getColor(), c.getEmail(), c.getFlagImage(), (DynamicTeam) c.getTeam(), (DynamicBoat) c.getBoat(),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), MillisecondsTimePoint.now(),
MillisecondsTimePoint.now(), Collections.singleton(new SeriesImpl("series", false, Collections
.singleton(new FleetImpl("fleet")), Arrays.asList("column"), racingEventService)), false,
new HighPoint(), 0, null, OneDesignRankingMetric::new);
racingEventService.addRegattaWithoutReplication(regatta);
leaderboard = racingEventService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "regatta", new int[] {});
regatta.registerCompetitor(competitor);
log = leaderboard.getRegattaLike().getRegattaLog();
}
@Test
public void testCheckinAndCheckout() throws Exception {
LeaderboardsResource resource = spyResource(new LeaderboardsResource());
UUID deviceUuid = UUID.randomUUID();
// checkin
long fromMillis = 500;
JSONObject json = new JSONObject();
json.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitor.getId().toString());
json.put(DeviceMappingConstants.JSON_DEVICE_UUID, deviceUuid.toString());
json.put(DeviceMappingConstants.JSON_FROM_MILLIS, fromMillis);
Response response = resource.postCheckin(json.toString(), leaderboard.getName());
assertThat("checkin returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode()));
Set<Competitor> registeredCompetitors = new CompetitorsInLogAnalyzer<>(log).analyze();
Map<Competitor, List<DeviceMapping<Competitor>>> mappings = new RegattaLogDeviceCompetitorMappingFinder(log).analyze();
assertThat("competitor was registered", registeredCompetitors.size(), equalTo(1));
assertThat("device mappings for competitor exist", mappings.size(), equalTo(1));
List<DeviceMapping<Competitor>> mappingsForC = mappings.get(competitor);
assertThat("exactly one device mapping for competitor exists", mappingsForC.size(), equalTo(1));
DeviceMapping<Competitor> mappingForC = mappingsForC.get(0);
assertThat("that mapping is for the correct device",
((SmartphoneUUIDIdentifier) mappingForC.getDevice()).getUUID(), equalTo(deviceUuid));
assertThat("that mapping starts at the correct timepoint", mappingForC.getTimeRange().from().asMillis(),
equalTo(fromMillis));
assertThat("that mapping is open-ended", mappingForC.getTimeRange().hasOpenEnd(), equalTo(true));
// checkout
long toMillis = 1000;
json = new JSONObject();
json.put(DeviceMappingConstants.JSON_TO_MILLIS, toMillis);
json.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitor.getId().toString());
json.put(DeviceMappingConstants.JSON_DEVICE_UUID, deviceUuid.toString());
response = resource.postCheckout(json.toString(), leaderboard.getName());
assertThat("checkout returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode()));
mappings = new RegattaLogDeviceCompetitorMappingFinder(log).analyze();
mappingForC = mappings.get(competitor).get(0);
assertThat("mapping now ends at checkout timepoint", mappingForC.getTimeRange().to().asMillis(),
equalTo(toMillis));
}
}
@@ -165,7 +165,8 @@ public class CompetitorsResource extends AbstractSailingServerResource {
}
getService().getCompetitorStore().updateCompetitor(competitorId, competitor.getName(), competitor.getColor(), competitor.getEmail(),
competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), imageUri, competitor.getFlagImage(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), imageUri, competitor.getFlagImage(),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, competitor.getSearchTag());
logger.log(Level.INFO, "Set team image for competitor " + competitor.getName());
JSONObject result = new JSONObject();
@@ -1,138 +1,139 @@
package com.sap.sailing.server.replication.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore;
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.server.operationaltransformation.AddRaceDefinition;
import com.sap.sailing.server.operationaltransformation.AllowCompetitorResetToDefaults;
import com.sap.sailing.server.operationaltransformation.CreateTrackedRace;
import com.sap.sailing.server.operationaltransformation.UpdateCompetitor;
import com.sap.sse.common.Color;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
/**
* Tests replication of competitors in conjunction with the {@link CompetitorStore} concepts, particularly the
* possibility to allow for competitor data to be updated, either explicitly or implicitly from a tracking provider
* after marking the competitor using
* {@link CompetitorStore#allowCompetitorResetToDefaults(com.sap.sailing.domain.base.Competitor)}.
*
* @author Axel Uhl (d043530)
*
*/
public class CompetitorReplicationTest extends AbstractServerReplicationTest {
/**
* Add a tracked race to the master that includes a competitor; check that the competitor was properly replicated to
* the replica's {@link CompetitorStore}. Afterwards, use the {@link UpdateCompetitor} operation on the master to
* perform an explicit update; ensure that the update arrived on the replica. Then execute an
* {@link AllowCompetitorResetToDefaults} operation on the master, afterwards update the competitor on the master,
* then force some competitor-related event to be sent to the replica, such as a GPS fix update. This will serialize
* the competitor with its modified state over to the replica where a
* {@link DomainFactory#getOrCreateCompetitor(java.io.Serializable, String, com.sap.sailing.domain.base.impl.DynamicTeam, com.sap.sailing.domain.base.impl.DynamicBoat)}
* will be triggered. This should also update the competitor on the client.
* @throws URISyntaxException
*/
@Test
public void testSimpleSpecificRegattaReplication() throws InterruptedException, URISyntaxException {
String baseEventName = "My Test Event";
String boatClassName = "Kielzugvogel";
Integer regattaId = 12345;
URI flagImageURI = new URI("http://www.sapsailing.com");
Iterable<Series> series = Collections.emptyList();
Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName,
/*startDate*/ null, /*endDate*/ null, regattaId, series,
/* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /* useStartTimeInference */ true, OneDesignRankingMetric::new);
Iterable<Waypoint> emptyWaypointList = Collections.emptyList();
final String competitorName = "Der mit dem Kiel zieht";
Competitor competitor = master.getBaseDomainFactory().getOrCreateCompetitor(
123, competitorName, Color.RED, "someone@nowhere.de", flagImageURI,
new TeamImpl("STG", Collections.singleton(new PersonImpl(competitorName, new NationalityImpl("GER"),
/* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas",
new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")),
new BoatImpl(competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null);
Iterable<Competitor> competitors = Collections.singleton(competitor);
final String raceName = "Test Race";
RaceDefinition raceDefinition = new RaceDefinitionImpl(raceName, new CourseImpl("Empty Course", emptyWaypointList),
masterRegatta.getBoatClass(), competitors);
master.apply(new AddRaceDefinition(masterRegatta.getRegattaIdentifier(), raceDefinition));
Thread.sleep(1000);
Regatta replicatedRegatta = replica.getRegatta(new RegattaName(masterRegatta.getName()));
assertNotNull(replicatedRegatta);
assertTrue(replicatedRegatta.isPersistent());
assertTrue(Util.isEmpty((replicatedRegatta.getSeries())));
assertNull(replicatedRegatta.getDefaultCourseArea());
assertTrue(regattaId.equals(replicatedRegatta.getId()));
RaceDefinition replicatedRace = replicatedRegatta.getRaceByName(raceName);
assertNotNull(replicatedRace);
Competitor replicatedCompetitor = replicatedRace.getCompetitors().iterator().next();
assertNotSame(replicatedCompetitor, competitor);
assertEquals(competitor.getId(), replicatedCompetitor.getId());
assertEquals(competitor.getName(), replicatedCompetitor.getName());
assertEquals(competitor.getColor(), replicatedCompetitor.getColor());
assertEquals(competitor.getFlagImage(), replicatedCompetitor.getFlagImage());
assertEquals(competitor.getBoat().getSailID(), replicatedCompetitor.getBoat().getSailID());
assertEquals(competitor.getTeam().getNationality(), replicatedCompetitor.getTeam().getNationality());
// now update competitor on master using replicating operation
final String newCompetitorName = "Der Vogel, der mit dem Kiel zieht";
master.apply(new UpdateCompetitor(competitor.getId().toString(), newCompetitorName, competitor.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(),
competitor.getTeam().getImage(), competitor.getFlagImage(),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null));
Thread.sleep(1000);
assertEquals(newCompetitorName, replicatedCompetitor.getName()); // expect in-place update of existing competitor in replica
// now allow for resetting to default through some event, such as receiving a GPS position
master.apply(new AllowCompetitorResetToDefaults(Collections.singleton(competitor.getId().toString())));
// modify the competitor on the master "from below" without an UpdateCompetitor operation, only locally:
master.getBaseDomainFactory().getCompetitorStore().updateCompetitor(competitor.getId().toString(), competitorName, Color.RED, competitor.getEmail(),
competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null);
final RegattaAndRaceIdentifier raceIdentifier = masterRegatta.getRaceIdentifier(raceDefinition);
DynamicTrackedRace trackedRace = (DynamicTrackedRace) master.apply(new CreateTrackedRace(raceIdentifier,
EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 3000,
/* millisecondsOverWhichToAverageWind */ 30000l, /* millisecondsOverWhichToAverageSpeed */ 30000l));
trackedRace.getTrack(competitor).addGPSFix(new GPSFixMovingImpl(new DegreePosition(49.425, 8.293), MillisecondsTimePoint.now(),
new KnotSpeedWithBearingImpl(12.3, new DegreeBearingImpl(242.3))));
Thread.sleep(1000);
TrackedRace replicatedTrackedRace = replica.getTrackedRace(raceIdentifier);
assertNotNull(replicatedTrackedRace);
assertNotNull(replicatedTrackedRace.getTrack(replicatedCompetitor).getFirstRawFix());
assertEquals(competitorName, replicatedCompetitor.getName());
}
package com.sap.sailing.server.replication.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore;
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.server.operationaltransformation.AddRaceDefinition;
import com.sap.sailing.server.operationaltransformation.AllowCompetitorResetToDefaults;
import com.sap.sailing.server.operationaltransformation.CreateTrackedRace;
import com.sap.sailing.server.operationaltransformation.UpdateCompetitor;
import com.sap.sse.common.Color;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
/**
* Tests replication of competitors in conjunction with the {@link CompetitorStore} concepts, particularly the
* possibility to allow for competitor data to be updated, either explicitly or implicitly from a tracking provider
* after marking the competitor using
* {@link CompetitorStore#allowCompetitorResetToDefaults(com.sap.sailing.domain.base.Competitor)}.
*
* @author Axel Uhl (d043530)
*
*/
public class CompetitorReplicationTest extends AbstractServerReplicationTest {
/**
* Add a tracked race to the master that includes a competitor; check that the competitor was properly replicated to
* the replica's {@link CompetitorStore}. Afterwards, use the {@link UpdateCompetitor} operation on the master to
* perform an explicit update; ensure that the update arrived on the replica. Then execute an
* {@link AllowCompetitorResetToDefaults} operation on the master, afterwards update the competitor on the master,
* then force some competitor-related event to be sent to the replica, such as a GPS fix update. This will serialize
* the competitor with its modified state over to the replica where a
* {@link DomainFactory#getOrCreateCompetitor(java.io.Serializable, String, com.sap.sailing.domain.base.impl.DynamicTeam, com.sap.sailing.domain.base.impl.DynamicBoat)}
* will be triggered. This should also update the competitor on the client.
* @throws URISyntaxException
*/
@Test
public void testSimpleSpecificRegattaReplication() throws InterruptedException, URISyntaxException {
String baseEventName = "My Test Event";
String boatClassName = "Kielzugvogel";
Integer regattaId = 12345;
URI flagImageURI = new URI("http://www.sapsailing.com");
Iterable<Series> series = Collections.emptyList();
Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName,
/*startDate*/ null, /*endDate*/ null, regattaId, series,
/* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /* useStartTimeInference */ true, OneDesignRankingMetric::new);
Iterable<Waypoint> emptyWaypointList = Collections.emptyList();
final String competitorName = "Der mit dem Kiel zieht";
Competitor competitor = master.getBaseDomainFactory().getOrCreateCompetitor(
123, competitorName, Color.RED, "someone@nowhere.de", flagImageURI,
new TeamImpl("STG", Collections.singleton(new PersonImpl(competitorName, new NationalityImpl("GER"),
/* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas",
new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")),
new BoatImpl(competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null);
Iterable<Competitor> competitors = Collections.singleton(competitor);
final String raceName = "Test Race";
RaceDefinition raceDefinition = new RaceDefinitionImpl(raceName, new CourseImpl("Empty Course", emptyWaypointList),
masterRegatta.getBoatClass(), competitors);
master.apply(new AddRaceDefinition(masterRegatta.getRegattaIdentifier(), raceDefinition));
Thread.sleep(1000);
Regatta replicatedRegatta = replica.getRegatta(new RegattaName(masterRegatta.getName()));
assertNotNull(replicatedRegatta);
assertTrue(replicatedRegatta.isPersistent());
assertTrue(Util.isEmpty((replicatedRegatta.getSeries())));
assertNull(replicatedRegatta.getDefaultCourseArea());
assertTrue(regattaId.equals(replicatedRegatta.getId()));
RaceDefinition replicatedRace = replicatedRegatta.getRaceByName(raceName);
assertNotNull(replicatedRace);
Competitor replicatedCompetitor = replicatedRace.getCompetitors().iterator().next();
assertNotSame(replicatedCompetitor, competitor);
assertEquals(competitor.getId(), replicatedCompetitor.getId());
assertEquals(competitor.getName(), replicatedCompetitor.getName());
assertEquals(competitor.getColor(), replicatedCompetitor.getColor());
assertEquals(competitor.getFlagImage(), replicatedCompetitor.getFlagImage());
assertEquals(competitor.getBoat().getSailID(), replicatedCompetitor.getBoat().getSailID());
assertEquals(competitor.getTeam().getNationality(), replicatedCompetitor.getTeam().getNationality());
// now update competitor on master using replicating operation
final String newCompetitorName = "Der Vogel, der mit dem Kiel zieht";
master.apply(new UpdateCompetitor(competitor.getId().toString(), newCompetitorName, competitor.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(),
competitor.getTeam().getImage(), competitor.getFlagImage(),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
Thread.sleep(1000);
assertEquals(newCompetitorName, replicatedCompetitor.getName()); // expect in-place update of existing competitor in replica
// now allow for resetting to default through some event, such as receiving a GPS position
master.apply(new AllowCompetitorResetToDefaults(Collections.singleton(competitor.getId().toString())));
// modify the competitor on the master "from below" without an UpdateCompetitor operation, only locally:
master.getBaseDomainFactory().getCompetitorStore().updateCompetitor(competitor.getId().toString(), competitorName, Color.RED, competitor.getEmail(),
competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
final RegattaAndRaceIdentifier raceIdentifier = masterRegatta.getRaceIdentifier(raceDefinition);
DynamicTrackedRace trackedRace = (DynamicTrackedRace) master.apply(new CreateTrackedRace(raceIdentifier,
EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 3000,
/* millisecondsOverWhichToAverageWind */ 30000l, /* millisecondsOverWhichToAverageSpeed */ 30000l));
trackedRace.getTrack(competitor).addGPSFix(new GPSFixMovingImpl(new DegreePosition(49.425, 8.293), MillisecondsTimePoint.now(),
new KnotSpeedWithBearingImpl(12.3, new DegreeBearingImpl(242.3))));
Thread.sleep(1000);
TrackedRace replicatedTrackedRace = replica.getTrackedRace(raceIdentifier);
assertNotNull(replicatedTrackedRace);
assertNotNull(replicatedTrackedRace.getTrack(replicatedCompetitor).getFirstRawFix());
assertEquals(competitorName, replicatedCompetitor.getName());
}
}
@@ -83,7 +83,7 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio
new PersonImpl("Tina Lutz", masterDomainFactory.getOrCreateNationality("GER"), null, null) }),
new PersonImpl("Rigo de Mas", masterDomainFactory.getOrCreateNationality("NED"), null, null)),
new BoatImpl("GER 61", masterDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null);
final String baseEventName = "Test Event";
AddDefaultRegatta addEventOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName,
/*startDate*/ null, /*endDate*/ null, UUID.randomUUID());
@@ -84,7 +84,7 @@ public class TrackedRaceWithGPSFixStoreContentsReplicationTest extends AbstractS
new PersonImpl("Tina Lutz", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null) }),
new PersonImpl("Rigo de Mas", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)),
new BoatImpl("GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null);
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null);
final String baseEventName = "Test Event";
AddDefaultRegatta addEventOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName,
/*startDate*/ null, /*endDate*/ null, UUID.randomUUID());
@@ -1,86 +1,86 @@
package com.sap.sailing.server.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sailing.domain.test.AbstractLeaderboardTest;
import com.sap.sailing.server.impl.PersistentCompetitorStore;
import com.sap.sse.common.Duration;
public class CompetitorStoreTest {
@Test
public void testAddingToTransientStore() {
CompetitorStore transientStore = new TransientCompetitorStoreImpl();
DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor");
Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(),
/* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730));
assertTrue(competitor != template);
Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(),
template.getBoat(), /* timeOnTimeFactor */ 1.345,
/* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(750.2));
assertSame(competitor, competitor2);
assertEquals(DomainFactory.INSTANCE.getOrCreateNationality("GER"), competitor.getTeam().getNationality());
DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam();
differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana
Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */
null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null);
assertSame(competitor, competitor3); // use existing competitor despite the different team
assertSame(competitor.getTeam(), competitor3.getTeam());
// now mark the competitor as to update from defaults
transientStore.allowCompetitorResetToDefaults(competitor);
Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */
null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null);
assertSame(competitor, competitor4); // expecting an in-place update
assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality());
}
@Test
public void testPersistentCompetitorStore() {
CompetitorStore persistentStore1 = new PersistentCompetitorStore(
PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null);
DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor");
Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(),
template.getBoat(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730));
CompetitorStore persistentStore2 = new PersistentCompetitorStore(
PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null);
Competitor competitor2 = persistentStore2.getExistingCompetitorById(template.getId());
assertNotSame(competitor2, template); // the new store loads new instances from the database
assertEquals(template.getId(), competitor2.getId());
assertEquals(template.getTeam().getNationality(), competitor2.getTeam().getNationality());
assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001);
assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001);
DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam();
differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana
Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */
null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null);
assertSame(competitor2, competitor3); // use existing competitor despite the different team
assertNotSame(differentTeam, competitor2.getTeam()); // team expected to remain unchanged
assertEquals(competitor.getTeam().getNationality(), competitor3.getTeam().getNationality()); // no updatability requested; nationality
// expected to remain unchanged
// now mark the competitor as to update from defaults
persistentStore2.allowCompetitorResetToDefaults(competitor2);
Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */
null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null);
assertSame(competitor2, competitor4); // expecting an in-place update
assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality());
}
}
package com.sap.sailing.server.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sailing.domain.test.AbstractLeaderboardTest;
import com.sap.sailing.server.impl.PersistentCompetitorStore;
import com.sap.sse.common.Duration;
public class CompetitorStoreTest {
@Test
public void testAddingToTransientStore() {
CompetitorStore transientStore = new TransientCompetitorStoreImpl();
DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor");
Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(),
/* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null);
assertTrue(competitor != template);
Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(),
template.getBoat(), /* timeOnTimeFactor */ 1.345,
/* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(750.2), null);
assertSame(competitor, competitor2);
assertEquals(DomainFactory.INSTANCE.getOrCreateNationality("GER"), competitor.getTeam().getNationality());
DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam();
differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana
Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */
null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null);
assertSame(competitor, competitor3); // use existing competitor despite the different team
assertSame(competitor.getTeam(), competitor3.getTeam());
// now mark the competitor as to update from defaults
transientStore.allowCompetitorResetToDefaults(competitor);
Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */
null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null);
assertSame(competitor, competitor4); // expecting an in-place update
assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality());
}
@Test
public void testPersistentCompetitorStore() {
CompetitorStore persistentStore1 = new PersistentCompetitorStore(
PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null);
DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor");
Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(),
template.getBoat(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null);
CompetitorStore persistentStore2 = new PersistentCompetitorStore(
PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null);
Competitor competitor2 = persistentStore2.getExistingCompetitorById(template.getId());
assertNotSame(competitor2, template); // the new store loads new instances from the database
assertEquals(template.getId(), competitor2.getId());
assertEquals(template.getTeam().getNationality(), competitor2.getTeam().getNationality());
assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001);
assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001);
DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam();
differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana
Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */
null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null);
assertSame(competitor2, competitor3); // use existing competitor despite the different team
assertNotSame(differentTeam, competitor2.getTeam()); // team expected to remain unchanged
assertEquals(competitor.getTeam().getNationality(), competitor3.getTeam().getNationality()); // no updatability requested; nationality
// expected to remain unchanged
// now mark the competitor as to update from defaults
persistentStore2.allowCompetitorResetToDefaults(competitor2);
Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(),
template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */
null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null);
assertSame(competitor2, competitor4); // expecting an in-place update
assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality());
}
}
@@ -1,90 +1,90 @@
package com.sap.sailing.server.test;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.junit.Test;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicPerson;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sse.mongodb.MongoDBService;
public class LeaderboardStorageTest extends TestCase {
private static final String LEADERBOARD_NAME = "test";
@Override
protected void setUp() throws Exception {
removeTestLeaderboard();
}
@Override
protected void tearDown() throws Exception {
removeTestLeaderboard();
}
private void removeTestLeaderboard() {
RacingEventService service = new RacingEventServiceImpl();
if (service.getLeaderboardByName(LEADERBOARD_NAME) != null) {
service.removeLeaderboard(LEADERBOARD_NAME);
}
}
@Test
public void testIfCarriedPointsAreStoredIfNoRacesAreTracked() {
RacingEventService service = new RacingEventServiceImpl();
int[] dicardingThresholds = {};
Leaderboard leaderboard = service.addFlexibleLeaderboard(LEADERBOARD_NAME, "testIt", dicardingThresholds,
new LowPoint(), "maaap");
List<DynamicPerson> sailorList = new ArrayList<DynamicPerson>();
sailorList.add(new PersonImpl("sailor", new NationalityImpl("GER"), null, ""));
DynamicTeam team = new TeamImpl("team", sailorList, null);
DynamicBoat boat = new BoatImpl("woot", service.getBaseDomainFactory().getOrCreateBoatClass("H16"), "70155");
String competitorId = "testC";
Competitor competitor = service.getBaseDomainFactory().getOrCreateCompetitor(competitorId, "Test C", null,
null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null);
double carriedPoints = 2.0;
leaderboard.setCarriedPoints(competitor, carriedPoints);
service.getMongoObjectFactory().storeLeaderboard(leaderboard);
// Test in db
DBCollection leaderboardCollection = MongoDBService.INSTANCE.getDB().getCollection("LEADERBOARDS");
BasicDBObject query = new BasicDBObject();
query.put("LEADERBOARD_NAME", LEADERBOARD_NAME);
DBCursor leaderboardObjectCursor = leaderboardCollection.find();
DBObject dbLeaderboard = leaderboardObjectCursor.next();
BasicDBList carriedPointsById = (BasicDBList) dbLeaderboard.get("LEADERBOARD_CARRIED_POINTS_BY_ID");
if (carriedPointsById != null) {
for (Object o : carriedPointsById) {
DBObject competitorIdAndCarriedPoints = (DBObject) o;
Serializable competitorIdFromDB = (Serializable) competitorIdAndCarriedPoints.get("COMPETITOR_ID");
Double carriedPointsForCompetitor = ((Number) competitorIdAndCarriedPoints
.get("LEADERBOARD_CARRIED_POINTS")).doubleValue();
assertEquals(competitorId, competitorIdFromDB);
assertEquals(carriedPoints, carriedPointsForCompetitor, 0.0001);
}
}
}
}
package com.sap.sailing.server.test;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.junit.Test;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.DynamicBoat;
import com.sap.sailing.domain.base.impl.DynamicPerson;
import com.sap.sailing.domain.base.impl.DynamicTeam;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sse.mongodb.MongoDBService;
public class LeaderboardStorageTest extends TestCase {
private static final String LEADERBOARD_NAME = "test";
@Override
protected void setUp() throws Exception {
removeTestLeaderboard();
}
@Override
protected void tearDown() throws Exception {
removeTestLeaderboard();
}
private void removeTestLeaderboard() {
RacingEventService service = new RacingEventServiceImpl();
if (service.getLeaderboardByName(LEADERBOARD_NAME) != null) {
service.removeLeaderboard(LEADERBOARD_NAME);
}
}
@Test
public void testIfCarriedPointsAreStoredIfNoRacesAreTracked() {
RacingEventService service = new RacingEventServiceImpl();
int[] dicardingThresholds = {};
Leaderboard leaderboard = service.addFlexibleLeaderboard(LEADERBOARD_NAME, "testIt", dicardingThresholds,
new LowPoint(), "maaap");
List<DynamicPerson> sailorList = new ArrayList<DynamicPerson>();
sailorList.add(new PersonImpl("sailor", new NationalityImpl("GER"), null, ""));
DynamicTeam team = new TeamImpl("team", sailorList, null);
DynamicBoat boat = new BoatImpl("woot", service.getBaseDomainFactory().getOrCreateBoatClass("H16"), "70155");
String competitorId = "testC";
Competitor competitor = service.getBaseDomainFactory().getOrCreateCompetitor(competitorId, "Test C", null,
null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null);
double carriedPoints = 2.0;
leaderboard.setCarriedPoints(competitor, carriedPoints);
service.getMongoObjectFactory().storeLeaderboard(leaderboard);
// Test in db
DBCollection leaderboardCollection = MongoDBService.INSTANCE.getDB().getCollection("LEADERBOARDS");
BasicDBObject query = new BasicDBObject();
query.put("LEADERBOARD_NAME", LEADERBOARD_NAME);
DBCursor leaderboardObjectCursor = leaderboardCollection.find();
DBObject dbLeaderboard = leaderboardObjectCursor.next();
BasicDBList carriedPointsById = (BasicDBList) dbLeaderboard.get("LEADERBOARD_CARRIED_POINTS_BY_ID");
if (carriedPointsById != null) {
for (Object o : carriedPointsById) {
DBObject competitorIdAndCarriedPoints = (DBObject) o;
Serializable competitorIdFromDB = (Serializable) competitorIdAndCarriedPoints.get("COMPETITOR_ID");
Double carriedPointsForCompetitor = ((Number) competitorIdAndCarriedPoints
.get("LEADERBOARD_CARRIED_POINTS")).doubleValue();
assertEquals(competitorId, competitorIdFromDB);
assertEquals(carriedPoints, carriedPointsForCompetitor, 0.0001);
}
}
}
}
File diff suppressed because it is too large. Load diff
@@ -1,220 +1,220 @@
package com.sap.sailing.server.test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.Wind;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.impl.WindImpl;
import com.sap.sailing.domain.common.impl.WindSourceImpl;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard;
import com.sap.sailing.server.operationaltransformation.AddDefaultRegatta;
import com.sap.sailing.server.operationaltransformation.AddRaceDefinition;
import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateTrackedRace;
import com.sap.sailing.server.operationaltransformation.DisconnectLeaderboardColumnFromTrackedRace;
import com.sap.sailing.server.operationaltransformation.TrackRegatta;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class WindByRaceLogTest {
private DynamicTrackedRace trackedRace;
private RegattaNameAndRaceName raceIdentifier;
private RaceColumn raceColumn;
private Fleet defaultFleet;
private RacingEventService service;
private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1);
@Before
public void setup() throws Exception {
this.service = new RacingEventServiceImpl();
final String boatClassName = "49er";
// FIXME use master DomainFactory; see bug 592
final DomainFactory masterDomainFactory = service.getBaseDomainFactory();
BoatClass boatClass = masterDomainFactory.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */true);
Competitor competitor = createCompetitor(masterDomainFactory);
int[] discardThreshold = {1, 2};
CreateFlexibleLeaderboard createLeaderboardOperation = new CreateFlexibleLeaderboard("Test Leaderboard", "Test", discardThreshold, new LowPoint(), null);
service.apply(createLeaderboardOperation);
AddColumnToLeaderboard leaderboardColumnOperation = new AddColumnToLeaderboard("R1", "Test Leaderboard", false);
raceColumn = service.apply(leaderboardColumnOperation);
final String baseRegattaName = "Test Event";
AddDefaultRegatta addRegattaOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseRegattaName, boatClassName), boatClassName,
/*startDate*/ null, /*endDate*/ null, UUID.randomUUID());
Regatta regatta = service.apply(addRegattaOperation);
final String raceName = "Test Race";
final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList<Waypoint>());
RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, Collections.singletonList(competitor));
AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race);
service.apply(addRaceOperation);
masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingInstruction*/ null));
raceIdentifier = new RegattaNameAndRaceName(regatta.getName(), raceName);
service.apply(new TrackRegatta(raceIdentifier));
trackedRace = (DynamicTrackedRace) service.apply(new CreateTrackedRace(raceIdentifier, EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE,/* delayToLiveInMillis */ 5000,
/* millisecondsOverWhichToAverageWind */ 10000, /* millisecondsOverWhichToAverageSpeed */10000));
trackedRace.setStartOfTrackingReceived(MillisecondsTimePoint.now());
defaultFleet = Util.get(raceColumn.getFleets(), 0);
}
private Competitor createCompetitor(final DomainFactory masterDomainFactory) {
return masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor",
(List<PersonImpl>) Arrays.asList(new PersonImpl[] { new PersonImpl("Sailor 1", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null)}),
new PersonImpl("Sailor 2", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)),
new BoatImpl("GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null);
}
private void attachTrackedRaceToRaceColumn() {
ConnectTrackedRaceToLeaderboardColumn connectColumn = new ConnectTrackedRaceToLeaderboardColumn("Test Leaderboard", "R1",
defaultFleet.getName(), raceIdentifier);
service.apply(connectColumn);
}
private void detachTrackedRaceFromRaceColumn() {
DisconnectLeaderboardColumnFromTrackedRace disconnectColumn = new DisconnectLeaderboardColumnFromTrackedRace("Test Leaderboard", "R1", defaultFleet.getName());
service.apply(disconnectColumn);
}
@Test
public void testAttachingRaceLogContainingWindFixes() {
RaceLog raceLog = raceColumn.getRaceLog(defaultFleet);
TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20);
TimePoint timeMinus2 = MillisecondsTimePoint.now().minus(10);
Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3,
new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234)));
Wind wind2 = new WindImpl(new DegreePosition(49, 3), timeMinus2,
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)));
RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false);
RaceLogWindFixEvent windEvent2 = new RaceLogWindFixEventImpl(timeMinus2, author, 0, wind2, /* isMagnetic */ false);
raceLog.add(windEvent1);
raceLog.add(windEvent2);
attachTrackedRaceToRaceColumn();
WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE);
assertTrue(Util.contains(trackedRace.getWindSources(), source));
WindTrack windTrack = trackedRace.getOrCreateWindTrack(source);
try {
windTrack.lockForRead();
assertTrue(Util.contains(windTrack.getFixes(), wind1));
assertTrue(Util.contains(windTrack.getFixes(), wind2));
} finally {
windTrack.unlockAfterRead();
}
}
@Test
public void testAttachingRaceLogAndAddWindFixes() {
RaceLog raceLog = raceColumn.getRaceLog(defaultFleet);
TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20);
attachTrackedRaceToRaceColumn();
Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3,
new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234)));
RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false);
raceLog.add(windEvent1);
WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE);
assertTrue(Util.contains(trackedRace.getWindSources(), source));
WindTrack windTrack = trackedRace.getOrCreateWindTrack(source);
try {
windTrack.lockForRead();
assertTrue(Util.contains(windTrack.getFixes(), wind1));
} finally {
windTrack.unlockAfterRead();
}
}
@Test
public void testDetachingRaceLogWithWindFixes() {
RaceLog raceLog = raceColumn.getRaceLog(defaultFleet);
TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20);
TimePoint timeMinus2 = MillisecondsTimePoint.now().minus(10);
TimePoint timeMinus1 = MillisecondsTimePoint.now().minus(5);
Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3,
new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234)));
Wind wind2 = new WindImpl(new DegreePosition(49, 3), timeMinus2,
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)));
Wind wind3 = new WindImpl(new DegreePosition(48, 1), timeMinus2,
new KnotSpeedWithBearingImpl(18, new DegreeBearingImpl(270)));
RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false);
RaceLogWindFixEvent windEvent2 = new RaceLogWindFixEventImpl(timeMinus2, author, 0, wind2, /* isMagnetic */ false);
RaceLogWindFixEvent windEvent3 = new RaceLogWindFixEventImpl(timeMinus1, author, 0, wind3, /* isMagnetic */ false);
raceLog.add(windEvent1);
raceLog.add(windEvent2);
attachTrackedRaceToRaceColumn();
raceLog.add(windEvent3);
detachTrackedRaceFromRaceColumn();
WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE);
assertTrue(Util.contains(trackedRace.getWindSources(), source));
WindTrack windTrack = trackedRace.getOrCreateWindTrack(source);
try {
windTrack.lockForRead();
assertFalse(Util.contains(windTrack.getFixes(), wind1));
assertFalse(Util.contains(windTrack.getFixes(), wind2));
assertFalse(Util.contains(windTrack.getFixes(), wind3));
} finally {
windTrack.unlockAfterRead();
}
}
}
package com.sap.sailing.server.test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.Wind;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.impl.WindImpl;
import com.sap.sailing.domain.common.impl.WindSourceImpl;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard;
import com.sap.sailing.server.operationaltransformation.AddDefaultRegatta;
import com.sap.sailing.server.operationaltransformation.AddRaceDefinition;
import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateTrackedRace;
import com.sap.sailing.server.operationaltransformation.DisconnectLeaderboardColumnFromTrackedRace;
import com.sap.sailing.server.operationaltransformation.TrackRegatta;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class WindByRaceLogTest {
private DynamicTrackedRace trackedRace;
private RegattaNameAndRaceName raceIdentifier;
private RaceColumn raceColumn;
private Fleet defaultFleet;
private RacingEventService service;
private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1);
@Before
public void setup() throws Exception {
this.service = new RacingEventServiceImpl();
final String boatClassName = "49er";
// FIXME use master DomainFactory; see bug 592
final DomainFactory masterDomainFactory = service.getBaseDomainFactory();
BoatClass boatClass = masterDomainFactory.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */true);
Competitor competitor = createCompetitor(masterDomainFactory);
int[] discardThreshold = {1, 2};
CreateFlexibleLeaderboard createLeaderboardOperation = new CreateFlexibleLeaderboard("Test Leaderboard", "Test", discardThreshold, new LowPoint(), null);
service.apply(createLeaderboardOperation);
AddColumnToLeaderboard leaderboardColumnOperation = new AddColumnToLeaderboard("R1", "Test Leaderboard", false);
raceColumn = service.apply(leaderboardColumnOperation);
final String baseRegattaName = "Test Event";
AddDefaultRegatta addRegattaOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseRegattaName, boatClassName), boatClassName,
/*startDate*/ null, /*endDate*/ null, UUID.randomUUID());
Regatta regatta = service.apply(addRegattaOperation);
final String raceName = "Test Race";
final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList<Waypoint>());
RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, Collections.singletonList(competitor));
AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race);
service.apply(addRaceOperation);
masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingInstruction*/ null));
raceIdentifier = new RegattaNameAndRaceName(regatta.getName(), raceName);
service.apply(new TrackRegatta(raceIdentifier));
trackedRace = (DynamicTrackedRace) service.apply(new CreateTrackedRace(raceIdentifier, EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE,/* delayToLiveInMillis */ 5000,
/* millisecondsOverWhichToAverageWind */ 10000, /* millisecondsOverWhichToAverageSpeed */10000));
trackedRace.setStartOfTrackingReceived(MillisecondsTimePoint.now());
defaultFleet = Util.get(raceColumn.getFleets(), 0);
}
private Competitor createCompetitor(final DomainFactory masterDomainFactory) {
return masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor",
(List<PersonImpl>) Arrays.asList(new PersonImpl[] { new PersonImpl("Sailor 1", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null)}),
new PersonImpl("Sailor 2", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)),
new BoatImpl("GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null);
}
private void attachTrackedRaceToRaceColumn() {
ConnectTrackedRaceToLeaderboardColumn connectColumn = new ConnectTrackedRaceToLeaderboardColumn("Test Leaderboard", "R1",
defaultFleet.getName(), raceIdentifier);
service.apply(connectColumn);
}
private void detachTrackedRaceFromRaceColumn() {
DisconnectLeaderboardColumnFromTrackedRace disconnectColumn = new DisconnectLeaderboardColumnFromTrackedRace("Test Leaderboard", "R1", defaultFleet.getName());
service.apply(disconnectColumn);
}
@Test
public void testAttachingRaceLogContainingWindFixes() {
RaceLog raceLog = raceColumn.getRaceLog(defaultFleet);
TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20);
TimePoint timeMinus2 = MillisecondsTimePoint.now().minus(10);
Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3,
new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234)));
Wind wind2 = new WindImpl(new DegreePosition(49, 3), timeMinus2,
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)));
RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false);
RaceLogWindFixEvent windEvent2 = new RaceLogWindFixEventImpl(timeMinus2, author, 0, wind2, /* isMagnetic */ false);
raceLog.add(windEvent1);
raceLog.add(windEvent2);
attachTrackedRaceToRaceColumn();
WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE);
assertTrue(Util.contains(trackedRace.getWindSources(), source));
WindTrack windTrack = trackedRace.getOrCreateWindTrack(source);
try {
windTrack.lockForRead();
assertTrue(Util.contains(windTrack.getFixes(), wind1));
assertTrue(Util.contains(windTrack.getFixes(), wind2));
} finally {
windTrack.unlockAfterRead();
}
}
@Test
public void testAttachingRaceLogAndAddWindFixes() {
RaceLog raceLog = raceColumn.getRaceLog(defaultFleet);
TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20);
attachTrackedRaceToRaceColumn();
Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3,
new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234)));
RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false);
raceLog.add(windEvent1);
WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE);
assertTrue(Util.contains(trackedRace.getWindSources(), source));
WindTrack windTrack = trackedRace.getOrCreateWindTrack(source);
try {
windTrack.lockForRead();
assertTrue(Util.contains(windTrack.getFixes(), wind1));
} finally {
windTrack.unlockAfterRead();
}
}
@Test
public void testDetachingRaceLogWithWindFixes() {
RaceLog raceLog = raceColumn.getRaceLog(defaultFleet);
TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20);
TimePoint timeMinus2 = MillisecondsTimePoint.now().minus(10);
TimePoint timeMinus1 = MillisecondsTimePoint.now().minus(5);
Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3,
new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234)));
Wind wind2 = new WindImpl(new DegreePosition(49, 3), timeMinus2,
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)));
Wind wind3 = new WindImpl(new DegreePosition(48, 1), timeMinus2,
new KnotSpeedWithBearingImpl(18, new DegreeBearingImpl(270)));
RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false);
RaceLogWindFixEvent windEvent2 = new RaceLogWindFixEventImpl(timeMinus2, author, 0, wind2, /* isMagnetic */ false);
RaceLogWindFixEvent windEvent3 = new RaceLogWindFixEventImpl(timeMinus1, author, 0, wind3, /* isMagnetic */ false);
raceLog.add(windEvent1);
raceLog.add(windEvent2);
attachTrackedRaceToRaceColumn();
raceLog.add(windEvent3);
detachTrackedRaceFromRaceColumn();
WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE);
assertTrue(Util.contains(trackedRace.getWindSources(), source));
WindTrack windTrack = trackedRace.getOrCreateWindTrack(source);
try {
windTrack.lockForRead();
assertFalse(Util.contains(windTrack.getFixes(), wind1));
assertFalse(Util.contains(windTrack.getFixes(), wind2));
assertFalse(Util.contains(windTrack.getFixes(), wind3));
} finally {
windTrack.unlockAfterRead();
}
}
}
@@ -1,109 +1,110 @@
package com.sap.sailing.server.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.net.URI;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TypeBasedServiceFinderFactory;
import com.sap.sse.mongodb.MongoDBService;
/**
* Manages a persistent set of {@link Competitor}s using a {@link MongoObjectFactory} to update the persistent store,
* and a {@link DomainObjectFactory} for initially filling this store's in-memory representation from the persistent
* store.<p>
*
* Note that the results of calling {@link CompetitorStore#allowCompetitorResetToDefaults(Competitor)} are not stored
* persistently and therefore will be reset when re-initializing a competitor store from the database.
*
* @author Axel Uhl (d043530)
*
*/
public class PersistentCompetitorStore extends TransientCompetitorStoreImpl implements CompetitorStore {
private static final long serialVersionUID = 9205956018421790908L;
private transient MongoObjectFactory storeTo;
private transient DomainObjectFactory loadFrom;
/**
* @param clear
* if <code>true</code>, the persistent competitor store is initially cleared, with all persistent
* competitor data removed; use with caution!
*/
public PersistentCompetitorStore(MongoObjectFactory storeTo, boolean clear,
TypeBasedServiceFinderFactory serviceFinderFactory, RaceLogResolver raceLogResolver) {
DomainFactoryImpl baseDomainFactory = new DomainFactoryImpl(this, raceLogResolver);
this.loadFrom = PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, baseDomainFactory, serviceFinderFactory);
this.storeTo = storeTo;
if (clear) {
storeTo.removeAllCompetitors();
} else {
for (Competitor competitor : loadFrom.loadAllCompetitors()) {
addCompetitorToTransientStore(competitor.getId(), competitor);
}
}
}
DomainObjectFactory getDomainObjectFactory() {
return loadFrom;
}
MongoObjectFactory getMongoObjectFactory() {
return storeTo;
}
DomainFactory getBaseDomainFactory() {
return loadFrom.getBaseDomainFactory();
}
/**
* Uses the {@link PersistenceFactory#getDefaultMongoObjectFactory() default DB persistence} to store new competitors.
* Use {@link #setStoreTo} to change this after de-serialization.
*/
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
storeTo = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory();
}
private void addCompetitorToTransientStore(Serializable id, Competitor competitor) {
super.addNewCompetitor(id, competitor);
}
@Override
protected void addNewCompetitor(Serializable id, Competitor competitor) {
storeTo.storeCompetitor(competitor);
super.addNewCompetitor(id, competitor);
}
@Override
public void clear() {
storeTo.removeAllCompetitors();
super.clear();
}
@Override
public void removeCompetitor(Competitor competitor) {
storeTo.removeCompetitor(competitor);
super.removeCompetitor(competitor);
}
@Override
public Competitor updateCompetitor(String idAsString, String newName, Color newRgbDisplayColor, String newEmail, String newSailId,
Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) {
Competitor result = super.updateCompetitor(idAsString, newName, newRgbDisplayColor, newEmail, newSailId, newNationality,
newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile);
storeTo.storeCompetitor(result);
return result;
}
}
package com.sap.sailing.server.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.net.URI;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TypeBasedServiceFinderFactory;
import com.sap.sse.mongodb.MongoDBService;
/**
* Manages a persistent set of {@link Competitor}s using a {@link MongoObjectFactory} to update the persistent store,
* and a {@link DomainObjectFactory} for initially filling this store's in-memory representation from the persistent
* store.<p>
*
* Note that the results of calling {@link CompetitorStore#allowCompetitorResetToDefaults(Competitor)} are not stored
* persistently and therefore will be reset when re-initializing a competitor store from the database.
*
* @author Axel Uhl (d043530)
*
*/
public class PersistentCompetitorStore extends TransientCompetitorStoreImpl implements CompetitorStore {
private static final long serialVersionUID = 9205956018421790908L;
private transient MongoObjectFactory storeTo;
private transient DomainObjectFactory loadFrom;
/**
* @param clear
* if <code>true</code>, the persistent competitor store is initially cleared, with all persistent
* competitor data removed; use with caution!
*/
public PersistentCompetitorStore(MongoObjectFactory storeTo, boolean clear,
TypeBasedServiceFinderFactory serviceFinderFactory, RaceLogResolver raceLogResolver) {
DomainFactoryImpl baseDomainFactory = new DomainFactoryImpl(this, raceLogResolver);
this.loadFrom = PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, baseDomainFactory, serviceFinderFactory);
this.storeTo = storeTo;
if (clear) {
storeTo.removeAllCompetitors();
} else {
for (Competitor competitor : loadFrom.loadAllCompetitors()) {
addCompetitorToTransientStore(competitor.getId(), competitor);
}
}
}
DomainObjectFactory getDomainObjectFactory() {
return loadFrom;
}
MongoObjectFactory getMongoObjectFactory() {
return storeTo;
}
DomainFactory getBaseDomainFactory() {
return loadFrom.getBaseDomainFactory();
}
/**
* Uses the {@link PersistenceFactory#getDefaultMongoObjectFactory() default DB persistence} to store new competitors.
* Use {@link #setStoreTo} to change this after de-serialization.
*/
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
storeTo = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory();
}
private void addCompetitorToTransientStore(Serializable id, Competitor competitor) {
super.addNewCompetitor(id, competitor);
}
@Override
protected void addNewCompetitor(Serializable id, Competitor competitor) {
storeTo.storeCompetitor(competitor);
super.addNewCompetitor(id, competitor);
}
@Override
public void clear() {
storeTo.removeAllCompetitors();
super.clear();
}
@Override
public void removeCompetitor(Competitor competitor) {
storeTo.removeCompetitor(competitor);
super.removeCompetitor(competitor);
}
@Override
public Competitor updateCompetitor(String idAsString, String newName, Color newRgbDisplayColor, String newEmail, String newSailId,
Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile,
String searchTag) {
Competitor result = super.updateCompetitor(idAsString, newName, newRgbDisplayColor, newEmail, newSailId, newNationality,
newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag);
storeTo.storeCompetitor(result);
return result;
}
}
@@ -547,7 +547,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
replicate(new UpdateCompetitor(competitor.getId().toString(), competitor.getName(), competitor
.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(),
competitor.getTeam().getImage(), competitor.getFlagImage(),
competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile()));
competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(),
competitor.getSearchTag()));
}
});
this.windStore = windStore;
@@ -2510,7 +2511,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
competitorStore.getOrCreateCompetitor(dynamicCompetitor.getId(), dynamicCompetitor.getName(),
dynamicCompetitor.getColor(), dynamicCompetitor.getEmail(), dynamicCompetitor.getFlagImage(),
dynamicCompetitor.getTeam(), dynamicCompetitor.getBoat(), dynamicCompetitor.getTimeOnTimeFactor(),
dynamicCompetitor.getTimeOnDistanceAllowancePerNauticalMile());
dynamicCompetitor.getTimeOnDistanceAllowancePerNauticalMile(), dynamicCompetitor.getSearchTag());
}
logoutput.append("Received " + competitorStore.size() + " NEW competitors\n");
@@ -1,76 +1,78 @@
package com.sap.sailing.server.operationaltransformation;
import java.net.URI;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
public class UpdateCompetitor extends AbstractRacingEventServiceOperation<Competitor> {
private static final long serialVersionUID = 1172181354320184263L;
private final String idAsString;
private final String newName;
private final Color newDisplayColor;
private final String newSailId;
private final String newEmail;
private final Nationality newNationality;
private final URI newTeamImageUri;
private final URI newFlagImageUri;
private final Double timeOnTimeFactor;
private final Duration timeOnDistanceAllowancePerNauticalMile;
/**
* @param idAsString
* Identified the competitor to update
* @param newNationality
* if <code>null</code>, the competitor obtains the "NONE" nationality, usually represented by a white
* flag
*/
public UpdateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail,
String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri,
Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) {
super();
this.idAsString = idAsString;
this.newName = newName;
this.newDisplayColor = newDisplayColor;
this.newSailId = newSailId;
this.newNationality = newNationality;
this.newTeamImageUri = newTeamImageUri;
this.newEmail = newEmail;
this.newFlagImageUri = newFlagImageUri;
this.timeOnTimeFactor = timeOnTimeFactor;
this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile;
}
/**
* {@link #internalApplyTo(RacingEventService)} already replicates the effects
*/
@Override
public boolean isRequiresExplicitTransitiveReplication() {
return false;
}
@Override
public Competitor internalApplyTo(RacingEventService toState) throws Exception {
Competitor result = toState.getBaseDomainFactory().getCompetitorStore()
.updateCompetitor(idAsString, newName, newDisplayColor, newEmail, newSailId, newNationality,
newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile);
return result;
}
@Override
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
// TODO Auto-generated method stub
return null;
}
}
package com.sap.sailing.server.operationaltransformation;
import java.net.URI;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
public class UpdateCompetitor extends AbstractRacingEventServiceOperation<Competitor> {
private static final long serialVersionUID = 1172181354320184263L;
private final String idAsString;
private final String newName;
private final Color newDisplayColor;
private final String newSailId;
private final String newEmail;
private final Nationality newNationality;
private final URI newTeamImageUri;
private final URI newFlagImageUri;
private final Double timeOnTimeFactor;
private final Duration timeOnDistanceAllowancePerNauticalMile;
private final String newSearchTag;
/**
* @param idAsString
* Identified the competitor to update
* @param newNationality
* if <code>null</code>, the competitor obtains the "NONE" nationality, usually represented by a white
* flag
*/
public UpdateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail,
String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri,
Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String newSearchTag) {
super();
this.idAsString = idAsString;
this.newName = newName;
this.newDisplayColor = newDisplayColor;
this.newSailId = newSailId;
this.newNationality = newNationality;
this.newTeamImageUri = newTeamImageUri;
this.newEmail = newEmail;
this.newFlagImageUri = newFlagImageUri;
this.timeOnTimeFactor = timeOnTimeFactor;
this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile;
this.newSearchTag = newSearchTag;
}
/**
* {@link #internalApplyTo(RacingEventService)} already replicates the effects
*/
@Override
public boolean isRequiresExplicitTransitiveReplication() {
return false;
}
@Override
public Competitor internalApplyTo(RacingEventService toState) throws Exception {
Competitor result = toState.getBaseDomainFactory().getCompetitorStore()
.updateCompetitor(idAsString, newName, newDisplayColor, newEmail, newSailId, newNationality,
newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, newSearchTag);
return result;
}
@Override
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
// TODO Auto-generated method stub
return null;
}
}
@@ -210,7 +210,7 @@ public class StructureImporter {
BoatAndTeam boatAndTeam = getBoatAndTeam(idAsString, name, nationality, boatClass);
this.baseDomainFactory.convertToCompetitorDTO(this.baseDomainFactory.getOrCreateCompetitor(
UUID.fromString(idAsString), name, color, email, flagImage, boatAndTeam.getTeam(), boatAndTeam.getBoat(),
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null));
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
} else {
break;
}
@@ -1,257 +1,257 @@
package com.sap.sailing.racecommittee.app.data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl;
import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.LeaderboardGroupBase;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.configuration.ConfigurationLoader;
import com.sap.sailing.domain.base.configuration.DeviceConfiguration;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.base.impl.MarkImpl;
import com.sap.sailing.domain.base.impl.StrippedEventImpl;
import com.sap.sailing.domain.base.racegroup.RaceGroup;
import com.sap.sailing.domain.base.racegroup.SeriesWithRows;
import com.sap.sailing.domain.base.racegroup.impl.RaceGroupImpl;
import com.sap.sailing.domain.base.racegroup.impl.SeriesWithRowsImpl;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.racecommittee.app.AppPreferences;
import com.sap.sailing.racecommittee.app.data.clients.LoadClient;
import com.sap.sailing.racecommittee.app.data.loaders.DataLoaderResult;
import com.sap.sailing.racecommittee.app.data.loaders.ImmediateDataLoaderCallbacks;
import com.sap.sailing.racecommittee.app.domain.CoursePosition;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.configuration.impl.PreferencesRegattaConfigurationLoader;
import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceIdentifierImpl;
import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceImpl;
import com.sap.sailing.racecommittee.app.ui.fragments.lists.PositionListFragment;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class OfflineDataManager extends DataManager {
private static boolean isInitialized = false;
private final Context context;
protected OfflineDataManager(Context context, DataStore dataStore, SharedDomainFactory domainFactory) {
super(context, dataStore, domainFactory);
this.context = context;
if (!isInitialized) {
isInitialized = true;
fillDataStore(dataStore);
}
}
private void fillDataStore(DataStore dataStore) {
Calendar cal = Calendar.getInstance();
cal.set(2012, 12, 1);
final TimePoint startDate = new MillisecondsTimePoint(cal.getTimeInMillis());
cal.set(2012, 12, 5);
final TimePoint endDate = new MillisecondsTimePoint(cal.getTimeInMillis());
dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Cardiff)", startDate, endDate, "Cardiff", true, UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet()));
dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Nice)", startDate, endDate, "Nice", true, UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet()));
dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Rio)", startDate, endDate, "Rio", true, UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet()));
EventBase newEvent = new StrippedEventImpl("Extreme Sailing Series 2013 (Muscat)", startDate, endDate, "Muscat", true, UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet());
newEvent.getVenue().addCourseArea(new CourseAreaImpl("Offshore", UUID.randomUUID()));
newEvent.getVenue().addCourseArea(new CourseAreaImpl("Stadium", UUID.randomUUID()));
dataStore.addEvent(newEvent);
SeriesWithRows qualifying = new SeriesWithRowsImpl("Qualifying", false, null);
SeriesWithRows medal = new SeriesWithRowsImpl("Medal", true, null);
RaceGroup raceGroup = new RaceGroupImpl("ESS", /* displayName */ null, new BoatClassImpl("X40", false), null, Arrays.asList(qualifying,
medal), new EmptyRegattaConfiguration());
List<Competitor> competitors = new ArrayList<Competitor>();
competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.BLUE, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null));
competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", Color.LIGHT_GRAY, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null));
competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null));
competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", Color.GREEN, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null));
competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", Color.BLACK, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null));
RaceLog log = new RaceLogImpl(UUID.randomUUID());
final AbstractLogEventAuthor author = AppPreferences.on(context).getAuthor();
ConfigurationLoader<RegattaConfiguration> configuration = PreferencesRegattaConfigurationLoader
.loadFromPreferences(preferences);
log.add(new RaceLogStartTimeEventImpl(new MillisecondsTimePoint(new Date().getTime() - 2000), author, 1,
new MillisecondsTimePoint(new Date().getTime() - 1000)));
log.add(new RaceLogRaceStatusEventImpl(new MillisecondsTimePoint(new Date().getTime()),
AppPreferences.on(context).getAuthor(), 1, RaceLogRaceStatus.FINISHING));
ManagedRace q1 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("A.B", new FleetImpl("A"), qualifying, raceGroup),
RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration));
log = new RaceLogImpl(UUID.randomUUID());
/*
* log.add(factory.createStartTimeEvent( new MillisecondsTimePoint(new Date()), 1, RaceLogRaceStatus.SCHEDULED,
* new MillisecondsTimePoint(new Date().getTime() + 100000)));
*/
ManagedRace q2 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("B", new FleetImpl("A.A"), qualifying, raceGroup),
RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration));
log = new RaceLogImpl(UUID.randomUUID());
/*
* log.add(factory.createRaceStatusEvent( new MillisecondsTimePoint(new Date()), 5,
* RaceLogRaceStatus.FINISHED));
*/
ManagedRace q3 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("Q3", new FleetImpl("Default"), qualifying, raceGroup),
RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration));
/*
* ManagedRace m1 = new ManagedRaceImpl( new ManagedRaceIdentifierImpl( "M1", new FleetImpl("Default"), medal,
* raceGroup), null);
*/
dataStore.addRace(q1);
dataStore.addRace(q2);
dataStore.addRace(q3);
// dataStore.addRace(m1);
Mark m1 = new MarkImpl("Red");
Mark m2 = new MarkImpl("Green");
Mark m3 = new MarkImpl("White");
dataStore.addMark(m1);
dataStore.addMark(m2);
dataStore.addMark(m3);
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<EventBase>>> createEventsLoader(
LoadClient<Collection<EventBase>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<EventBase>>(context, callback,
new Callable<Collection<EventBase>>() {
@Override
public Collection<EventBase> call() throws Exception {
return dataStore.getEvents();
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<CourseArea>>> createCourseAreasLoader(
final Serializable parentEventId, LoadClient<Collection<CourseArea>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<CourseArea>>(context, callback,
new Callable<Collection<CourseArea>>() {
@Override
public Collection<CourseArea> call() throws Exception {
return dataStore.getCourseAreas(dataStore.getEvent(parentEventId));
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<CourseArea>>> createCourseAreasLoader(
final EventBase parentEvent, LoadClient<Collection<CourseArea>> callback) {
// TODO Auto-generated method stub
return new ImmediateDataLoaderCallbacks<Collection<CourseArea>>(context, callback,
new Callable<Collection<CourseArea>>() {
@Override
public Collection<CourseArea> call() throws Exception {
return dataStore.getCourseAreas(parentEvent);
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<ManagedRace>>> createRacesLoader(Serializable courseAreaId,
LoadClient<Collection<ManagedRace>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<ManagedRace>>(context, callback,
new Callable<Collection<ManagedRace>>() {
@Override
public Collection<ManagedRace> call() throws Exception {
return dataStore.getRaces();
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<Mark>>> createMarksLoader(ManagedRace managedRace,
LoadClient<Collection<Mark>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<Mark>>(context, callback, new Callable<Collection<Mark>>() {
@Override
public Collection<Mark> call() throws Exception {
return dataStore.getMarks();
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<CourseBase>> createCourseLoader(final ManagedRace managedRace,
LoadClient<CourseBase> callback) {
return new ImmediateDataLoaderCallbacks<CourseBase>(context, callback, new Callable<CourseBase>() {
@Override
public CourseBase call() throws Exception {
return managedRace.getCourseOnServer();
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<Competitor>>> createCompetitorsLoader(
final ManagedRace managedRace, LoadClient<Collection<Competitor>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<Competitor>>(context, callback,
new Callable<Collection<Competitor>>() {
@Override
public Collection<Competitor> call() throws Exception {
return managedRace.getCompetitors();
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<DeviceConfiguration>> createConfigurationLoader(
DeviceConfigurationIdentifier identifier, LoadClient<DeviceConfiguration> callback) {
return new ImmediateDataLoaderCallbacks<DeviceConfiguration>(context, callback,
new Callable<DeviceConfiguration>() {
@Override
public DeviceConfiguration call() throws Exception {
throw new IllegalStateException("No remote configuration in offline mode.");
}
});
}
@Override
public String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts, boolean showStreamlets, boolean showSimulation,
boolean showMapControls) {
throw new IllegalStateException("No wind map in offline mode.");
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<CoursePosition>>> createPositionLoader(
PositionListFragment positionListFragment) {
// TODO Auto-generated method stub
return null;
}
}
package com.sap.sailing.racecommittee.app.data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl;
import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.LeaderboardGroupBase;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.configuration.ConfigurationLoader;
import com.sap.sailing.domain.base.configuration.DeviceConfiguration;
import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.base.impl.MarkImpl;
import com.sap.sailing.domain.base.impl.StrippedEventImpl;
import com.sap.sailing.domain.base.racegroup.RaceGroup;
import com.sap.sailing.domain.base.racegroup.SeriesWithRows;
import com.sap.sailing.domain.base.racegroup.impl.RaceGroupImpl;
import com.sap.sailing.domain.base.racegroup.impl.SeriesWithRowsImpl;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.racecommittee.app.AppPreferences;
import com.sap.sailing.racecommittee.app.data.clients.LoadClient;
import com.sap.sailing.racecommittee.app.data.loaders.DataLoaderResult;
import com.sap.sailing.racecommittee.app.data.loaders.ImmediateDataLoaderCallbacks;
import com.sap.sailing.racecommittee.app.domain.CoursePosition;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.configuration.impl.PreferencesRegattaConfigurationLoader;
import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceIdentifierImpl;
import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceImpl;
import com.sap.sailing.racecommittee.app.ui.fragments.lists.PositionListFragment;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class OfflineDataManager extends DataManager {
private static boolean isInitialized = false;
private final Context context;
protected OfflineDataManager(Context context, DataStore dataStore, SharedDomainFactory domainFactory) {
super(context, dataStore, domainFactory);
this.context = context;
if (!isInitialized) {
isInitialized = true;
fillDataStore(dataStore);
}
}
private void fillDataStore(DataStore dataStore) {
Calendar cal = Calendar.getInstance();
cal.set(2012, 12, 1);
final TimePoint startDate = new MillisecondsTimePoint(cal.getTimeInMillis());
cal.set(2012, 12, 5);
final TimePoint endDate = new MillisecondsTimePoint(cal.getTimeInMillis());
dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Cardiff)", startDate, endDate, "Cardiff", true, UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet()));
dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Nice)", startDate, endDate, "Nice", true, UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet()));
dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Rio)", startDate, endDate, "Rio", true, UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet()));
EventBase newEvent = new StrippedEventImpl("Extreme Sailing Series 2013 (Muscat)", startDate, endDate, "Muscat", true, UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet());
newEvent.getVenue().addCourseArea(new CourseAreaImpl("Offshore", UUID.randomUUID()));
newEvent.getVenue().addCourseArea(new CourseAreaImpl("Stadium", UUID.randomUUID()));
dataStore.addEvent(newEvent);
SeriesWithRows qualifying = new SeriesWithRowsImpl("Qualifying", false, null);
SeriesWithRows medal = new SeriesWithRowsImpl("Medal", true, null);
RaceGroup raceGroup = new RaceGroupImpl("ESS", /* displayName */ null, new BoatClassImpl("X40", false), null, Arrays.asList(qualifying,
medal), new EmptyRegattaConfiguration());
List<Competitor> competitors = new ArrayList<Competitor>();
competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.BLUE, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", Color.LIGHT_GRAY, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", Color.GREEN, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", Color.BLACK, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null));
RaceLog log = new RaceLogImpl(UUID.randomUUID());
final AbstractLogEventAuthor author = AppPreferences.on(context).getAuthor();
ConfigurationLoader<RegattaConfiguration> configuration = PreferencesRegattaConfigurationLoader
.loadFromPreferences(preferences);
log.add(new RaceLogStartTimeEventImpl(new MillisecondsTimePoint(new Date().getTime() - 2000), author, 1,
new MillisecondsTimePoint(new Date().getTime() - 1000)));
log.add(new RaceLogRaceStatusEventImpl(new MillisecondsTimePoint(new Date().getTime()),
AppPreferences.on(context).getAuthor(), 1, RaceLogRaceStatus.FINISHING));
ManagedRace q1 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("A.B", new FleetImpl("A"), qualifying, raceGroup),
RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration));
log = new RaceLogImpl(UUID.randomUUID());
/*
* log.add(factory.createStartTimeEvent( new MillisecondsTimePoint(new Date()), 1, RaceLogRaceStatus.SCHEDULED,
* new MillisecondsTimePoint(new Date().getTime() + 100000)));
*/
ManagedRace q2 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("B", new FleetImpl("A.A"), qualifying, raceGroup),
RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration));
log = new RaceLogImpl(UUID.randomUUID());
/*
* log.add(factory.createRaceStatusEvent( new MillisecondsTimePoint(new Date()), 5,
* RaceLogRaceStatus.FINISHED));
*/
ManagedRace q3 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("Q3", new FleetImpl("Default"), qualifying, raceGroup),
RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration));
/*
* ManagedRace m1 = new ManagedRaceImpl( new ManagedRaceIdentifierImpl( "M1", new FleetImpl("Default"), medal,
* raceGroup), null);
*/
dataStore.addRace(q1);
dataStore.addRace(q2);
dataStore.addRace(q3);
// dataStore.addRace(m1);
Mark m1 = new MarkImpl("Red");
Mark m2 = new MarkImpl("Green");
Mark m3 = new MarkImpl("White");
dataStore.addMark(m1);
dataStore.addMark(m2);
dataStore.addMark(m3);
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<EventBase>>> createEventsLoader(
LoadClient<Collection<EventBase>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<EventBase>>(context, callback,
new Callable<Collection<EventBase>>() {
@Override
public Collection<EventBase> call() throws Exception {
return dataStore.getEvents();
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<CourseArea>>> createCourseAreasLoader(
final Serializable parentEventId, LoadClient<Collection<CourseArea>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<CourseArea>>(context, callback,
new Callable<Collection<CourseArea>>() {
@Override
public Collection<CourseArea> call() throws Exception {
return dataStore.getCourseAreas(dataStore.getEvent(parentEventId));
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<CourseArea>>> createCourseAreasLoader(
final EventBase parentEvent, LoadClient<Collection<CourseArea>> callback) {
// TODO Auto-generated method stub
return new ImmediateDataLoaderCallbacks<Collection<CourseArea>>(context, callback,
new Callable<Collection<CourseArea>>() {
@Override
public Collection<CourseArea> call() throws Exception {
return dataStore.getCourseAreas(parentEvent);
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<ManagedRace>>> createRacesLoader(Serializable courseAreaId,
LoadClient<Collection<ManagedRace>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<ManagedRace>>(context, callback,
new Callable<Collection<ManagedRace>>() {
@Override
public Collection<ManagedRace> call() throws Exception {
return dataStore.getRaces();
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<Mark>>> createMarksLoader(ManagedRace managedRace,
LoadClient<Collection<Mark>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<Mark>>(context, callback, new Callable<Collection<Mark>>() {
@Override
public Collection<Mark> call() throws Exception {
return dataStore.getMarks();
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<CourseBase>> createCourseLoader(final ManagedRace managedRace,
LoadClient<CourseBase> callback) {
return new ImmediateDataLoaderCallbacks<CourseBase>(context, callback, new Callable<CourseBase>() {
@Override
public CourseBase call() throws Exception {
return managedRace.getCourseOnServer();
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<Competitor>>> createCompetitorsLoader(
final ManagedRace managedRace, LoadClient<Collection<Competitor>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<Competitor>>(context, callback,
new Callable<Collection<Competitor>>() {
@Override
public Collection<Competitor> call() throws Exception {
return managedRace.getCompetitors();
}
});
}
@Override
public LoaderCallbacks<DataLoaderResult<DeviceConfiguration>> createConfigurationLoader(
DeviceConfigurationIdentifier identifier, LoadClient<DeviceConfiguration> callback) {
return new ImmediateDataLoaderCallbacks<DeviceConfiguration>(context, callback,
new Callable<DeviceConfiguration>() {
@Override
public DeviceConfiguration call() throws Exception {
throw new IllegalStateException("No remote configuration in offline mode.");
}
});
}
@Override
public String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts, boolean showStreamlets, boolean showSimulation,
boolean showMapControls) {
throw new IllegalStateException("No wind map in offline mode.");
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<CoursePosition>>> createPositionLoader(
PositionListFragment positionListFragment) {
// TODO Auto-generated method stub
return null;
}
}