mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-15 06:49:56 +00:00
Merge branch 'master' into translation
Conflicts: java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties Change-Id: I3ff3966a8ebb007d14f37ea96fc6cdcc46a17dd5
This commit is contained in:
commit
38d65f22ba
151 files changed
+7700
-7129
No files matched your search
+1
-1
@@ -6,7 +6,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.1.0-alpha5'
|
||||
classpath 'com.android.tools.build:gradle:2.1.0-beta1'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ SAP is at the center of today’s technology revolution, developing innovations
|
||||
* [[Amazon EC2|wiki/amazon-ec2]]
|
||||
* [[SSL / HTTPS Support|wiki/ssl-support]]
|
||||
* [[EC2 Backup Strategy|wiki/amazon-ec2-backup-strategy]]
|
||||
* [[EC2 mail relaying|wiki/mail-relaying]]
|
||||
* [[TracTrac|wiki/tractrac-lifecycle]]
|
||||
* [[Analytics on a stick|wiki/analytics-on-a-stick]]
|
||||
* [[Operating Igtimi WindBots/windbot-operations]]
|
||||
|
||||
@@ -45,6 +45,14 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
||||
if (coreLocationManager.respondsToSelector("requestAlwaysAuthorization")) {
|
||||
coreLocationManager.requestAlwaysAuthorization()
|
||||
}
|
||||
|
||||
// Now try everything to allow the app to use the GPS sensor
|
||||
// while in background
|
||||
coreLocationManager.pausesLocationUpdatesAutomatically = false;
|
||||
if #available(iOS 9, *) {
|
||||
coreLocationManager.allowsBackgroundLocationUpdates = true;
|
||||
}
|
||||
|
||||
coreLocationManager.startUpdatingLocation()
|
||||
coreLocationManager.startUpdatingHeading()
|
||||
coreLocationManager.delegate = self
|
||||
@@ -102,4 +110,4 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -17,7 +17,9 @@ public interface CompetitorDTO extends Serializable, MappableToDevice {
|
||||
String getIdAsString();
|
||||
|
||||
String getSailID();
|
||||
|
||||
|
||||
String getSearchTag();
|
||||
|
||||
BoatDTO getBoat();
|
||||
|
||||
BoatClassDTO getBoatClass();
|
||||
|
||||
+219
-207
@@ -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;
|
||||
}
|
||||
}
|
||||
+148
-142
@@ -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);
|
||||
}
|
||||
}
|
||||
+23
-21
@@ -1,21 +1,23 @@
|
||||
package com.sap.sailing.domain.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState;
|
||||
|
||||
public class RaceLogTrackingInfoDTO implements Serializable {
|
||||
private static final long serialVersionUID = -6861382173074620168L;
|
||||
public boolean raceLogTrackerExists;
|
||||
public boolean competitorRegistrationsExists;
|
||||
public RaceLogTrackingState raceLogTrackingState;
|
||||
|
||||
protected RaceLogTrackingInfoDTO() {}
|
||||
|
||||
public RaceLogTrackingInfoDTO(boolean raceLogTrackerExists, boolean competitorRegistrationsExists,
|
||||
RaceLogTrackingState raceLogTrackingState) {
|
||||
this.raceLogTrackerExists = raceLogTrackerExists;
|
||||
this.competitorRegistrationsExists = competitorRegistrationsExists;
|
||||
this.raceLogTrackingState = raceLogTrackingState;
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.domain.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState;
|
||||
|
||||
public class RaceLogTrackingInfoDTO implements Serializable {
|
||||
private static final long serialVersionUID = -6861382173074620168L;
|
||||
public boolean raceLogTrackerExists;
|
||||
public boolean competitorRegistrationsExists;
|
||||
public boolean courseExists;
|
||||
public RaceLogTrackingState raceLogTrackingState;
|
||||
|
||||
protected RaceLogTrackingInfoDTO() {}
|
||||
|
||||
public RaceLogTrackingInfoDTO(boolean raceLogTrackerExists, boolean competitorRegistrationsExists, boolean courseExists,
|
||||
RaceLogTrackingState raceLogTrackingState) {
|
||||
this.raceLogTrackerExists = raceLogTrackerExists;
|
||||
this.competitorRegistrationsExists = competitorRegistrationsExists;
|
||||
this.courseExists = courseExists;
|
||||
this.raceLogTrackingState = raceLogTrackingState;
|
||||
}
|
||||
}
|
||||
+1
@@ -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
@@ -37,7 +37,6 @@ public class GPSFixImpl extends AbstractGPSFixImpl implements GPSFix {
|
||||
public String toString() {
|
||||
return getTimePoint()+": "+getPosition();
|
||||
}
|
||||
|
||||
|
||||
public static GPSFixImpl create(double lonDeg, double latDeg, long timeMillis) {
|
||||
return new GPSFixImpl(new DegreePosition(latDeg, lonDeg), new MillisecondsTimePoint(timeMillis));
|
||||
|
||||
+4
@@ -28,7 +28,9 @@ import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.Account;
|
||||
import com.sap.sailing.domain.igtimiadapter.BulkFixReceiver;
|
||||
@@ -47,6 +49,8 @@ import com.sap.sse.mongodb.MongoDBService;
|
||||
public class WebSocketTest {
|
||||
private static final Logger logger = Logger.getLogger(WebSocketTest.class.getName());
|
||||
|
||||
@Rule public Timeout AbstractTracTracLiveTestTimeout = new Timeout(1 * 60 * 1000);
|
||||
|
||||
@WebSocket
|
||||
public class SimpleEchoTestSocket {
|
||||
private final CountDownLatch closeLatch;
|
||||
|
||||
+7
@@ -1002,6 +1002,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
}
|
||||
|
||||
public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogUseCompetitorsFromRaceLogEvent event) {
|
||||
BasicDBObject result = new BasicDBObject();
|
||||
storeRaceLogIdentifier(raceLogIdentifier, result);
|
||||
result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogUseCompetitorsFromRaceLogEvent(event));
|
||||
return result;
|
||||
}
|
||||
|
||||
public DBObject storeRaceLogUseCompetitorsFromRaceLogEvent(RaceLogUseCompetitorsFromRaceLogEvent event) {
|
||||
DBObject result = new BasicDBObject();
|
||||
storeRaceLogEventProperties(event, result);
|
||||
result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogUseCompetitorsFromRaceLogEvent.class.getSimpleName());
|
||||
|
||||
+94
-94
@@ -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();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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)));
|
||||
|
||||
+150
-150
@@ -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));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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));
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
trackingInvitationFor=Einladung zum Tracken für
|
||||
scanQRCodeOrVisitUrlToRegisterAs=Installiere die SAP Sailing Boat Tracker App. Dann scanne den QRCode oder klicke den Link mit deinem Smartphone an, um dich zu registrieren als
|
||||
scanQRCodeOrVisitUrlToRegisterAs=Installiere die {0} App. Dann scanne den QRCode oder klicke den Link mit deinem Smartphone an, um dich zu registrieren als
|
||||
welcomeTo=Willkommen zu
|
||||
iOSUsers=iOS App starten
|
||||
androidUsers=Android App starten
|
||||
@@ -7,4 +7,6 @@ alternativelyVisitThisLink=Wenn die App bereits installiert ist, und du diese Ma
|
||||
buoyTender=Bojenleger
|
||||
appStoreInstallText=Falls die App noch nicht installiert ist, kannst du sie hier finden:Ÿ
|
||||
appIos=iOS App installieren
|
||||
appAndroid=Android App installieren
|
||||
appAndroid=Android App installieren
|
||||
buoyPingerAppName=SAP Sailing Buoy Pinger
|
||||
sailInSightAppName=SAP Sail InSight
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
trackingInvitationFor=Tracking Invitation for
|
||||
scanQRCodeOrVisitUrlToRegisterAs=Make sure you have the SAP Sailing Boat Tracker App installed. Then scan the following QRCode or click the link using your smartphone to register as
|
||||
scanQRCodeOrVisitUrlToRegisterAs=Make sure you have the {0} App installed. Then scan the following QRCode or click the link using your smartphone to register as
|
||||
welcomeTo=Welcome to
|
||||
iOSUsers=Start iOS App
|
||||
androidUsers=Start Android App
|
||||
@@ -7,4 +7,6 @@ alternativelyVisitThisLink=If you are reading this mail on the device with the A
|
||||
buoyTender=buoy tender
|
||||
appStoreInstallText=If don't have the App yet, please install:
|
||||
appIos=Install iOS App
|
||||
appAndroid=Install Android App
|
||||
appAndroid=Install Android App
|
||||
buoyPingerAppName=SAP Sailing Buoy Pinger
|
||||
sailInSightAppName=SAP Sail InSight
|
||||
+16
-1
@@ -532,7 +532,22 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
|
||||
for (DeviceMapping<Mark> mapping : markMappingsByDevices.get(device)) {
|
||||
Mark mark = mapping.getMappedTo();
|
||||
if (mapping.getTimeRange().includes(timePoint)) {
|
||||
trackedRace.recordFix(mark, fix);
|
||||
final DynamicGPSFixTrack<Mark, GPSFix> markTrack = trackedRace.getOrCreateTrack(mark);
|
||||
final GPSFix firstFixAtOrAfter;
|
||||
boolean forceFix;
|
||||
markTrack.lockForRead();
|
||||
try {
|
||||
forceFix = Util.isEmpty(markTrack.getRawFixes()) ||
|
||||
(firstFixAtOrAfter=markTrack.getFirstFixAtOrAfter(timePoint)) != null &&
|
||||
firstFixAtOrAfter.getTimePoint().equals(timePoint);
|
||||
} finally {
|
||||
markTrack.unlockAfterRead();
|
||||
}
|
||||
if (forceFix) {
|
||||
trackedRace.recordFix(mark, fix, /* only when in tracking interval */ false); // force fix into track
|
||||
} else {
|
||||
trackedRace.recordFix(mark, fix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-6
@@ -298,8 +298,9 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
logoUrl = imagesWithTag.get(0).getURL().toString();
|
||||
}
|
||||
try {
|
||||
sendInvitationEmail(locale, toAddress, leaderboardName, competitorName, url, iOSAppUrl,
|
||||
androidAppUrl, logoUrl);
|
||||
final ResourceBundleStringMessages B = RaceLogTrackingI18n.STRING_MESSAGES;
|
||||
sendInvitationEmail(locale, toAddress, leaderboardName, competitorName, url, B.get(locale, "sailInSightAppName"),
|
||||
iOSAppUrl, androidAppUrl, logoUrl);
|
||||
} catch (MailException e) {
|
||||
occuredExceptions.append(e.getMessage() + "\r\n");
|
||||
}
|
||||
@@ -311,7 +312,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
}
|
||||
|
||||
private void sendInvitationEmail(Locale locale, final String toAddress, String leaderboardName, String invitee,
|
||||
String url, String iOSAppUrl, String androidAppUrl, String logoUrl) throws MailException {
|
||||
String url, String appName, String iOSAppUrl, String androidAppUrl, String logoUrl) throws MailException {
|
||||
final ResourceBundleStringMessages B = RaceLogTrackingI18n.STRING_MESSAGES;
|
||||
String subject = String.format("%s %s", B.get(locale, "trackingInvitationFor"), invitee);
|
||||
|
||||
@@ -338,7 +339,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
htmlText.append("<p><img src=\"").append(logoUrl).append("\" /></p> ");
|
||||
}
|
||||
htmlText.append("<h1>").append(B.get(locale, "welcomeTo")).append(" ").append(leaderboardName).append("</h1> ");
|
||||
htmlText.append("<p>").append(B.get(locale, "scanQRCodeOrVisitUrlToRegisterAs")).append(" <b>").append(invitee)
|
||||
htmlText.append("<p>").append(B.get(locale, "scanQRCodeOrVisitUrlToRegisterAs", appName)).append(" <b>").append(invitee)
|
||||
.append("</b></p> ");
|
||||
htmlText.append("<p class=\"qr\"><img src=\"cid:image\" title=\"").append(url).append("\" /></p> ");
|
||||
htmlText.append("<p class=\"spacer\">").append(B.get(locale, "alternativelyVisitThisLink")).append("</p> ");
|
||||
@@ -407,9 +408,10 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
eventId, NonGwtUrlHelper.INSTANCE);
|
||||
for (String toAddress : emailArray) {
|
||||
try {
|
||||
final ResourceBundleStringMessages B = RaceLogTrackingI18n.STRING_MESSAGES;
|
||||
sendInvitationEmail(locale, toAddress, leaderboardName,
|
||||
RaceLogTrackingI18n.STRING_MESSAGES.get(locale, "buoyTender"), url, iOSAppUrl, androidAppUrl,
|
||||
logoUrl);
|
||||
RaceLogTrackingI18n.STRING_MESSAGES.get(locale, "buoyTender"), url, B.get(locale, "buoyPingerAppName"), iOSAppUrl,
|
||||
androidAppUrl, logoUrl);
|
||||
} catch (MailException e) {
|
||||
occuredExceptions.append(e.getMessage() + "\r\n");
|
||||
}
|
||||
|
||||
+2
-2
@@ -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() {
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
+22
-20
@@ -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);
|
||||
}
|
||||
+33
-33
@@ -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);
|
||||
}
|
||||
+80
-80
@@ -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);
|
||||
}
|
||||
+22
-2
@@ -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();
|
||||
}
|
||||
|
||||
+26
-24
@@ -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);
|
||||
}
|
||||
+379
-379
@@ -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;
|
||||
}
|
||||
}
|
||||
+277
-276
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+372
-372
@@ -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());
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
+4
@@ -179,4 +179,8 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest {
|
||||
public static String getTracTracPassword() {
|
||||
return "tracTest";
|
||||
}
|
||||
|
||||
protected void addReceiverToStopDuringTearDown(Receiver receiver) {
|
||||
receivers.add(receiver);
|
||||
}
|
||||
}
|
||||
+320
-299
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,9 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest {
|
||||
}
|
||||
});
|
||||
addListenersForStoredDataAndStartController(receivers);
|
||||
for (final Receiver receiver : receivers) {
|
||||
addReceiverToStopDuringTearDown(receiver);
|
||||
}
|
||||
// now we expect that there is no
|
||||
assertNull(domainFactory.getExistingRaceDefinitionForRace(tractracRace.getId()));
|
||||
race = domainFactory.getAndWaitForRaceDefinition(tractracRace.getId());
|
||||
|
||||
+182
-182
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+7
-6
@@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.same;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -36,7 +37,7 @@ public class MarkPositionTimeFilterTest {
|
||||
m = new MarkImpl("Test Mark");
|
||||
track = new DynamicGPSFixTrackImpl<Mark>(m, /* millisecondsOverWhichToAverage */ 5000);
|
||||
when(trackedRace.getOrCreateTrack(m)).thenReturn(track);
|
||||
doCallRealMethod().when(trackedRace).recordFix(same(m), (GPSFixMoving) anyObject());
|
||||
doCallRealMethod().when(trackedRace).recordFix(same(m), (GPSFixMoving) anyObject(), anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -47,7 +48,7 @@ public class MarkPositionTimeFilterTest {
|
||||
@Test
|
||||
public void testAddFixForMark() {
|
||||
trackedRace.recordFix(m, new GPSFixMovingImpl(new DegreePosition(12, 13), MillisecondsTimePoint.now(),
|
||||
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))));
|
||||
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))), /* onlyWhenInTrackingInterval */ true);
|
||||
track.lockForRead();
|
||||
try {
|
||||
assertEquals(1, track.getRawFixes().size());
|
||||
@@ -64,7 +65,7 @@ public class MarkPositionTimeFilterTest {
|
||||
when(trackedRace.getStartOfTracking()).thenReturn(start);
|
||||
when(trackedRace.getEndOfTracking()).thenReturn(end);
|
||||
trackedRace.recordFix(m, new GPSFixMovingImpl(new DegreePosition(12, 13), fix,
|
||||
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))));
|
||||
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))), /* onlyWhenInTrackingInterval */ true);
|
||||
track.lockForRead();
|
||||
try {
|
||||
assertEquals(1, track.getRawFixes().size());
|
||||
@@ -81,7 +82,7 @@ public class MarkPositionTimeFilterTest {
|
||||
when(trackedRace.getStartOfTracking()).thenReturn(start);
|
||||
when(trackedRace.getEndOfTracking()).thenReturn(end);
|
||||
trackedRace.recordFix(m, new GPSFixMovingImpl(new DegreePosition(12, 13), fix,
|
||||
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))));
|
||||
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))), /* onlyWhenInTrackingInterval */ true);
|
||||
track.lockForRead();
|
||||
try {
|
||||
assertTrue(track.getRawFixes().isEmpty());
|
||||
@@ -98,7 +99,7 @@ public class MarkPositionTimeFilterTest {
|
||||
when(trackedRace.getStartOfTracking()).thenReturn(start);
|
||||
when(trackedRace.getEndOfTracking()).thenReturn(end);
|
||||
trackedRace.recordFix(m, new GPSFixMovingImpl(new DegreePosition(12, 13), fix,
|
||||
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))));
|
||||
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))), /* onlyWhenInTrackingInterval */ true);
|
||||
track.lockForRead();
|
||||
try {
|
||||
assertTrue(track.getRawFixes().isEmpty());
|
||||
@@ -107,7 +108,7 @@ public class MarkPositionTimeFilterTest {
|
||||
}
|
||||
when(trackedRace.getEndOfTracking()).thenReturn(fix.plus(10000));
|
||||
trackedRace.recordFix(m, new GPSFixMovingImpl(new DegreePosition(12, 13), fix,
|
||||
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))));
|
||||
new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))), /* onlyWhenInTrackingInterval */ true);
|
||||
track.lockForRead();
|
||||
try {
|
||||
assertEquals(1, track.getRawFixes().size());
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
@@ -112,6 +112,7 @@ public class ReceiveMarkPassingDataTest extends AbstractTracTracLiveTest {
|
||||
null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false, ReceiverType.RACECOURSE, ReceiverType.MARKPOSITIONS,
|
||||
ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS)) {
|
||||
receivers.add(r);
|
||||
addReceiverToStopDuringTearDown(r);
|
||||
}
|
||||
addListenersForStoredDataAndStartController(receivers);
|
||||
raceDefinition = DomainFactory.INSTANCE.getAndWaitForRaceDefinition(race.getId());
|
||||
|
||||
+1
-1
@@ -54,7 +54,6 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest {
|
||||
|
||||
@Override
|
||||
public void competitorPositionChanged(GPSFixMoving fix, Competitor competitor) {
|
||||
System.out.println("Received fix "+fix);
|
||||
synchronized (semaphor) {
|
||||
if (first) {
|
||||
firstTracked[0] = competitor;
|
||||
@@ -89,6 +88,7 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest {
|
||||
null, /* tracTracUsername */null, /* tracTracPassword */null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false)) {
|
||||
receiver.subscribe();
|
||||
getRaceSubscriber().start();
|
||||
addReceiverToStopDuringTearDown(receiver);
|
||||
}
|
||||
addListenersForStoredDataAndStartController(domainFactory
|
||||
.getUpdateReceivers(trackedRegatta, /* delayToLiveInMillis */0l, null, /* simulator */
|
||||
|
||||
+1
-1
@@ -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())));
|
||||
}
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ public abstract class AbstractMarkPassingTest extends OnlineTracTracBasedTest {
|
||||
Map<Competitor, Map<Waypoint, MarkPassing>> computedPasses = new HashMap<>();
|
||||
// Get calculatedMarkPasses
|
||||
long time = System.currentTimeMillis();
|
||||
new MarkPassingCalculator(getTrackedRace(), false);
|
||||
new MarkPassingCalculator(getTrackedRace(), false, /* waitForInitialMarkPassingCalculation */ true);
|
||||
time = System.currentTimeMillis() - time;
|
||||
|
||||
for (Competitor c : getRace().getCompetitors()) {
|
||||
|
||||
+3
-3
@@ -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");
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ public class StarIDM2013MarkPassingTest extends AbstractMarkPassingTest {
|
||||
}
|
||||
|
||||
private void testWholeRace5() throws InvalidDateException {
|
||||
new MarkPassingCalculator(getTrackedRace(), false); // do our calculation, injecting into TrackedRace
|
||||
new MarkPassingCalculator(getTrackedRace(), false, /* waitForInitialMarkPassingCalculation */ true); // do our calculation, injecting into TrackedRace
|
||||
final Competitor GER7897 = getCompetitorByName("Tusch, Frank,Winkelmann, Sven");
|
||||
assertMarkPassing(GER7897, Util.get(getWaypoints(), 0), DateParser.parse("2013-05-04T14:50:10+0200"));
|
||||
assertMarkPassing(GER7897, Util.get(getWaypoints(), 1), DateParser.parse("2013-05-04T14:57:12+0200"));
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
|
||||
+21
-21
@@ -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();
|
||||
|
||||
}
|
||||
+5
@@ -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);
|
||||
|
||||
+2
-1
@@ -1,9 +1,10 @@
|
||||
package com.sap.sailing.domain.markpassingcalculation;
|
||||
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sailing.domain.markpassingcalculation.impl.CandidateChooserImpl;
|
||||
import com.sap.sailing.domain.markpassingcalculation.impl.CandidateImpl;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
/**
|
||||
* Represent the possible {@link MarkPassing} of a {@link Waypoint}. It contains the {@link Waypoint} it might be passing, a
|
||||
|
||||
-6
@@ -15,9 +15,6 @@ import com.sap.sse.common.Util;
|
||||
* @author Nicolas Klose
|
||||
*/
|
||||
public interface CandidateFinder {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param fixes
|
||||
* Either new fixes or fixes that may have changed their status, e.g. as a result of new mark
|
||||
@@ -26,8 +23,6 @@ public interface CandidateFinder {
|
||||
*/
|
||||
Util.Pair<Iterable<Candidate>, Iterable<Candidate>> getCandidateDeltas(Competitor c, Iterable<GPSFix> fixes);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* When initializing or refreshing the calculator, the whole race until now is evaluated. For that purpose all of the
|
||||
* {@link Candidate}s are needed instead of just the deltas.
|
||||
@@ -41,5 +36,4 @@ public interface CandidateFinder {
|
||||
* mark fixes..
|
||||
*/
|
||||
Map<Competitor, List<GPSFix>> calculateFixesAffectedByNewMarkFixes(Map<Mark, List<GPSFix>> newMarkFixes);
|
||||
|
||||
}
|
||||
+17
-10
@@ -34,7 +34,7 @@ import com.sap.sse.util.impl.ThreadFactoryWithPriority;
|
||||
* Calculates the {@link MarkPassing}s for a {@link DynamicTrackedRace} using an {@link CandidateFinder} and an
|
||||
* {@link CandidateChooser}. The finder evaluates the fixes and finds possible MarkPassings as {@link Candidate}s . The
|
||||
* chooser than finds the most likely sequence of {@link Candidate}s and updates the race with new {@link MarkPassing}s
|
||||
* for this sequence. Upon calling the constructor {@link #MarkPassingCalculator(DynamicTrackedRace, boolean)} this
|
||||
* for this sequence. Upon calling the constructor {@link #MarkPassingCalculator(DynamicTrackedRace, boolean, boolean)} this
|
||||
* happens for the current state of the race. In addition, for live races, the <code>listen</code> parameter of the
|
||||
* constructor should be true. Then a {@link MarkPassingUpdateListener} is initialized which puts new fixes into a queue
|
||||
* as {@link StorePositionUpdateStrategy}. A new thread will also be started to evaluate the new fixes (See
|
||||
@@ -58,7 +58,7 @@ public class MarkPassingCalculator {
|
||||
|
||||
private boolean suspended = false;
|
||||
|
||||
public MarkPassingCalculator(DynamicTrackedRace race, boolean listen) {
|
||||
public MarkPassingCalculator(DynamicTrackedRace race, boolean listen, boolean waitForInitialMarkPassingCalculation) {
|
||||
if (listen) {
|
||||
listener = new MarkPassingUpdateListener(race);
|
||||
} else {
|
||||
@@ -67,14 +67,21 @@ public class MarkPassingCalculator {
|
||||
this.race = race;
|
||||
finder = new CandidateFinderImpl(race);
|
||||
chooser = new CandidateChooserImpl(race);
|
||||
for (Competitor c : race.getRace().getCompetitors()) {
|
||||
Util.Pair<Iterable<Candidate>, Iterable<Candidate>> allCandidates = finder.getAllCandidates(c);
|
||||
chooser.calculateMarkPassDeltas(c, allCandidates.getA(), allCandidates.getB());
|
||||
}
|
||||
if (listen) {
|
||||
final Thread listenerThread = new Thread(new Listen(race.getRace().getName()), "MarkPassingCalculator for race " + race.getRace().getName());
|
||||
listenerThread.setDaemon(true);
|
||||
listenerThread.start();
|
||||
Thread t = new Thread(() -> {
|
||||
for (Competitor c : race.getRace().getCompetitors()) {
|
||||
Util.Pair<Iterable<Candidate>, Iterable<Candidate>> allCandidates = finder.getAllCandidates(c);
|
||||
chooser.calculateMarkPassDeltas(c, allCandidates.getA(), allCandidates.getB());
|
||||
}
|
||||
if (listen) {
|
||||
final Thread listenerThread = new Thread(new Listen(race.getRace().getName()), "MarkPassingCalculator for race " + race.getRace().getName());
|
||||
listenerThread.setDaemon(true);
|
||||
listenerThread.start();
|
||||
}
|
||||
}, "MarkPassingCalculator for race "+race.getRace().getName()+" initialization");
|
||||
if (waitForInitialMarkPassingCalculation) {
|
||||
t.run();
|
||||
} else {
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -30,6 +30,8 @@ import com.sap.sse.common.Util.Triple;
|
||||
public class MarkPassingUpdateListener extends AbstractRaceChangeListener {
|
||||
private static final Logger logger = Logger.getLogger(MarkPassingUpdateListener.class.getName());
|
||||
private LinkedBlockingQueue<StorePositionUpdateStrategy> queue;
|
||||
private final String raceName;
|
||||
|
||||
private final StorePositionUpdateStrategy endMarker = new StorePositionUpdateStrategy() {
|
||||
@Override
|
||||
public void storePositionUpdate(Map<Competitor, List<GPSFix>> competitorFixes,
|
||||
@@ -44,6 +46,7 @@ public class MarkPassingUpdateListener extends AbstractRaceChangeListener {
|
||||
* Adds itself automatically as a Listener on the <code>race</code> and its course.
|
||||
*/
|
||||
public MarkPassingUpdateListener(DynamicTrackedRace race) {
|
||||
raceName = race.getRace().getName();
|
||||
queue = new LinkedBlockingQueue<>();
|
||||
race.addListener(this);
|
||||
race.getRace().getCourse().addCourseListener(this);
|
||||
@@ -98,7 +101,7 @@ public class MarkPassingUpdateListener extends AbstractRaceChangeListener {
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
logger.info("Stopping " + this);
|
||||
logger.info("Stopping " + this + " for race " + raceName);
|
||||
queue.add(endMarker);
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -31,6 +31,7 @@ import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.impl.MillisecondsDurationImpl;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
@@ -106,7 +107,7 @@ public class CandidateChooserImpl implements CandidateChooser {
|
||||
private final CandidateWithSettableTime start;
|
||||
private final CandidateWithSettableWaypointIndex end;
|
||||
private final DynamicTrackedRace race;
|
||||
|
||||
|
||||
public CandidateChooserImpl(DynamicTrackedRace race) {
|
||||
this.race = race;
|
||||
waypointPositionAndDistanceCache = new WaypointPositionAndDistanceCache(race, Duration.ONE_MINUTE);
|
||||
@@ -395,8 +396,9 @@ public class CandidateChooserImpl implements CandidateChooser {
|
||||
}
|
||||
}
|
||||
}
|
||||
Candidate marker = candidateWithParentAndHighestTotalProbability.get(endOfFixedInterval).getA();
|
||||
while (marker.getOneBasedIndexOfWaypoint() > 0) {
|
||||
final Pair<Candidate, Double> bestCandidateAndProbabilityForEndOfFixedInterval = candidateWithParentAndHighestTotalProbability.get(endOfFixedInterval);
|
||||
Candidate marker = bestCandidateAndProbabilityForEndOfFixedInterval == null ? null : bestCandidateAndProbabilityForEndOfFixedInterval.getA();
|
||||
while (marker != null && marker.getOneBasedIndexOfWaypoint() > 0) {
|
||||
mostLikelyCandidates.add(marker);
|
||||
marker = candidateWithParentAndHighestTotalProbability.get(marker).getA();
|
||||
}
|
||||
|
||||
+22
-14
@@ -49,7 +49,6 @@ import com.sap.sse.common.Util.Pair;
|
||||
*
|
||||
*/
|
||||
public class CandidateFinderImpl implements CandidateFinder {
|
||||
|
||||
// The higher this is, the closer the fixes have to be to waypoint to become a Candidate
|
||||
private final int STRICTNESS_OF_DISTANCE_BASED_PROBABILITY = 7;
|
||||
|
||||
@@ -775,18 +774,21 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
final DynamicGPSFixTrack<Competitor, GPSFixMoving> track = race.getTrack(otherCompetitor);
|
||||
if (track != null) {
|
||||
final Position estimatedPositionAtT = track.getEstimatedPosition(t, /* extrapolate */ true);
|
||||
final Distance otherCompetitorsDistanceToStartAtT = getMinDistanceOrNull(calculateDistance(estimatedPositionAtT, start, t));
|
||||
if (otherCompetitorsDistanceToStartAtT != null) {
|
||||
final Distance crossTrackError;
|
||||
if (startIsLine) {
|
||||
Pair<Position, Bearing> crossingInformationForStartLine = crossingInformationForStart.iterator().next();
|
||||
crossTrackError = estimatedPositionAtT.crossTrackError(crossingInformationForStartLine.getA(),
|
||||
crossingInformationForStartLine.getB());
|
||||
} else {
|
||||
crossTrackError = null;
|
||||
// consider that a position may not be available for that other competitor, although a track exists
|
||||
if (estimatedPositionAtT != null) {
|
||||
final Distance otherCompetitorsDistanceToStartAtT = getMinDistanceOrNull(calculateDistance(estimatedPositionAtT, start, t));
|
||||
if (otherCompetitorsDistanceToStartAtT != null) {
|
||||
final Distance crossTrackError;
|
||||
if (startIsLine) {
|
||||
Pair<Position, Bearing> crossingInformationForStartLine = crossingInformationForStart.iterator().next();
|
||||
crossTrackError = estimatedPositionAtT.crossTrackError(crossingInformationForStartLine.getA(),
|
||||
crossingInformationForStartLine.getB());
|
||||
} else {
|
||||
crossTrackError = null;
|
||||
}
|
||||
distancesToStartLineOfOtherCompetitors.add(new
|
||||
AbsoluteGeometricDistanceAndSignedProjectedDistanceToStartLine(otherCompetitorsDistanceToStartAtT, crossTrackError));
|
||||
}
|
||||
distancesToStartLineOfOtherCompetitors.add(new
|
||||
AbsoluteGeometricDistanceAndSignedProjectedDistanceToStartLine(otherCompetitorsDistanceToStartAtT, crossTrackError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -960,7 +962,11 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
result = 1;
|
||||
} else {
|
||||
//TODO There should be a constant (either the 1.5 or the -0.2) which controls how strict the the curve is.
|
||||
result = (1-PENALTY_FOR_WRONG_SIDE) * Math.pow(1.5, -0.2 * onWrongSide.getMeters()) + PENALTY_FOR_WRONG_SIDE;
|
||||
result = Math.min(1.0, (1-PENALTY_FOR_WRONG_SIDE) *
|
||||
// consider the possibility that both, mark and boat could have been GPSFix.TYPICAL_HDOP off and
|
||||
// only start penalizing beyond this distance
|
||||
Math.pow(1.5, -0.2 * onWrongSide.add(GPSFix.TYPICAL_HDOP.scale(-2.0)).getMeters())
|
||||
+ PENALTY_FOR_WRONG_SIDE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1003,7 +1009,9 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
Distance legLength = getAverageLengthOfAdjacentLegs(t, w);
|
||||
if (legLength != null) {
|
||||
result = 1 / (STRICTNESS_OF_DISTANCE_BASED_PROBABILITY/* Raising this will make it stricter */
|
||||
* Math.abs(distance.getMeters() / legLength.getMeters()) + 1);
|
||||
// reduce distance by 2x the typical HDOP, accounting for the possibility that some distance from the mark
|
||||
// may have been caused by inaccurate GPS tracking
|
||||
* Math.abs(Math.max(0.0, distance.add(GPSFix.TYPICAL_HDOP.scale(-2)).getMeters()) / legLength.getMeters()) + 1);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+5
@@ -100,6 +100,11 @@ public class DummyMarkPassingWithTimePointOnly implements MarkPassing {
|
||||
public Duration getTimeOnDistanceAllowancePerNauticalMile() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSearchTag() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+13
-4
@@ -104,9 +104,6 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
|
||||
this.startTimeChangedListeners = new HashSet<>();
|
||||
this.raceAbortedListeners = new HashSet<>();
|
||||
this.raceIsKnownToStartUpwind = race.getBoatClass().typicallyStartsUpwind();
|
||||
if (markPassingCalculator != null) {
|
||||
logListener.setMarkPassingUpdateListener(markPassingCalculator.getListener());
|
||||
}
|
||||
if (!raceIsKnownToStartUpwind) {
|
||||
Set<WindSource> windSourcesToExclude = new HashSet<WindSource>();
|
||||
for (WindSource windSourceToExclude : getWindSourcesToExclude()) {
|
||||
@@ -135,6 +132,14 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
|
||||
startTimeChangedListeners = new HashSet<>();
|
||||
raceAbortedListeners = new HashSet<>();
|
||||
}
|
||||
|
||||
protected Object readResolve() {
|
||||
super.readResolve();
|
||||
if (markPassingCalculator != null) {
|
||||
logListener.setMarkPassingUpdateListener(markPassingCalculator.getListener());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #raceIsKnownToStartUpwind} (see also {@link #raceIsKnownToStartUpwind()}) is initialized based on the <code>race</code>'s
|
||||
@@ -1011,7 +1016,11 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
|
||||
|
||||
@Override
|
||||
protected MarkPassingCalculator createMarkPassingCalculator() {
|
||||
return new MarkPassingCalculator(this, true);
|
||||
// not waiting for initial mark passing creation is essential for not holding up, e.g.,
|
||||
// an initial load during replication where it is perfectly fine to obtain the results from
|
||||
// mark passing analysis as they become available; for test cases, however, "true" would
|
||||
// be a more appropriate choice
|
||||
return new MarkPassingCalculator(this, true, /* waitForInitialMarkPassingCalculation */ false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+18
-3
@@ -281,7 +281,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
|
||||
private transient ConcurrentHashMap<TimePoint, Future<Wind>> directionFromStartToNextMarkCache;
|
||||
|
||||
protected final MarkPassingCalculator markPassingCalculator;
|
||||
protected transient MarkPassingCalculator markPassingCalculator;
|
||||
private final boolean hasMarkPassingCalculator;
|
||||
|
||||
private final ConcurrentHashMap<Mark, GPSFixTrack<Mark, GPSFix>> markTracks;
|
||||
|
||||
@@ -535,13 +536,16 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
public void raceAdded(TrackedRace trackedRace) {}
|
||||
@Override
|
||||
public void raceRemoved(TrackedRace trackedRace) {
|
||||
// stop mark passing calculator when tracked race is removed:
|
||||
markPassingCalculator.stop();
|
||||
if (trackedRace == TrackedRaceImpl.this) {
|
||||
// stop mark passing calculator when tracked race is removed:
|
||||
markPassingCalculator.stop();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
markPassingCalculator = null;
|
||||
}
|
||||
hasMarkPassingCalculator = useInternalMarkPassingAlgorithm;
|
||||
// now wait until wind loading has at least started; then we know that the serialization lock is safely held by the loader
|
||||
try {
|
||||
waitUntilLoadingFromWindStoreComplete();
|
||||
@@ -643,6 +647,17 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
triggerManeuverCacheRecalculationForAllCompetitors();
|
||||
logger.info("Deserialized race " + getRace().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* After the object graph has entirely been re-constructed, create the mark passing calculator if
|
||||
* the original object had one.
|
||||
*/
|
||||
protected Object readResolve() {
|
||||
if (hasMarkPassingCalculator) {
|
||||
markPassingCalculator = createMarkPassingCalculator();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the {@link TrackedRace} object and the {@link RaceDefinition} and in particular its {@link CourseImpl} objects are not
|
||||
|
||||
@@ -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 "${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work" -war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -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 "${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work" -war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -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>
|
||||
+8
-3
@@ -7,14 +7,14 @@ import com.sap.sse.security.ui.userprofile.shared.userdetails.UserDetailsPresent
|
||||
public class UserProfileDetailsPresenter implements UserProfileDetailsView.Presenter {
|
||||
|
||||
private final UserProfileDetailsView view;
|
||||
private final UserProfileView.Presenter userProfilePresenter;
|
||||
private final UserDetailsPresenter userDetailsPresenter;
|
||||
|
||||
public UserProfileDetailsPresenter(UserProfileDetailsView view, UserProfileView.Presenter userProfilePresenter) {
|
||||
this.view = view;
|
||||
|
||||
this.userProfilePresenter = userProfilePresenter;
|
||||
view.setPresenter(this);
|
||||
|
||||
userDetailsPresenter = new UserDetailsPresenter(view.getUserDetailsView(),
|
||||
this.userDetailsPresenter = new UserDetailsPresenter(view.getUserDetailsView(),
|
||||
userProfilePresenter.getAuthenticationManager(), userProfilePresenter.getUserManagementService(),
|
||||
userProfilePresenter.getMailVerifiedUrl());
|
||||
}
|
||||
@@ -24,4 +24,9 @@ public class UserProfileDetailsPresenter implements UserProfileDetailsView.Prese
|
||||
view.getDecorator().setAuthenticationContext(authenticationContext);
|
||||
userDetailsPresenter.setAuthenticationContext(authenticationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doTriggerLoginForm() {
|
||||
userProfilePresenter.doTriggerLoginForm();
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.home.desktop.places.user.profile.detailstab;
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
|
||||
import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext;
|
||||
import com.sap.sse.security.ui.authentication.decorator.NotLoggedInPresenter;
|
||||
import com.sap.sse.security.ui.userprofile.shared.userdetails.UserDetailsView;
|
||||
|
||||
public interface UserProfileDetailsView extends IsWidget {
|
||||
@@ -13,7 +14,7 @@ public interface UserProfileDetailsView extends IsWidget {
|
||||
|
||||
NeedsAuthenticationContext getDecorator();
|
||||
|
||||
public interface Presenter {
|
||||
public interface Presenter extends NotLoggedInPresenter {
|
||||
void setAuthenticationContext(AuthenticationContext userManagementContext);
|
||||
}
|
||||
}
|
||||
+1
-8
@@ -6,7 +6,6 @@ import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.common.client.SharedResources;
|
||||
import com.sap.sailing.gwt.home.desktop.places.user.profile.UserProfileView;
|
||||
import com.sap.sailing.gwt.home.shared.usermanagement.decorator.AuthorizedContentDecoratorDesktop;
|
||||
import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext;
|
||||
import com.sap.sse.security.ui.userprofile.desktop.userdetails.UserAccountDetails;
|
||||
@@ -28,19 +27,13 @@ public class UserProfileDetailsViewImpl extends Composite implements UserProfile
|
||||
@UiField(provided = true)
|
||||
UserAccountDetails accountDetailsUi;
|
||||
|
||||
private UserProfileView.Presenter currentPresenter;
|
||||
|
||||
|
||||
public UserProfileDetailsViewImpl() {
|
||||
}
|
||||
|
||||
public UserDetailsView getUserDetailsView() {
|
||||
return accountDetailsUi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPresenter(Presenter presenter) {
|
||||
decoratorUi = new AuthorizedContentDecoratorDesktop(currentPresenter);
|
||||
decoratorUi = new AuthorizedContentDecoratorDesktop(presenter);
|
||||
accountDetailsUi = new UserAccountDetails(SharedResources.INSTANCE);
|
||||
initWidget(ourUiBinder.createAndBindUi(this));
|
||||
}
|
||||
|
||||
+3
-3
@@ -242,7 +242,7 @@ public abstract class AbstractRegattaWithSeriesAndFleetsDialog<T> extends DataEn
|
||||
protected void fillCourseAreaListBox(EventDTO selectedEvent) {
|
||||
courseAreaListBox.addItem(stringMessages.selectCourseArea());
|
||||
for (CourseAreaDTO courseArea : selectedEvent.venue.getCourseAreas()) {
|
||||
courseAreaListBox.addItem(courseArea.getName());
|
||||
courseAreaListBox.addItem(courseArea.getName(), courseArea.id.toString());
|
||||
if (courseArea.id.equals(regatta.defaultCourseAreaUuid)) {
|
||||
courseAreaListBox.setSelectedIndex(courseAreaListBox.getItemCount() - 1);
|
||||
}
|
||||
@@ -270,9 +270,9 @@ public abstract class AbstractRegattaWithSeriesAndFleetsDialog<T> extends DataEn
|
||||
EventDTO event = getSelectedEvent();
|
||||
int selIndex = courseAreaListBox.getSelectedIndex();
|
||||
if (selIndex > 0 && event != null) { // the zero index represents the 'no selection' text
|
||||
String itemText = courseAreaListBox.getItemText(selIndex);
|
||||
String selectedCourseAreaIdAsString = courseAreaListBox.getValue(selIndex);
|
||||
for (CourseAreaDTO courseAreaDTO : event.venue.getCourseAreas()) {
|
||||
if (courseAreaDTO.getName().equals(itemText)) {
|
||||
if (courseAreaDTO.id.toString().equals(selectedCourseAreaIdAsString)) {
|
||||
result = courseAreaDTO;
|
||||
break;
|
||||
}
|
||||
|
||||
+17
-13
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+16
@@ -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");
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.resources.client.ImageResource;
|
||||
import com.sap.sailing.gwt.ui.shared.CourseAreaDTO;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.gwt.client.StringMessages;
|
||||
import com.sap.sse.gwt.client.controls.listedit.ExpandedListEditorUi;
|
||||
import com.sap.sse.gwt.client.controls.listedit.GenericStringListEditorComposite;
|
||||
import com.sap.sse.gwt.client.controls.listedit.GenericStringListInlineEditorComposite;
|
||||
import com.sap.sse.gwt.client.controls.listedit.ListEditorComposite;
|
||||
import com.sap.sse.gwt.client.controls.listedit.ListEditorUiStrategy;
|
||||
|
||||
public class CourseAreaListInlineEditorComposite extends GenericStringListInlineEditorComposite<CourseAreaDTO> {
|
||||
|
||||
public CourseAreaListInlineEditorComposite(Iterable<CourseAreaDTO> initialValues,
|
||||
ListEditorUiStrategy<CourseAreaDTO> activeUi) {
|
||||
super(initialValues, activeUi);
|
||||
}
|
||||
|
||||
public CourseAreaListInlineEditorComposite(Iterable<CourseAreaDTO> initialValues, StringMessages stringMessages,
|
||||
ImageResource removeImage, List<String> suggestValues, int textBoxSize) {
|
||||
super(initialValues, stringMessages, removeImage, suggestValues, textBoxSize);
|
||||
}
|
||||
|
||||
public static class CollapsedUi extends GenericStringListEditorComposite.CollapsedUi<CourseAreaDTO> {
|
||||
public CollapsedUi(StringMessages stringMessages, String dialogTitle, ExpandedListEditorUi<CourseAreaDTO> expandedUi) {
|
||||
super(stringMessages, dialogTitle, expandedUi);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListEditorComposite<CourseAreaDTO> createExpandedUi(Iterable<CourseAreaDTO> initialValues, ExpandedListEditorUi<CourseAreaDTO> ui) {
|
||||
return new CourseAreaListInlineEditorComposite(initialValues, ui);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CourseAreaDTO parse(String s) {
|
||||
return new CourseAreaDTO(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CourseAreaDTO parse(String s, CourseAreaDTO valueToUpdate) {
|
||||
final CourseAreaDTO result;
|
||||
if (Util.equalsWithNull(valueToUpdate.getName(), s)) {
|
||||
result = valueToUpdate;
|
||||
} else {
|
||||
result = parse(s);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toString(CourseAreaDTO value) {
|
||||
return value.getName();
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -7,6 +7,7 @@ import java.util.List;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.CourseAreaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
|
||||
import com.sap.sse.gwt.client.media.ImageDTO;
|
||||
@@ -45,6 +46,6 @@ public class EventCreateDialog extends EventDialog {
|
||||
imagesListComposite.fillImages(Collections.<ImageDTO>emptyList());
|
||||
videosListComposite.fillVideos(Collections.<VideoDTO>emptyList());
|
||||
// add default course area
|
||||
courseAreaNameList.setValue(Collections.singletonList("Default"));
|
||||
courseAreaNameList.setValue(Collections.singletonList(new CourseAreaDTO("Default")));
|
||||
}
|
||||
}
|
||||
+19
-17
@@ -34,8 +34,8 @@ import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.VenueDTO;
|
||||
import com.sap.sse.gwt.client.IconResources;
|
||||
import com.sap.sse.gwt.client.controls.listedit.GenericStringListInlineEditorComposite;
|
||||
import com.sap.sse.gwt.client.controls.listedit.StringConstantsListEditorComposite;
|
||||
import com.sap.sse.gwt.client.controls.listedit.StringListInlineEditorComposite;
|
||||
import com.sap.sse.gwt.client.media.ImageDTO;
|
||||
import com.sap.sse.gwt.client.media.VideoDTO;
|
||||
|
||||
@@ -50,12 +50,12 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap<EventDTO>
|
||||
protected UUID id;
|
||||
protected TextBox officialWebsiteURLEntryField;
|
||||
protected Map<String, TextBox> sailorsInfoWebsiteURLEntryFields = new HashMap<>();
|
||||
protected StringListInlineEditorComposite courseAreaNameList;
|
||||
protected CourseAreaListInlineEditorComposite courseAreaNameList;
|
||||
protected StringConstantsListEditorComposite leaderboardGroupList;
|
||||
protected Map<String, LeaderboardGroupDTO> availableLeaderboardGroupsByName;
|
||||
protected ImagesListComposite imagesListComposite;
|
||||
protected VideosListComposite videosListComposite;
|
||||
|
||||
protected ImagesListComposite imagesListComposite;
|
||||
protected VideosListComposite videosListComposite;
|
||||
|
||||
protected static class EventParameterValidator implements Validator<EventDTO> {
|
||||
|
||||
private StringMessages stringMessages;
|
||||
@@ -76,8 +76,9 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap<EventDTO>
|
||||
if (courseAreaNotEmpty) {
|
||||
for (CourseAreaDTO courseArea : eventToValidate.venue.getCourseAreas()) {
|
||||
courseAreaNotEmpty = courseArea.getName() != null && courseArea.getName().length() > 0;
|
||||
if (!courseAreaNotEmpty)
|
||||
if (!courseAreaNotEmpty) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,11 +139,17 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap<EventDTO>
|
||||
validate();
|
||||
}
|
||||
};
|
||||
final ValueChangeHandler<Iterable<CourseAreaDTO>> courseAreaValueChangeHandler = new ValueChangeHandler<Iterable<CourseAreaDTO>>() {
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<Iterable<CourseAreaDTO>> event) {
|
||||
validate();
|
||||
}
|
||||
};
|
||||
|
||||
courseAreaNameList = new StringListInlineEditorComposite(Collections.<String> emptyList(),
|
||||
new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */
|
||||
courseAreaNameList = new CourseAreaListInlineEditorComposite(Collections.<CourseAreaDTO> emptyList(),
|
||||
new GenericStringListInlineEditorComposite.ExpandedUi<CourseAreaDTO>(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */
|
||||
SuggestedCourseAreaNames.suggestedCourseAreaNames, stringMessages.enterCourseAreaName(), 50));
|
||||
courseAreaNameList.addValueChangeHandler(valueChangeHandler);
|
||||
courseAreaNameList.addValueChangeHandler(courseAreaValueChangeHandler);
|
||||
List<String> leaderboardGroupNames = new ArrayList<>();
|
||||
for(LeaderboardGroupDTO leaderboardGroupDTO: availableLeaderboardGroups) {
|
||||
leaderboardGroupNames.add(leaderboardGroupDTO.getName());
|
||||
@@ -178,16 +185,11 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap<EventDTO>
|
||||
result.endDate = endDateBox.getValue();
|
||||
result.isPublic = isPublicCheckBox.getValue();
|
||||
result.id = id;
|
||||
List<CourseAreaDTO> courseAreas = new ArrayList<CourseAreaDTO>();
|
||||
for (String courseAreaName : courseAreaNameList.getValue()) {
|
||||
CourseAreaDTO courseAreaDTO = new CourseAreaDTO();
|
||||
courseAreaDTO.setName(courseAreaName);
|
||||
courseAreas.add(courseAreaDTO);
|
||||
}
|
||||
for (ImageDTO image: imagesListComposite.getAllImages()) {
|
||||
List<CourseAreaDTO> courseAreas = courseAreaNameList.getValue();
|
||||
for (ImageDTO image : imagesListComposite.getAllImages()) {
|
||||
result.addImage(image);
|
||||
}
|
||||
for (VideoDTO video: videosListComposite.getAllVideos()) {
|
||||
for (VideoDTO video : videosListComposite.getAllVideos()) {
|
||||
result.addVideo(video);
|
||||
}
|
||||
result.venue = new VenueDTO(venueEntryField.getText(), courseAreas);
|
||||
|
||||
+1
-9
@@ -6,7 +6,6 @@ import java.util.List;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.CourseAreaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
|
||||
|
||||
@@ -29,17 +28,10 @@ public class EventEditDialog extends EventDialog {
|
||||
isPublicCheckBox = createCheckbox("");
|
||||
isPublicCheckBox.setValue(event.isPublic);
|
||||
id = event.id;
|
||||
|
||||
List<String> courseAreaNames = new ArrayList<>();
|
||||
if (event.venue.getCourseAreas() != null && event.venue.getCourseAreas().size() > 0) {
|
||||
for (CourseAreaDTO courseArea : event.venue.getCourseAreas()) {
|
||||
courseAreaNames.add(courseArea.getName());
|
||||
}
|
||||
}
|
||||
officialWebsiteURLEntryField = createTextBox(event.getOfficialWebsiteURL());
|
||||
officialWebsiteURLEntryField.setVisibleLength(50);
|
||||
sailorsInfoWebsiteURLEntryFields = createTextBoxesForLocalesAndDefault(event.getSailorsInfoWebsiteURLs());
|
||||
courseAreaNameList.setValue(courseAreaNames);
|
||||
courseAreaNameList.setValue(new ArrayList<>(event.venue.getCourseAreas()));
|
||||
List<String> leaderboardGroupNames = new ArrayList<>();
|
||||
for(LeaderboardGroupDTO leaderboardGroupDTO: event.getLeaderboardGroups()) {
|
||||
leaderboardGroupNames.add(leaderboardGroupDTO.getName());
|
||||
|
||||
+6
-6
@@ -130,9 +130,9 @@ public abstract class FlexibleLeaderboardDialog extends AbstractLeaderboardDialo
|
||||
}
|
||||
|
||||
private void fillCourseAreaListBox(EventDTO selectedEvent) {
|
||||
courseAreaListBox.addItem("Please select a course area...");
|
||||
courseAreaListBox.addItem(stringMessages.pleaseSelectACourseArea());
|
||||
for (CourseAreaDTO courseArea : selectedEvent.venue.getCourseAreas()) {
|
||||
courseAreaListBox.addItem(courseArea.getName());
|
||||
courseAreaListBox.addItem(courseArea.getName(), courseArea.id.toString());
|
||||
}
|
||||
courseAreaListBox.setEnabled(true);
|
||||
}
|
||||
@@ -156,10 +156,10 @@ public abstract class FlexibleLeaderboardDialog extends AbstractLeaderboardDialo
|
||||
CourseAreaDTO result = null;
|
||||
EventDTO event = getSelectedEvent();
|
||||
int selIndex = courseAreaListBox.getSelectedIndex();
|
||||
if(selIndex > 0 && event != null) { // the zero index represents the 'no selection' text
|
||||
String itemText = courseAreaListBox.getItemText(selIndex);
|
||||
for(CourseAreaDTO courseAreaDTO: event.venue.getCourseAreas()) {
|
||||
if(courseAreaDTO.getName().equals(itemText)) {
|
||||
if (selIndex > 0 && event != null) { // the zero index represents the 'no selection' text
|
||||
String selectedCourseAreaId = courseAreaListBox.getValue(selIndex);
|
||||
for (CourseAreaDTO courseAreaDTO : event.venue.getCourseAreas()) {
|
||||
if (courseAreaDTO.id.toString().equals(selectedCourseAreaId)) {
|
||||
result = courseAreaDTO;
|
||||
break;
|
||||
}
|
||||
|
||||
+2
-1
@@ -27,6 +27,7 @@ import com.sap.sse.gwt.client.IconResources;
|
||||
import com.sap.sse.gwt.client.controls.IntegerBox;
|
||||
import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicator;
|
||||
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
|
||||
import com.sap.sse.gwt.client.controls.listedit.GenericStringListInlineEditorComposite;
|
||||
import com.sap.sse.gwt.client.controls.listedit.StringListInlineEditorComposite;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
|
||||
import com.sap.sse.gwt.client.media.ImageDTO;
|
||||
@@ -139,7 +140,7 @@ public abstract class ImageDialog extends DataEntryDialog<ImageDTO> {
|
||||
});
|
||||
|
||||
tagsListEditor = new StringListInlineEditorComposite(Collections.<String> emptyList(),
|
||||
new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */
|
||||
new GenericStringListInlineEditorComposite.ExpandedUi<String>(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */
|
||||
MediaConstants.imageTagSuggestions, "Enter tags for the image", 30));
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -31,6 +31,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
|
||||
import com.sap.sse.gwt.client.IconResources;
|
||||
import com.sap.sse.gwt.client.controls.listedit.GenericStringListInlineEditorComposite;
|
||||
import com.sap.sse.gwt.client.controls.listedit.StringListEditorComposite;
|
||||
import com.sap.sse.gwt.client.controls.listedit.StringListInlineEditorComposite;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
|
||||
@@ -234,7 +235,7 @@ public class SeriesEditDialog extends DataEntryDialog<SeriesDescriptor> {
|
||||
return selectedSeries;
|
||||
}
|
||||
|
||||
private class RaceNamesEditorUi extends StringListInlineEditorComposite.ExpandedUi {
|
||||
private class RaceNamesEditorUi extends GenericStringListInlineEditorComposite.ExpandedUi<String> {
|
||||
private final RegattaDTO regatta;
|
||||
|
||||
private final ListBox addRacesFromListBox;
|
||||
|
||||
+13
-1
@@ -217,7 +217,11 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC
|
||||
private boolean doesTrackerExist(RaceColumnDTOAndFleetDTOWithNameBasedEquality race) {
|
||||
return race.getA().getRaceLogTrackingInfo(race.getB()).raceLogTrackerExists;
|
||||
}
|
||||
|
||||
|
||||
private boolean doesCourseExist(RaceColumnDTOAndFleetDTOWithNameBasedEquality race) {
|
||||
return race.getA().getRaceLogTrackingInfo(race.getB()).courseExists;
|
||||
}
|
||||
|
||||
private boolean doCompetitorResgistrationsExist(RaceColumnDTOAndFleetDTOWithNameBasedEquality race) {
|
||||
return race.getA().getRaceLogTrackingInfo(race.getB()).competitorRegistrationsExists;
|
||||
}
|
||||
@@ -240,6 +244,13 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality> courseStateColumn = new TextColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality>() {
|
||||
@Override
|
||||
public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality raceColumnAndFleetName) {
|
||||
return doesCourseExist(raceColumnAndFleetName) ? stringMessages.ok() : stringMessages.none();
|
||||
}
|
||||
};
|
||||
|
||||
raceActionColumn =
|
||||
new ImagesBarColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality, RaceLogTrackingEventManagementRaceImagesBarCell>(
|
||||
new RaceLogTrackingEventManagementRaceImagesBarCell(stringMessages, this));
|
||||
@@ -348,6 +359,7 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC
|
||||
|
||||
racesTable.addColumn(raceLogTrackingStateColumn, stringMessages.raceStatusColumn());
|
||||
racesTable.addColumn(trackerStateColumn, stringMessages.trackerStatus());
|
||||
racesTable.addColumn(courseStateColumn, stringMessages.courseStatus());
|
||||
racesTable.addColumn(raceActionColumn, stringMessages.actions());
|
||||
racesTable.setWidth("600px");
|
||||
}
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ import com.sap.sse.common.media.MimeType;
|
||||
import com.sap.sse.gwt.adminconsole.URLFieldWithFileUpload;
|
||||
import com.sap.sse.gwt.client.IconResources;
|
||||
import com.sap.sse.gwt.client.controls.IntegerBox;
|
||||
import com.sap.sse.gwt.client.controls.listedit.GenericStringListInlineEditorComposite;
|
||||
import com.sap.sse.gwt.client.controls.listedit.StringListInlineEditorComposite;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
|
||||
import com.sap.sse.gwt.client.media.VideoDTO;
|
||||
@@ -89,7 +90,7 @@ public abstract class VideoDialog extends DataEntryDialog<VideoDTO> {
|
||||
});
|
||||
thumbnailURLAndUploadComposite = new URLFieldWithFileUpload(stringMessages);
|
||||
tagsListEditor = new StringListInlineEditorComposite(Collections.<String> emptyList(),
|
||||
new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */
|
||||
new GenericStringListInlineEditorComposite.ExpandedUi<String>(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */
|
||||
MediaConstants.videoTagSuggestions, "Enter tags for the video", 50));
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -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();
|
||||
@@ -1039,6 +1040,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c
|
||||
String removeLeaderboardFilter();
|
||||
String competitorRegistrations();
|
||||
String trackerStatus();
|
||||
String courseStatus();
|
||||
String canOnlyBeEditedBeforeStartingTracking();
|
||||
String defineCourse();
|
||||
String mapDevices();
|
||||
|
||||
+2
@@ -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.
|
||||
@@ -1009,6 +1010,7 @@ filterByLeaderboard=Filter by Leaderboard
|
||||
removeLeaderboardFilter=Remove Leaderboard filter
|
||||
competitorRegistrations=Competitor Registrations
|
||||
trackerStatus=Tracker Status
|
||||
courseStatus=Course Status
|
||||
canOnlyBeEditedBeforeStartingTracking=Can only be edited before starting tracking
|
||||
defineCourse=Define Course Layout
|
||||
mapDevices=Map Devices to Competitors and Marks
|
||||
|
||||
+7
-5
@@ -415,8 +415,8 @@ successfullyUpdatedCourse=Kurs erfolgreich aktualisiert
|
||||
selectTwoMarksForGate=Zwei Marken auswählen, um ein Gate zu erstellen
|
||||
errorTryingToObtainTheMarksOfTheRace=Fehler beim Ermitteln der Marken des Regattakurses: {0}
|
||||
errorTryingToObtainRaceCourse=Fehler beim Ermitteln des Rennkurses: {0}
|
||||
insertWaypointBeforeSelected=Wegpunkt nach dem selektierten einfügen
|
||||
insertWaypointAfterSelected=Wegpunkt vor dem selektierten einfügen
|
||||
insertWaypointBeforeSelected=Wegpunkt vor dem selektierten einfügen
|
||||
insertWaypointAfterSelected=Wegpunkt nach dem selektierten einfügen
|
||||
addGate=Gate hinzufügen
|
||||
scoringSchemeLowPointSystem=Low Point System
|
||||
scoringSchemeHighPointSystem=High Point System
|
||||
@@ -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.
|
||||
@@ -998,8 +999,9 @@ denoteForRaceLogTracking=Für RaceLog Tracking markieren
|
||||
startRaceLogTracking=RaceLog Tracking starten
|
||||
filterByLeaderboard=Nach Rangliste filtern
|
||||
removeLeaderboardFilter=Nicht nach Rangliste filtern
|
||||
competitorRegistrations=Team Anmeldungen
|
||||
trackerStatus=Tracker-Status
|
||||
competitorRegistrations=Teamanmeldungen
|
||||
trackerStatus=Trackerstatus
|
||||
courseStatus=Kursstatus
|
||||
canOnlyBeEditedBeforeStartingTracking=Kann nur vor Beginn des Trackings bearbeitet werden
|
||||
defineCourse=Kurs definieren
|
||||
mapDevices=Gerätezuordnung zu Teams und Tonnen
|
||||
@@ -1416,7 +1418,7 @@ couldNotRetrieveImageSizeYet=Bildgröße konnte noch nicht ermittelt werden.
|
||||
pleaseOnlyUploadContentYouHaveAllUsageRightsFor=Bitte nur Inhalte hochladen, für die alle Verwendungsrechte vorliegen. Bitte beachten: Bilder können verändert wiedergegeben werden.
|
||||
registerCompetitorsOnRace=Teilnehmer auf dem Rennen registrieren (z.B. für Split-Fleets)
|
||||
doYouWantToRegisterCompetitorsDirectlyOnTheRace=Wollen Sie Teilnehmer direkt auf dem Rennen registrieren?
|
||||
warningDirectCompetitorRegistration=Warnung! Diese Einstellung führt dazu, dass Teilnehmer dieses Rennens sich von nunan auf Rennebene registriert werden müssen. Dies ist nur sinnvoll, wenn sich die Teilnehmer verschiedener Rennen einer Regatta unterscheiden.
|
||||
warningDirectCompetitorRegistration=Warnung! Diese Einstellung führt dazu, dass Teilnehmer dieses Rennens von nun an auf Rennebene registriert werden müssen. Dies ist nur sinnvoll, wenn sich die Teilnehmer verschiedener Rennen einer Regatta unterscheiden.
|
||||
warningRegattaCompetitorRegistration=Warnung! Diese Einstellung reaktiviert die Teilnehmerregistrierung auf Regatta-Ebene. Alle Teilnehmer der zu diesem Rennen gehörenden Regatta werden automatisch Teilnehmer dieses Rennens.
|
||||
doYouWantToDisableCompetitorsRegistrationsOnTheRace=Wollen Sie Teilnehmer auf Regatta- statt Rennebene registrieren?
|
||||
competitorRegistrationsOnRaceDisabled=Teilnehmeranmeldung ist für dieses Rennen auf Rennebene deaktiviert. Aktivieren durch selektieren der CheckBox auf der linken Seite.
|
||||
|
||||
+2
@@ -973,6 +973,7 @@ successfullyRemoveIgtimiAccount=已成功移除用户{0}的 Igtimi 账户
|
||||
eMailMustNotBeEmpty=电子邮件地址不得为空
|
||||
emailAddress=电子邮件地址
|
||||
password=密码
|
||||
searchTag=Search tag
|
||||
doYouReallyWantToRemoveLeaderboard=是否确定移除积分榜: ''{0}''?
|
||||
metaLeaderboardCannotBeChanged=此为元积分榜。无法在此处更改。
|
||||
failedToSetNewStartTime=设置新开始时间失败。 相同的开始时间可能已存在于比赛轮次日志中或某人已添加(场次编号和逻辑时间)更新的开始时间。
|
||||
@@ -1005,6 +1006,7 @@ filterByLeaderboard=按积分榜筛选
|
||||
removeLeaderboardFilter=移除积分榜筛选器
|
||||
competitorRegistrations=参赛队注册
|
||||
trackerStatus=跟踪器状态
|
||||
courseStatus=Course Status
|
||||
canOnlyBeEditedBeforeStartingTracking=只可以在开始跟踪前编辑
|
||||
defineCourse=定义场地设置
|
||||
mapDevices=将设备映射到参赛队和标志
|
||||
|
||||
+2
@@ -975,6 +975,7 @@ successfullyRemoveIgtimiAccount=已成功移除用户{0}的 Igtimi 账户
|
||||
eMailMustNotBeEmpty=电子邮件地址不得为空
|
||||
emailAddress=电子邮件地址
|
||||
password=密码
|
||||
searchTag=Search tag
|
||||
doYouReallyWantToRemoveLeaderboard=是否确定移除积分榜: ''{0}''?
|
||||
metaLeaderboardCannotBeChanged=此为元积分榜。无法在此处更改。
|
||||
failedToSetNewStartTime=设置新开始时间失败。 相同的开始时间可能已存在于比赛轮次日志中或某人已添加(场次编号和逻辑时间)更新的开始时间。
|
||||
@@ -1007,6 +1008,7 @@ filterByLeaderboard=按积分榜筛选
|
||||
removeLeaderboardFilter=移除积分榜筛选器
|
||||
competitorRegistrations=参赛队注册
|
||||
trackerStatus=跟踪器状态
|
||||
courseStatus=Course Status
|
||||
canOnlyBeEditedBeforeStartingTracking=只可以在开始跟踪前编辑
|
||||
defineCourse=定义场地设置
|
||||
mapDevices=将设备映射到参赛队和标志
|
||||
|
||||
+12
-6
@@ -2453,8 +2453,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
new RaceLogTrackingStateAnalyzer(raceLog).analyze();
|
||||
final boolean raceLogTrackerExists = raceLog == null ? false : getService().getRaceTrackerById(raceLog.getId()) != null;
|
||||
final boolean competitorRegistrationsExist = raceLog == null ? false : !Util.isEmpty(raceColumn.getAllCompetitors(fleet));
|
||||
final boolean courseExist = raceLog == null ? false : !Util.isEmpty(raceColumn.getCourseMarks(fleet));
|
||||
final RaceLogTrackingInfoDTO raceLogTrackingInfo = new RaceLogTrackingInfoDTO(raceLogTrackerExists,
|
||||
competitorRegistrationsExist, raceLogTrackingState);
|
||||
competitorRegistrationsExist, courseExist, raceLogTrackingState);
|
||||
raceColumnDTO.setRaceLogTrackingInfo(fleetDTO, raceLogTrackingInfo);
|
||||
}
|
||||
}
|
||||
@@ -4718,7 +4719,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 +4728,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;
|
||||
}
|
||||
@@ -5161,14 +5163,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
}
|
||||
|
||||
private Mark convertToMark(MarkDTO dto, boolean resolve) {
|
||||
Mark result = null;
|
||||
if (resolve) {
|
||||
Mark existing = baseDomainFactory.getExistingMarkByIdAsString(dto.getIdAsString());
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
result = existing;
|
||||
}
|
||||
}
|
||||
Serializable id = UUID.randomUUID();
|
||||
return baseDomainFactory.getOrCreateMark(id, dto.getName(), dto.type, dto.color, dto.shape, dto.pattern);
|
||||
if (result == null) {
|
||||
Serializable id = UUID.randomUUID();
|
||||
result = baseDomainFactory.getOrCreateMark(id, dto.getName(), dto.type, dto.color, dto.shape, dto.pattern);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+23
-1
@@ -6,7 +6,7 @@ import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
import com.sap.sailing.domain.common.dto.NamedDTO;
|
||||
|
||||
/**
|
||||
* Equality and hash code are based on the course area's name, as inherited from {@link NamedDTO}.
|
||||
* Equality and hash code are based on the course area's {@link #id}.
|
||||
*/
|
||||
public class CourseAreaDTO extends NamedDTO implements IsSerializable {
|
||||
private static final long serialVersionUID = -5279690838452265454L;
|
||||
@@ -18,4 +18,26 @@ public class CourseAreaDTO extends NamedDTO implements IsSerializable {
|
||||
public CourseAreaDTO(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = prime * ((id == null) ? 0 : id.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
CourseAreaDTO other = (CourseAreaDTO) obj;
|
||||
if (id == null) {
|
||||
if (other.id != null)
|
||||
return false;
|
||||
} else if (!id.equals(other.id))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+122
-122
@@ -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()));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
|
||||
+6
-6
@@ -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);
|
||||
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -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));
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
+3
@@ -92,6 +92,9 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive
|
||||
}, /* trackedRegattaRegistry */ null, mock(RaceLogResolver.class),
|
||||
/*courseDesignUpdateURI*/ null, /*tracTracUsername*/ null, /*tracTracPassword*/ null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false, ReceiverType.RACECOURSE);
|
||||
addListenersForStoredDataAndStartController(typeControllers);
|
||||
for (final Receiver receiver : typeControllers) {
|
||||
addReceiverToStopDuringTearDown(receiver);
|
||||
}
|
||||
RaceDefinition race = domainFactory.getAndWaitForRaceDefinition(getTracTracEvent().getRaces().iterator().next().getId());
|
||||
DynamicTrackedRace trackedRace = trackedRegatta.createTrackedRace(race, Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE,
|
||||
/* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 10000, new DynamicRaceDefinitionSet() {
|
||||
|
||||
-1
@@ -31,7 +31,6 @@ public class MarkDeserializer implements JsonDeserializer<Mark> {
|
||||
String shape = (String) object.get(MarkJsonSerializer.FIELD_SHAPE);
|
||||
MarkType type = MarkType.valueOf((String) object.get(MarkJsonSerializer.FIELD_TYPE));
|
||||
String name = (String) object.get(MarkJsonSerializer.FIELD_NAME);
|
||||
|
||||
Mark mark = factory.getOrCreateMark(id, name, type, color, shape, pattern);
|
||||
return mark;
|
||||
}
|
||||
|
||||
+100
-99
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -63,6 +63,11 @@ public class Helpers {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the {@link Object#toString() string representation} of {@code serializableId} {@link UUID#fromString(String) parses}
|
||||
* as a {@link UUID}, the resulting {@link UUID} is returned. Otherwise, the {@code serializableId} parameter's value
|
||||
* is returned unchanged.
|
||||
*/
|
||||
public static Serializable tryUuidConversion(Serializable serializableId) {
|
||||
try {
|
||||
return UUID.fromString(serializableId.toString());
|
||||
|
||||
+1
@@ -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());
|
||||
|
||||
+248
-248
@@ -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);
|
||||
}
|
||||
}
|
||||
+102
-102
@@ -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;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 151 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user