diff --git a/build.gradle b/build.gradle index 7871b6fab19..4254f5bf9f2 100644 --- a/build.gradle +++ b/build.gradle @@ -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' } } diff --git a/home.md b/home.md index d8231764684..04431fabbd3 100644 --- a/home.md +++ b/home.md @@ -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]] diff --git a/ios/SAPTracker/src/xcode/SAPTracker/LocationManager.swift b/ios/SAPTracker/src/xcode/SAPTracker/LocationManager.swift index 09000559c7a..79e8327c34d 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/LocationManager.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/LocationManager.swift @@ -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; } -} \ No newline at end of file +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java index 7a60ac393cc..0769df08249 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java @@ -17,7 +17,9 @@ public interface CompetitorDTO extends Serializable, MappableToDevice { String getIdAsString(); String getSailID(); - + + String getSearchTag(); + BoatDTO getBoat(); BoatClassDTO getBoatClass(); diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java index ca059c63cc6..d10dea35696 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java @@ -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; + } +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java index 4016116068c..de15b86d671 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java @@ -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); + } } \ No newline at end of file diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceLogTrackingInfoDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceLogTrackingInfoDTO.java index 5a424d1412b..1096987fefd 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceLogTrackingInfoDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceLogTrackingInfoDTO.java @@ -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; + } +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/CompetitorJsonConstants.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/CompetitorJsonConstants.java index 2c56deda227..2d083a0ad1c 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/CompetitorJsonConstants.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/CompetitorJsonConstants.java @@ -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"; diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/GPSFixImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/GPSFixImpl.java index d37526dbff5..f915d9a8a54 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/GPSFixImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/GPSFixImpl.java @@ -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)); diff --git a/java/com.sap.sailing.domain.igtimiadapter.test/src/com/sap/sailing/domain/igtimiadapter/websocket/WebSocketTest.java b/java/com.sap.sailing.domain.igtimiadapter.test/src/com/sap/sailing/domain/igtimiadapter/websocket/WebSocketTest.java index 03c2cc7ec4e..eb3f52bf7fa 100755 --- a/java/com.sap.sailing.domain.igtimiadapter.test/src/com/sap/sailing/domain/igtimiadapter/websocket/WebSocketTest.java +++ b/java/com.sap.sailing.domain.igtimiadapter.test/src/com/sap/sailing/domain/igtimiadapter/websocket/WebSocketTest.java @@ -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; diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index fe7afc50e49..8377d398eff 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -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()); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java index bc7380eb902..23ae75b4041 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java @@ -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(); + } +} diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java index a152a09097f..e70ac72f818 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java @@ -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))); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java index 1cd8a239441..44440153343 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java @@ -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. 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. 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. 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. 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)); + } +} diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java index 27c8ea5529c..e0407e57277 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java @@ -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)); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_de.properties b/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_de.properties index b03501999c6..dd6e394c6fc 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_de.properties +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_de.properties @@ -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 \ No newline at end of file +appAndroid=Android App installieren +buoyPingerAppName=SAP Sailing Buoy Pinger +sailInSightAppName=SAP Sail InSight \ No newline at end of file diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_en.properties b/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_en.properties index a0a76a3ed1b..f99307e6ec4 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_en.properties +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_en.properties @@ -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 \ No newline at end of file +appAndroid=Install Android App +buoyPingerAppName=SAP Sailing Buoy Pinger +sailInSightAppName=SAP Sail InSight \ No newline at end of file diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java index 0daa3a1bef8..5e9ca597b04 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java @@ -532,7 +532,22 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener { for (DeviceMapping mapping : markMappingsByDevices.get(device)) { Mark mark = mapping.getMappedTo(); if (mapping.getTimeRange().includes(timePoint)) { - trackedRace.recordFix(mark, fix); + final DynamicGPSFixTrack 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); + } } } } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java index 265cee35628..d11b48e86cc 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java @@ -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("

"); } htmlText.append("

").append(B.get(locale, "welcomeTo")).append(" ").append(leaderboardName).append("

"); - htmlText.append("

").append(B.get(locale, "scanQRCodeOrVisitUrlToRegisterAs")).append(" ").append(invitee) + htmlText.append("

").append(B.get(locale, "scanQRCodeOrVisitUrlToRegisterAs", appName)).append(" ").append(invitee) .append("

"); htmlText.append("

"); htmlText.append("

").append(B.get(locale, "alternativelyVisitThisLink")).append("

"); @@ -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"); } diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java index 693e7df1e24..219ac0590cc 100755 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java @@ -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() { diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java index 00bd8c50d03..894d574aada 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java @@ -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; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java index 74a7f176fdd..5fc715f27d9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java @@ -23,6 +23,8 @@ public interface Competitor extends Named, WithID, IsManagedByCachetrue, - * must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the - * competitor's values. - */ - Competitor getExistingCompetitorById(Serializable competitorId); - - /** - * Checks if the competitor 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 true, + * must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the + * competitor's values. + */ + Competitor getExistingCompetitorById(Serializable competitorId); + + /** + * Checks if the competitor 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); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java index 4b0fb8afb85..7ccc5f81527 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java @@ -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 true, - * 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 - * competitor'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 getCompetitors(); - - void removeCompetitor(Competitor competitor); - - /** - * Updates the competitor with {@link Competitor#getId() ID} id 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.

- * - * 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 true, + * 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 + * competitor'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 getCompetitors(); + + void removeCompetitor(Competitor competitor); + + /** + * Updates the competitor with {@link Competitor#getId() ID} id 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.

+ * + * 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); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java index 03d495961e5..706ab7e4d72 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java @@ -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 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(); } @@ -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(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java index 011234189f5..a0fd2afc28c 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java @@ -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); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java index dfea9a3b76c..f35232cf6f6 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java @@ -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 same string is used as key that is also used to set the {@link Nationality} - * object's {@link Nationality#getThreeLetterIOCAcronym() IOC code}. - */ - private final Map nationalityCache; - - private final Map markCache; - - private final Map 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 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 controlPointWithTwoMarksIdCache; - - private final Map boatClassCache; - - protected final CompetitorStore competitorStore; - - private final Map 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 null. 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 waypointCache; - - private final ReferenceQueue waypointCacheReferenceQueue; - - private final Map 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 { - 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 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(); - nationalityCache = new HashMap(); - markCache = new HashMap(); - markIdCache = new HashMap(); - controlPointWithTwoMarksCache = new HashMap(); - controlPointWithTwoMarksIdCache = new HashMap(); - boatClassCache = new HashMap(); - this.competitorStore = competitorStore; - waypointCache = new ConcurrentHashMap(); - // 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(); - configurationMatcherCache = new HashMap(); - } - - @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 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 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 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 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 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 same string is used as key that is also used to set the {@link Nationality} + * object's {@link Nationality#getThreeLetterIOCAcronym() IOC code}. + */ + private final Map nationalityCache; + + private final Map markCache; + + private final Map 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 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 controlPointWithTwoMarksIdCache; + + private final Map boatClassCache; + + protected final CompetitorStore competitorStore; + + private final Map 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 null. 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 waypointCache; + + private final ReferenceQueue waypointCacheReferenceQueue; + + private final Map 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 { + 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 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(); + nationalityCache = new HashMap(); + markCache = new HashMap(); + markIdCache = new HashMap(); + controlPointWithTwoMarksCache = new HashMap(); + controlPointWithTwoMarksIdCache = new HashMap(); + boatClassCache = new HashMap(); + this.competitorStore = competitorStore; + waypointCache = new ConcurrentHashMap(); + // 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(); + configurationMatcherCache = new HashMap(); + } + + @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 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 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 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 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 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; + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index fad14860eb0..5a4d89e2f8b 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -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 competitorCache; - private final Map competitorsByIdAsString; - private transient Set 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 competitorsToUpdateDuringGetOrCreate; - - private transient WeakHashMap weakCompetitorDTOCache; - - private final NamedReentrantReadWriteLock lock; - - public TransientCompetitorStoreImpl() { - lock = new NamedReentrantReadWriteLock("CompetitorStore", /* fair */ false); - competitorCache = new HashMap(); - competitorsByIdAsString = new HashMap(); - competitorsToUpdateDuringGetOrCreate = new HashSet(); - weakCompetitorDTOCache = new WeakHashMap(); - listeners = Collections.synchronizedSet(new HashSet()); - } - - private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { - ois.defaultReadObject(); - weakCompetitorDTOCache = new WeakHashMap(); - listeners = Collections.synchronizedSet(new HashSet()); - } - - @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 competitor 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 getCompetitors() { - LockUtil.lockForRead(lock); - try { - return new ArrayList(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 competitorCache; + private final Map competitorsByIdAsString; + private transient Set 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 competitorsToUpdateDuringGetOrCreate; + + private transient WeakHashMap weakCompetitorDTOCache; + + private final NamedReentrantReadWriteLock lock; + + public TransientCompetitorStoreImpl() { + lock = new NamedReentrantReadWriteLock("CompetitorStore", /* fair */ false); + competitorCache = new HashMap(); + competitorsByIdAsString = new HashMap(); + competitorsToUpdateDuringGetOrCreate = new HashSet(); + weakCompetitorDTOCache = new WeakHashMap(); + listeners = Collections.synchronizedSet(new HashSet()); + } + + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + ois.defaultReadObject(); + weakCompetitorDTOCache = new WeakHashMap(); + listeners = Collections.synchronizedSet(new HashSet()); + } + + @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 competitor 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 getCompetitors() { + LockUtil.lockForRead(lock); + try { + return new ArrayList(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); + } + } +} diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index c0239414ed0..fd218645037 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -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; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java index f630c65f58d..feb5b68187a 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java @@ -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.

- * - * The data of a meaningful and non-trivial {@link LeaderboardDTO} is obtained by using an instrumented version of - * SailingServiceImpl.getLeaderboardByName(...) 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 hadLegDetailsInR9 = new HashSet<>(); - Map newRows = new HashMap<>(); - for (CompetitorDTO competitor : previousVersion.rows.keySet()) { - LeaderboardRowDTO competitorRow = new LeaderboardRowDTO(); - cloner.clone(newVersion.rows.get(competitor), competitorRow); - Map newFieldsByRaceColumnName = new HashMap<>(); - for (Entry 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(newVersion.rows); - List raceListBeforeStripping = new ArrayList(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 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 newRows = new HashMap(newVersion.rows); - double newDistance = 1234; - String nameOfRaceColumnToChange = "R9"; - int indexOfLegToChange = 7; // ( zero based: ) 8th leg is the last leg - for (Map.Entry e : newVersion.rows.entrySet()) { - LeaderboardRowDTO newRow = new LeaderboardRowDTO(); - cloner.clone(e.getValue(), newRow); - newRows.put(e.getKey(), newRow); - newRow.fieldsByRaceColumnName = new HashMap(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(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 rowsBeforeStripping = newVersion.rows; - Map, List> previousLegDetailsBeforeStripping = new HashMap<>(); - for (Map.Entry e : rowsBeforeStripping.entrySet()) { - for (Map.Entry e2 : e.getValue().fieldsByRaceColumnName.entrySet()) { - if (e2.getValue().legDetails != null) { - previousLegDetailsBeforeStripping.put(new com.sap.sse.common.Util.Pair(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, List> e : previousLegDetailsBeforeStripping.entrySet()) { - final LeaderboardRowDTO leaderboardRowDTO = rowsBeforeStripping.get(e.getKey().getA()); - if (leaderboardRowDTO != null) { - List 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 e : newVersion.rows.entrySet()) { - if (e.getValue().fieldsByRaceColumnName != null) { - assertTrue(e.getValue().fieldsByRaceColumnName.size() <= 1); - for (Map.Entry e2 : e.getValue().fieldsByRaceColumnName.entrySet()) { - if (e2.getKey().equals(nameOfRaceColumnToChange)) { - List r9LegDetails = e2.getValue().legDetails; - if (r9LegDetails != null) { - for (int i=0; i(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 newCompetitorsBeforeStripping = new ArrayList(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 newSuppressedCompetitors = new ArrayList(); - Util.addAll(newVersion.getSuppressedCompetitors(), newSuppressedCompetitors); - newVersion.setSuppressedCompetitors(newSuppressedCompetitors); - newVersion.competitors = new ArrayList(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 newSuppressedCompetitorsBeforeStripping = new ArrayList(); - 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(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(newVersion.competitorDisplayNames); - newVersion.competitorDisplayNames.put(newVersion.competitors.get(13), "Humba"); - newVersion.competitorDisplayNames.put(somebodyNew, "Trala"); - final HashMap newDisplayNamesBeforeStripping = new HashMap(); - 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> newCompetitorOrderingPerRace = new HashMap>(newVersion.getCompetitorOrderingPerRaceColumnName()); - newVersion.setCompetitorOrderingPerRace(newCompetitorOrderingPerRace); - List newOrdering = new ArrayList(newVersion.getCompetitorsFromBestToWorst(r9)); - newVersion.setCompetitorsFromBestToWorst(r9, newOrdering); - newVersion.competitors = new ArrayList(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 newOrderBeforeStripping = new ArrayList(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 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 m = (Map) racesPerFleetField.get(clonedR9); - racesPerFleetField.set(clonedR9, new HashMap(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 clonedRaceList = new ArrayList(newVersion.getRaceList()); - clonedRaceList.set(clonedRaceList.indexOf(r9), clonedR9); - newVersion.setRaceList(clonedRaceList); - List raceListBeforeStripping = new ArrayList(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.

+ * + * The data of a meaningful and non-trivial {@link LeaderboardDTO} is obtained by using an instrumented version of + * SailingServiceImpl.getLeaderboardByName(...) 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 hadLegDetailsInR9 = new HashSet<>(); + Map newRows = new HashMap<>(); + for (CompetitorDTO competitor : previousVersion.rows.keySet()) { + LeaderboardRowDTO competitorRow = new LeaderboardRowDTO(); + cloner.clone(newVersion.rows.get(competitor), competitorRow); + Map newFieldsByRaceColumnName = new HashMap<>(); + for (Entry 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(newVersion.rows); + List raceListBeforeStripping = new ArrayList(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 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 newRows = new HashMap(newVersion.rows); + double newDistance = 1234; + String nameOfRaceColumnToChange = "R9"; + int indexOfLegToChange = 7; // ( zero based: ) 8th leg is the last leg + for (Map.Entry e : newVersion.rows.entrySet()) { + LeaderboardRowDTO newRow = new LeaderboardRowDTO(); + cloner.clone(e.getValue(), newRow); + newRows.put(e.getKey(), newRow); + newRow.fieldsByRaceColumnName = new HashMap(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(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 rowsBeforeStripping = newVersion.rows; + Map, List> previousLegDetailsBeforeStripping = new HashMap<>(); + for (Map.Entry e : rowsBeforeStripping.entrySet()) { + for (Map.Entry e2 : e.getValue().fieldsByRaceColumnName.entrySet()) { + if (e2.getValue().legDetails != null) { + previousLegDetailsBeforeStripping.put(new com.sap.sse.common.Util.Pair(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, List> e : previousLegDetailsBeforeStripping.entrySet()) { + final LeaderboardRowDTO leaderboardRowDTO = rowsBeforeStripping.get(e.getKey().getA()); + if (leaderboardRowDTO != null) { + List 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 e : newVersion.rows.entrySet()) { + if (e.getValue().fieldsByRaceColumnName != null) { + assertTrue(e.getValue().fieldsByRaceColumnName.size() <= 1); + for (Map.Entry e2 : e.getValue().fieldsByRaceColumnName.entrySet()) { + if (e2.getKey().equals(nameOfRaceColumnToChange)) { + List r9LegDetails = e2.getValue().legDetails; + if (r9LegDetails != null) { + for (int i=0; i(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 newCompetitorsBeforeStripping = new ArrayList(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 newSuppressedCompetitors = new ArrayList(); + Util.addAll(newVersion.getSuppressedCompetitors(), newSuppressedCompetitors); + newVersion.setSuppressedCompetitors(newSuppressedCompetitors); + newVersion.competitors = new ArrayList(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 newSuppressedCompetitorsBeforeStripping = new ArrayList(); + 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(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(newVersion.competitorDisplayNames); + newVersion.competitorDisplayNames.put(newVersion.competitors.get(13), "Humba"); + newVersion.competitorDisplayNames.put(somebodyNew, "Trala"); + final HashMap newDisplayNamesBeforeStripping = new HashMap(); + 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> newCompetitorOrderingPerRace = new HashMap>(newVersion.getCompetitorOrderingPerRaceColumnName()); + newVersion.setCompetitorOrderingPerRace(newCompetitorOrderingPerRace); + List newOrdering = new ArrayList(newVersion.getCompetitorsFromBestToWorst(r9)); + newVersion.setCompetitorsFromBestToWorst(r9, newOrdering); + newVersion.competitors = new ArrayList(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 newOrderBeforeStripping = new ArrayList(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 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 m = (Map) racesPerFleetField.get(clonedR9); + racesPerFleetField.set(clonedR9, new HashMap(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 clonedRaceList = new ArrayList(newVersion.getRaceList()); + clonedRaceList.set(clonedRaceList.indexOf(r9), clonedR9); + newVersion.setRaceList(clonedRaceList); + List raceListBeforeStripping = new ArrayList(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()); + } +} diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java index 0bc77b2bd22..db4365de36d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java @@ -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); } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java index 8a8a930bf72..e5acc80daf5 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java @@ -179,4 +179,8 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest { public static String getTracTracPassword() { return "tracTest"; } + + protected void addReceiverToStopDuringTearDown(Receiver receiver) { + receivers.add(receiver); + } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java index 8635dc19eca..ec519bdd7ac 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java @@ -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(); + } +} diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java index d5c8a4b7178..33a8894c49f 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java @@ -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()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java index db6cfdb55e2..b43c350c0e5 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java @@ -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 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 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 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(), 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()); - when(mockedRaceDefinition.getCourse()).thenReturn(course); - when(mockedRaceDefinition.getBoatClass()).thenReturn(new BoatClassImpl("TestClass", true)); - when(mockedRaceDefinition.getName()).thenReturn("TestRace"); - Iterable competitorSet = createCompetitorSet(boatClass); - when(mockedRaceDefinition.getCompetitors()).thenReturn(competitorSet); - return mockedRaceDefinition; - } - - private Iterable createCompetitorSet(BoatClass boatClass) { - Set 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 fleets = new HashSet<>(); - fleets.add(fleet); - - Series series = new SeriesImpl("TestSeries", false, fleets, new HashSet(), 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 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 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 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(), 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()); + when(mockedRaceDefinition.getCourse()).thenReturn(course); + when(mockedRaceDefinition.getBoatClass()).thenReturn(new BoatClassImpl("TestClass", true)); + when(mockedRaceDefinition.getName()).thenReturn("TestRace"); + Iterable competitorSet = createCompetitorSet(boatClass); + when(mockedRaceDefinition.getCompetitors()).thenReturn(competitorSet); + return mockedRaceDefinition; + } + + private Iterable createCompetitorSet(BoatClass boatClass) { + Set 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 fleets = new HashSet<>(); + fleets.add(fleet); + + Series series = new SeriesImpl("TestSeries", false, fleets, new HashSet(), trackedRegattaRegistry); + return series; + } + +} diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MarkPositionTimeFilterTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MarkPositionTimeFilterTest.java index 355c207a3f4..c53d016a14a 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MarkPositionTimeFilterTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MarkPositionTimeFilterTest.java @@ -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(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()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java index 72f002fbfb8..378df1e5721 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java @@ -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); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java index cb7d6c5a6e0..89f74c0e261 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java @@ -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()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java index 03f9b00753d..667ce328d5d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java @@ -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 */ diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java index 40abe2563a6..8c346df6cae 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java @@ -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 track = readTrack(c, KIELER_WOCHE); if (track != null) { tracks.put(c, track); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java index 3d3fc2ddd2f..e9f1099044b 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java @@ -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()))); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java index 159809279a5..0013699ab37 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java @@ -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); } /** diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java index cf6c06430f3..2cec66d642d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java @@ -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, diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMarkPassingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMarkPassingTest.java index bcab5fcf473..11bd52a71e2 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMarkPassingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMarkPassingTest.java @@ -123,7 +123,7 @@ public abstract class AbstractMarkPassingTest extends OnlineTracTracBasedTest { Map> 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()) { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java index 4f4451b016b..1f6023f282d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java @@ -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"); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/StarIDM2013MarkPassingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/StarIDM2013MarkPassingTest.java index 1d62e3c0308..a91dd72f700 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/StarIDM2013MarkPassingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/StarIDM2013MarkPassingTest.java @@ -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")); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java index d982c9341f3..90bcdf66356 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java @@ -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 threeLetterIOCCode also as the diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index 7df01e515ff..0b248290948 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -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; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java index 2a962d846bc..ba24fa23ff1 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java @@ -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 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 getCompetitors(); + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java index d5eda9b723d..7c0d5142d2d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java @@ -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); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/Candidate.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/Candidate.java index 71b4aca1767..bbe1b82fbdd 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/Candidate.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/Candidate.java @@ -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 diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/CandidateFinder.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/CandidateFinder.java index 41a41cd975f..50199c8abe9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/CandidateFinder.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/CandidateFinder.java @@ -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> getCandidateDeltas(Competitor c, Iterable 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> calculateFixesAffectedByNewMarkFixes(Map> newMarkFixes); - } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingCalculator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingCalculator.java index bb58ce6b5dc..f59626ef5a1 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingCalculator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingCalculator.java @@ -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 listen 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> 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> 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(); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingUpdateListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingUpdateListener.java index d29571368c4..c35e2dd3d9c 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingUpdateListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingUpdateListener.java @@ -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 queue; + private final String raceName; + private final StorePositionUpdateStrategy endMarker = new StorePositionUpdateStrategy() { @Override public void storePositionUpdate(Map> competitorFixes, @@ -44,6 +46,7 @@ public class MarkPassingUpdateListener extends AbstractRaceChangeListener { * Adds itself automatically as a Listener on the race 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); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateChooserImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateChooserImpl.java index 3b2435361bf..657e33e83a1 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateChooserImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateChooserImpl.java @@ -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 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(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImpl.java index 4a13891c6fa..3df53508ee6 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImpl.java @@ -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 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 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 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; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java index 5514307549f..53219a75c61 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java @@ -131,7 +131,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { * Helper instance used to encode null values in {@link ConcurrentHashMap} instances which do not accept * null 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; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java index 8e94e07d7d1..8b3da218a62 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java @@ -100,6 +100,11 @@ public class DummyMarkPassingWithTimePointOnly implements MarkPassing { public Duration getTimeOnDistanceAllowancePerNauticalMile() { return null; } + + @Override + public String getSearchTag() { + return null; + } }; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java index adb90c43932..f4d60a544c8 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java @@ -104,9 +104,6 @@ DynamicTrackedRace, GPSTrackListener { this.startTimeChangedListeners = new HashSet<>(); this.raceAbortedListeners = new HashSet<>(); this.raceIsKnownToStartUpwind = race.getBoatClass().typicallyStartsUpwind(); - if (markPassingCalculator != null) { - logListener.setMarkPassingUpdateListener(markPassingCalculator.getListener()); - } if (!raceIsKnownToStartUpwind) { Set windSourcesToExclude = new HashSet(); for (WindSource windSourceToExclude : getWindSourcesToExclude()) { @@ -135,6 +132,14 @@ DynamicTrackedRace, GPSTrackListener { 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 race's @@ -1011,7 +1016,11 @@ DynamicTrackedRace, GPSTrackListener { @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 diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index 487c6081ce4..8b236db7afb 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -281,7 +281,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl private transient ConcurrentHashMap> directionFromStartToNextMarkCache; - protected final MarkPassingCalculator markPassingCalculator; + protected transient MarkPassingCalculator markPassingCalculator; + private final boolean hasMarkPassingCalculator; private final ConcurrentHashMap> 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 diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch index 82f8aab22d4..2bd988c6083 100644 --- a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch @@ -72,7 +72,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsPresenter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsPresenter.java index f78b38ca1f1..97ca4c126e7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsPresenter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsPresenter.java @@ -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(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsView.java index b59ca898648..0c1da6e94cc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsView.java @@ -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); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsViewImpl.java index 9e371f2fee1..6353e4ac988 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsViewImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/detailstab/UserProfileDetailsViewImpl.java @@ -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)); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java index d4938a0a812..1a9c673c17d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java @@ -242,7 +242,7 @@ public abstract class AbstractRegattaWithSeriesAndFleetsDialog 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 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; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java index 582df7eb5af..2b996f96f4c 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java @@ -45,6 +45,7 @@ public class CompetitorEditDialog extends DataEntryDialog { 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 { * 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 null 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 callback, String boatClass) { @@ -102,6 +103,7 @@ public class CompetitorEditDialog extends DataEntryDialog { 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 { 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 { 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; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java index 62cbcea7a3b..5e309807bf3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java @@ -170,6 +170,20 @@ public class CompetitorTableWrapper competitorSearchTagColumn = new TextColumn() { + @Override + public String getValue(CompetitorDTO competitor) { + return competitor.getSearchTag(); + } + }; + competitorSearchTagColumn.setSortable(true); + competitorColumnListHandler.setComparator(competitorSearchTagColumn, new Comparator() { + @Override + public int compare(CompetitorDTO o1, CompetitorDTO o2) { + return new NaturalComparator(false).compare(o1.getSearchTag(), o2.getSearchTag()); + } + }); + TextColumn timeOnTimeFactorColumn = new TextColumn() { @Override public String getValue(CompetitorDTO competitor) { @@ -212,6 +226,7 @@ public class CompetitorTableWrapper { + + public CourseAreaListInlineEditorComposite(Iterable initialValues, + ListEditorUiStrategy activeUi) { + super(initialValues, activeUi); + } + + public CourseAreaListInlineEditorComposite(Iterable initialValues, StringMessages stringMessages, + ImageResource removeImage, List suggestValues, int textBoxSize) { + super(initialValues, stringMessages, removeImage, suggestValues, textBoxSize); + } + + public static class CollapsedUi extends GenericStringListEditorComposite.CollapsedUi { + public CollapsedUi(StringMessages stringMessages, String dialogTitle, ExpandedListEditorUi expandedUi) { + super(stringMessages, dialogTitle, expandedUi); + } + + @Override + protected ListEditorComposite createExpandedUi(Iterable initialValues, ExpandedListEditorUi 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(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventCreateDialog.java index 51c16288695..8f326c00669 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventCreateDialog.java @@ -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.emptyList()); videosListComposite.fillVideos(Collections.emptyList()); // add default course area - courseAreaNameList.setValue(Collections.singletonList("Default")); + courseAreaNameList.setValue(Collections.singletonList(new CourseAreaDTO("Default"))); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java index 1599a5dda38..f9a3ab586d7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java @@ -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 protected UUID id; protected TextBox officialWebsiteURLEntryField; protected Map sailorsInfoWebsiteURLEntryFields = new HashMap<>(); - protected StringListInlineEditorComposite courseAreaNameList; + protected CourseAreaListInlineEditorComposite courseAreaNameList; protected StringConstantsListEditorComposite leaderboardGroupList; protected Map availableLeaderboardGroupsByName; - protected ImagesListComposite imagesListComposite; - protected VideosListComposite videosListComposite; - + protected ImagesListComposite imagesListComposite; + protected VideosListComposite videosListComposite; + protected static class EventParameterValidator implements Validator { private StringMessages stringMessages; @@ -76,8 +76,9 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap 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 validate(); } }; + final ValueChangeHandler> courseAreaValueChangeHandler = new ValueChangeHandler>() { + @Override + public void onValueChange(ValueChangeEvent> event) { + validate(); + } + }; - courseAreaNameList = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ + courseAreaNameList = new CourseAreaListInlineEditorComposite(Collections. emptyList(), + new GenericStringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ SuggestedCourseAreaNames.suggestedCourseAreaNames, stringMessages.enterCourseAreaName(), 50)); - courseAreaNameList.addValueChangeHandler(valueChangeHandler); + courseAreaNameList.addValueChangeHandler(courseAreaValueChangeHandler); List leaderboardGroupNames = new ArrayList<>(); for(LeaderboardGroupDTO leaderboardGroupDTO: availableLeaderboardGroups) { leaderboardGroupNames.add(leaderboardGroupDTO.getName()); @@ -178,16 +185,11 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap result.endDate = endDateBox.getValue(); result.isPublic = isPublicCheckBox.getValue(); result.id = id; - List courseAreas = new ArrayList(); - for (String courseAreaName : courseAreaNameList.getValue()) { - CourseAreaDTO courseAreaDTO = new CourseAreaDTO(); - courseAreaDTO.setName(courseAreaName); - courseAreas.add(courseAreaDTO); - } - for (ImageDTO image: imagesListComposite.getAllImages()) { + List 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); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventEditDialog.java index e0e4e169d1b..60989b5a63f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventEditDialog.java @@ -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 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 leaderboardGroupNames = new ArrayList<>(); for(LeaderboardGroupDTO leaderboardGroupDTO: event.getLeaderboardGroups()) { leaderboardGroupNames.add(leaderboardGroupDTO.getName()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardDialog.java index 5b3087f60f5..cf80c7b6e04 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardDialog.java @@ -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; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageDialog.java index a910f0f54b8..b6c79623306 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageDialog.java @@ -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 { }); tagsListEditor = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ + new GenericStringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ MediaConstants.imageTagSuggestions, "Enter tags for the image", 30)); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java index 37c769e6c8a..5e5a0d1952c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java @@ -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 { return selectedSeries; } - private class RaceNamesEditorUi extends StringListInlineEditorComposite.ExpandedUi { + private class RaceNamesEditorUi extends GenericStringListInlineEditorComposite.ExpandedUi { private final RegattaDTO regatta; private final ListBox addRacesFromListBox; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java index e6f83f32fa4..09b27b6be3a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java @@ -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 courseStateColumn = new TextColumn() { + @Override + public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality raceColumnAndFleetName) { + return doesCourseExist(raceColumnAndFleetName) ? stringMessages.ok() : stringMessages.none(); + } + }; + raceActionColumn = new ImagesBarColumn( 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"); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/VideoDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/VideoDialog.java index 4e6dd34566b..e531c1754bd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/VideoDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/VideoDialog.java @@ -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 { }); thumbnailURLAndUploadComposite = new URLFieldWithFileUpload(stringMessages); tagsListEditor = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ + new GenericStringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ MediaConstants.videoTagSuggestions, "Enter tags for the video", 50)); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index e6991021c58..7542b21290d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -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(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 018755ac805..6d693b221cb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -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 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index ca4c9d6eb77..80977349b2c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -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. diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties index 94234b387e1..f326f873061 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties @@ -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=将设备映射到参赛队和标志 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties index 2695ce2a71b..8965d3606a4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties @@ -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=将设备映射到参赛队和标志 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 7c042a80084..fd8c29a3dc2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -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; } /** diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/CourseAreaDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/CourseAreaDTO.java index 519fef52db8..0e7efe510df 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/CourseAreaDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/CourseAreaDTO.java @@ -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; + } } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java index b83bd571c31..7506506df8c 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java @@ -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); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java index 488ef888b67..779f51c9c60 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java @@ -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); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreCompetitorTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreCompetitorTest.java index 2f140adbb70..58a0b750a91 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreCompetitorTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreCompetitorTest.java @@ -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 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 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())); + } +} diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java index 400ab63fffd..9350703e2f4 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java @@ -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); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index 4e4a559b722..197c9e784a6 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -820,7 +820,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); List competitors = new ArrayList(); - 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 waypoints = Collections.emptyList(); Course course = new CourseImpl("Course", waypoints); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index 2d42c374a28..5c477d975cc 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -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); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java index 1c125627097..768991ec3ce 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java @@ -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; } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java index 69fceafcff4..8bd6033f7e4 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java @@ -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)); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java index 046d7bf82bf..796528a1c40 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java @@ -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); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java index 770acae35f6..c9985c042e7 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java @@ -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. emptyList(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 10000, new DynamicRaceDefinitionSet() { diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/MarkDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/MarkDeserializer.java index 6e9e649d69f..841b66ffa94 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/MarkDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/MarkDeserializer.java @@ -31,7 +31,6 @@ public class MarkDeserializer implements JsonDeserializer { 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; } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java index 9fffd40b1de..18cccebf0cb 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java @@ -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 { - protected final CompetitorFactory competitorStore; - protected final JsonDeserializer teamJsonDeserializer; - protected final JsonDeserializer 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 teamJsonDeserializer, JsonDeserializer 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 { + protected final CompetitorFactory competitorStore; + protected final JsonDeserializer teamJsonDeserializer; + protected final JsonDeserializer 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 teamJsonDeserializer, JsonDeserializer 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); + } + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/Helpers.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/Helpers.java index 6762c862c3e..b7bc8ebccdb 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/Helpers.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/Helpers.java @@ -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()); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java index 57cdd52907f..a7809bbed07 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java @@ -55,6 +55,7 @@ public class CompetitorJsonSerializer implements JsonSerializer { 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()); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index f47dd00c129..ea6d4a1f70f 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -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 flagEventSerializer; - private JsonSerializer startTimeSerializer; - private JsonSerializer raceStatusSerializer; - private JsonSerializer courseAreaChangedEventSerializer; - private JsonSerializer passChangedSerializer; - private JsonSerializer courseDesignChangedEventSerializer; - private JsonSerializer finishPositioningListChangedEventSerializer; - private JsonSerializer finishPositioningConfirmedEventSerializer; - private JsonSerializer pathfinderEventSerializer; - private JsonSerializer gateLineOpeningTimeEventSerializer; - private JsonSerializer startProcedureTypeChangedEventSerializer; - private JsonSerializer protestStartTimeEventSerializer; - private JsonSerializer windFixEventSerializer; - private JsonSerializer denoteForTrackingEventSerializer; - private JsonSerializer startTrackingEventSerializer; - private JsonSerializer revokeEventSerializer; - private JsonSerializer registerCompetitorEventSerializer; - private JsonSerializer additionalScoringInformationSerializer; - private JsonSerializer fixedMarkPassingEventSerializer; - private JsonSerializer suppressedMarkPassingsSerializer; - private JsonSerializer dependentStartTimeEventSerializer; - private JsonSerializer startOfTrackingEventSerializer; - private JsonSerializer useCompetitorsFromRaceLogEventSerializer; - private JsonSerializer 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 flagEventSerializer; + private JsonSerializer startTimeSerializer; + private JsonSerializer raceStatusSerializer; + private JsonSerializer courseAreaChangedEventSerializer; + private JsonSerializer passChangedSerializer; + private JsonSerializer courseDesignChangedEventSerializer; + private JsonSerializer finishPositioningListChangedEventSerializer; + private JsonSerializer finishPositioningConfirmedEventSerializer; + private JsonSerializer pathfinderEventSerializer; + private JsonSerializer gateLineOpeningTimeEventSerializer; + private JsonSerializer startProcedureTypeChangedEventSerializer; + private JsonSerializer protestStartTimeEventSerializer; + private JsonSerializer windFixEventSerializer; + private JsonSerializer denoteForTrackingEventSerializer; + private JsonSerializer startTrackingEventSerializer; + private JsonSerializer revokeEventSerializer; + private JsonSerializer registerCompetitorEventSerializer; + private JsonSerializer additionalScoringInformationSerializer; + private JsonSerializer fixedMarkPassingEventSerializer; + private JsonSerializer suppressedMarkPassingsSerializer; + private JsonSerializer dependentStartTimeEventSerializer; + private JsonSerializer startOfTrackingEventSerializer; + private JsonSerializer useCompetitorsFromRaceLogEventSerializer; + private JsonSerializer 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); + } +} diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java index 0f03454938e..2909a63f6e2 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java @@ -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 parameters) throws Exception { - HttpServletRequest request = mock(HttpServletRequest.class); - HttpServletResponse response = mock(HttpServletResponse.class); - when(request.getMethod()).thenReturn(GetOrPostMethod); - - if(parameters != null) { - for(Map.Entry 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 createCompetitors(int numberOfCompetitorsToCreate) { - List result = new ArrayList(); - 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 parameters) throws Exception { + HttpServletRequest request = mock(HttpServletRequest.class); + HttpServletResponse response = mock(HttpServletResponse.class); + when(request.getMethod()).thenReturn(GetOrPostMethod); + + if(parameters != null) { + for(Map.Entry 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 createCompetitors(int numberOfCompetitorsToCreate) { + List result = new ArrayList(); + 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; + } +} diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java index 96928919c5c..4af70af38be 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java @@ -1,92 +1,92 @@ -package com.sap.sailing.server.gateway.test.jaxrs; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; - -import java.io.UnsupportedEncodingException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -import javax.ws.rs.core.Response; - -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.NationalityImpl; -import com.sap.sailing.domain.base.impl.PersonImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; -import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneUuidServiceFinderFactory; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; -import com.sap.sailing.server.impl.RacingEventServiceImpl; -import com.sap.sse.common.Color; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.mongodb.MongoDBConfiguration; -import com.sap.sse.mongodb.MongoDBService; - -public abstract class AbstractJaxRsApiTest { - protected RacingEventService racingEventService; - protected MongoDBService service; - - protected static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - - public void setUp() { - service = MongoDBConfiguration.getDefaultTestConfiguration().getService(); - service.getDB().dropDatabase(); - - racingEventService = new RacingEventServiceImpl(true, new MockSmartphoneUuidServiceFinderFactory()); - } - - protected T spyResource(T resource) { - T spyResource = spy(resource); - - doReturn(racingEventService).when(spyResource).getService(); - return spyResource; - } - - protected String decodeResponseFromByteArray(Response response) throws UnsupportedEncodingException { - byte[] entity = (byte[]) response.getEntity(); - - return new String(entity, "UTF-8"); - } - - protected TimePoint parseTimepointFromJsonNumber(Long timePointAsJsonNumber) throws ParseException { - TimePoint result = null; - if(timePointAsJsonNumber != null) { - result = new MillisecondsTimePoint(timePointAsJsonNumber); - } - return result; - } - - protected TimePoint parseTimepointFromJsonString(String timePointAsJsonString) throws ParseException { - TimePoint result = null; - if(timePointAsJsonString != null && !timePointAsJsonString.isEmpty()) { - Date date = TIMEPOINT_FORMATTER.parse(timePointAsJsonString); - result = new MillisecondsTimePoint(date); - } - return result; - } - - protected List createCompetitors(int numberOfCompetitorsToCreate) { - List result = new ArrayList(); - BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); - for (int i = 1; i <= numberOfCompetitorsToCreate; i++) { - String competitorName = "C" + i; - Competitor competitor = new CompetitorImpl(new Integer(i), competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton( - new PersonImpl(competitorName, new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous "+competitorName)), - new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", - boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); - result.add(competitor); - } - return result; - } -} +package com.sap.sailing.server.gateway.test.jaxrs; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import java.io.UnsupportedEncodingException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import javax.ws.rs.core.Response; + +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.NationalityImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; +import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneUuidServiceFinderFactory; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; +import com.sap.sailing.server.impl.RacingEventServiceImpl; +import com.sap.sse.common.Color; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.mongodb.MongoDBConfiguration; +import com.sap.sse.mongodb.MongoDBService; + +public abstract class AbstractJaxRsApiTest { + protected RacingEventService racingEventService; + protected MongoDBService service; + + protected static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + + public void setUp() { + service = MongoDBConfiguration.getDefaultTestConfiguration().getService(); + service.getDB().dropDatabase(); + + racingEventService = new RacingEventServiceImpl(true, new MockSmartphoneUuidServiceFinderFactory()); + } + + protected T spyResource(T resource) { + T spyResource = spy(resource); + + doReturn(racingEventService).when(spyResource).getService(); + return spyResource; + } + + protected String decodeResponseFromByteArray(Response response) throws UnsupportedEncodingException { + byte[] entity = (byte[]) response.getEntity(); + + return new String(entity, "UTF-8"); + } + + protected TimePoint parseTimepointFromJsonNumber(Long timePointAsJsonNumber) throws ParseException { + TimePoint result = null; + if(timePointAsJsonNumber != null) { + result = new MillisecondsTimePoint(timePointAsJsonNumber); + } + return result; + } + + protected TimePoint parseTimepointFromJsonString(String timePointAsJsonString) throws ParseException { + TimePoint result = null; + if(timePointAsJsonString != null && !timePointAsJsonString.isEmpty()) { + Date date = TIMEPOINT_FORMATTER.parse(timePointAsJsonString); + result = new MillisecondsTimePoint(date); + } + return result; + } + + protected List createCompetitors(int numberOfCompetitorsToCreate) { + List result = new ArrayList(); + BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); + for (int i = 1; i <= numberOfCompetitorsToCreate; i++) { + String competitorName = "C" + i; + Competitor competitor = new CompetitorImpl(new Integer(i), competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl(competitorName, new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous "+competitorName)), + new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", + boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + result.add(competitor); + } + return result; + } +} diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java index 7c7892a8860..8892eed8776 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java @@ -1,87 +1,87 @@ -package com.sap.sailing.server.gateway.test.jaxrs; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collections; - -import org.apache.commons.io.IOUtils; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.json.simple.parser.ParseException; -import org.junit.Before; -import org.junit.Test; - -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; -import com.sap.sailing.domain.base.impl.DynamicTeam; -import com.sap.sailing.domain.base.impl.NationalityImpl; -import com.sap.sailing.domain.base.impl.PersonImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; -import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; -import com.sap.sailing.server.gateway.jaxrs.api.CompetitorsResource; -import com.sap.sse.filestorage.FileStorageManagementService; -import com.sap.sse.filestorage.FileStorageService; -import com.sap.sse.filestorage.InvalidPropertiesException; -import com.sap.sse.filestorage.OperationFailedException; -import com.sap.sse.filestorage.testsupport.AmazonS3TestSupport; - -public class CompetitorsResourceTeamImageTest extends AbstractJaxRsApiTest { - private static final String name = "Heiko KRÖGER"; - private static final String id = "af855a56-9726-4a9c-a77e-da955bd289be"; - private static final String boatClassName = "49er"; - private static final String sailID = "GER 1"; - private static final String nationality = "GER"; - private static final String teamImageFile = "Bundesliga2014_Regatta6_eventteaser.jpg"; - - private FileStorageService storageService; - - @Before - public void setUpSubClass() throws InvalidPropertiesException { - super.setUp(); - racingEventService = spy(racingEventService); - storageService = AmazonS3TestSupport.createService(); - FileStorageManagementService fsmsMock = mock(FileStorageManagementService.class); - doReturn(fsmsMock).when(racingEventService).getFileStorageManagementService(); - doReturn(storageService).when(fsmsMock).getActiveFileStorageService(); - DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl( - nationality), null, null)), null); - DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID); - racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, team, boat, - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); - } - - @Test - public void storeAndRemoveTeamImage() throws URISyntaxException, ParseException, MalformedURLException, - IOException, OperationFailedException, InvalidPropertiesException { - //set team image - CompetitorsResource r = spyResource(new CompetitorsResource()); - String fileExtension = teamImageFile.substring(teamImageFile.lastIndexOf("."));; - InputStream stream = getClass().getResourceAsStream("/" + teamImageFile); - - // this is not ideal, as this #available() is not supposed to be used for getting the file size - // however, working with a File() descriptor does not work, as when running via maven/tycho the - // URL has the bundleresource:// scheme instead of file:, which File() can't handle - long length = stream.available(); - - String jsonString = r.setTeamImage(id, stream, fileExtension, length); - - //now download and compare - JSONObject json = (JSONObject) JSONValue.parseWithException(jsonString); - String imageUriString = (String) json.get(DeviceMappingConstants.JSON_TEAM_IMAGE_URI); - URI imageUri = new URI(imageUriString); - - InputStream downloadStream = imageUri.toURL().openStream(); - stream = getClass().getResourceAsStream("/" + teamImageFile); - IOUtils.contentEquals(downloadStream, stream); - - storageService.removeFile(imageUri); - } -} +package com.sap.sailing.server.gateway.test.jaxrs; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.commons.io.IOUtils; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.json.simple.parser.ParseException; +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.base.impl.NationalityImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; +import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; +import com.sap.sailing.server.gateway.jaxrs.api.CompetitorsResource; +import com.sap.sse.filestorage.FileStorageManagementService; +import com.sap.sse.filestorage.FileStorageService; +import com.sap.sse.filestorage.InvalidPropertiesException; +import com.sap.sse.filestorage.OperationFailedException; +import com.sap.sse.filestorage.testsupport.AmazonS3TestSupport; + +public class CompetitorsResourceTeamImageTest extends AbstractJaxRsApiTest { + private static final String name = "Heiko KRÖGER"; + private static final String id = "af855a56-9726-4a9c-a77e-da955bd289be"; + private static final String boatClassName = "49er"; + private static final String sailID = "GER 1"; + private static final String nationality = "GER"; + private static final String teamImageFile = "Bundesliga2014_Regatta6_eventteaser.jpg"; + + private FileStorageService storageService; + + @Before + public void setUpSubClass() throws InvalidPropertiesException { + super.setUp(); + racingEventService = spy(racingEventService); + storageService = AmazonS3TestSupport.createService(); + FileStorageManagementService fsmsMock = mock(FileStorageManagementService.class); + doReturn(fsmsMock).when(racingEventService).getFileStorageManagementService(); + doReturn(storageService).when(fsmsMock).getActiveFileStorageService(); + DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl( + nationality), null, null)), null); + DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID); + racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, team, boat, + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + } + + @Test + public void storeAndRemoveTeamImage() throws URISyntaxException, ParseException, MalformedURLException, + IOException, OperationFailedException, InvalidPropertiesException { + //set team image + CompetitorsResource r = spyResource(new CompetitorsResource()); + String fileExtension = teamImageFile.substring(teamImageFile.lastIndexOf("."));; + InputStream stream = getClass().getResourceAsStream("/" + teamImageFile); + + // this is not ideal, as this #available() is not supposed to be used for getting the file size + // however, working with a File() descriptor does not work, as when running via maven/tycho the + // URL has the bundleresource:// scheme instead of file:, which File() can't handle + long length = stream.available(); + + String jsonString = r.setTeamImage(id, stream, fileExtension, length); + + //now download and compare + JSONObject json = (JSONObject) JSONValue.parseWithException(jsonString); + String imageUriString = (String) json.get(DeviceMappingConstants.JSON_TEAM_IMAGE_URI); + URI imageUri = new URI(imageUriString); + + InputStream downloadStream = imageUri.toURL().openStream(); + stream = getClass().getResourceAsStream("/" + teamImageFile); + IOUtils.contentEquals(downloadStream, stream); + + storageService.removeFile(imageUri); + } +} diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java index f495140b639..9a80d9c972a 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java @@ -1,53 +1,53 @@ -package com.sap.sailing.server.gateway.test.jaxrs; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; - -import java.util.Collections; - -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.junit.Before; -import org.junit.Test; - -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; -import com.sap.sailing.domain.base.impl.DynamicTeam; -import com.sap.sailing.domain.base.impl.NationalityImpl; -import com.sap.sailing.domain.base.impl.PersonImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; -import com.sap.sailing.server.gateway.deserialization.impl.Helpers; -import com.sap.sailing.server.gateway.jaxrs.api.CompetitorsResource; - -public class CompetitorsResourceTest extends AbstractJaxRsApiTest { - private final String name = "Heiko KRÖGER"; - private final String id = "af855a56-9726-4a9c-a77e-da955bd289be"; - private final String boatClassName = "49er"; - private final String sailID = "GER 1"; - private final String nationality = "GER"; - private final String countryCode = "DE"; - - - @Before - public void setUp() { - super.setUp(); - DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl(nationality), null, null)), null); - DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID); - racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); - } - - @Test - public void testExportRegattasAsJson() throws Exception { - CompetitorsResource resource = spyResource(new CompetitorsResource()); - String jsonString = resource.getCompetitor(id).getEntity().toString(); - JSONObject json = Helpers.toJSONObjectSafe(JSONValue.parse(jsonString)); - assertThat("id is correct", json.get("id"), equalTo(id)); - assertThat("name is correct", json.get("name"), equalTo(name)); - assertThat("boatClass is correct", json.get("boatClassName"), equalTo(boatClassName)); - assertThat("sailID is correct", json.get("sailID"), equalTo(sailID)); - assertThat("nationality is correct", json.get("nationality"), equalTo(nationality)); - assertThat("nationality is correct", json.get("countryCode"), equalTo(countryCode)); - } - -} +package com.sap.sailing.server.gateway.test.jaxrs; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +import java.util.Collections; + +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.base.impl.NationalityImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; +import com.sap.sailing.server.gateway.deserialization.impl.Helpers; +import com.sap.sailing.server.gateway.jaxrs.api.CompetitorsResource; + +public class CompetitorsResourceTest extends AbstractJaxRsApiTest { + private final String name = "Heiko KRÖGER"; + private final String id = "af855a56-9726-4a9c-a77e-da955bd289be"; + private final String boatClassName = "49er"; + private final String sailID = "GER 1"; + private final String nationality = "GER"; + private final String countryCode = "DE"; + + + @Before + public void setUp() { + super.setUp(); + DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl(nationality), null, null)), null); + DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID); + racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + } + + @Test + public void testExportRegattasAsJson() throws Exception { + CompetitorsResource resource = spyResource(new CompetitorsResource()); + String jsonString = resource.getCompetitor(id).getEntity().toString(); + JSONObject json = Helpers.toJSONObjectSafe(JSONValue.parse(jsonString)); + assertThat("id is correct", json.get("id"), equalTo(id)); + assertThat("name is correct", json.get("name"), equalTo(name)); + assertThat("boatClass is correct", json.get("boatClassName"), equalTo(boatClassName)); + assertThat("sailID is correct", json.get("sailID"), equalTo(sailID)); + assertThat("nationality is correct", json.get("nationality"), equalTo(nationality)); + assertThat("nationality is correct", json.get("countryCode"), equalTo(countryCode)); + } + +} diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java index ce41334c142..23f3daff110 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java @@ -1,106 +1,106 @@ -package com.sap.sailing.server.gateway.test.jaxrs; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import javax.ws.rs.core.Response; - -import org.json.simple.JSONObject; -import org.junit.Before; -import org.junit.Test; - -import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceCompetitorMappingFinder; -import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; -import com.sap.sailing.domain.base.impl.DynamicTeam; -import com.sap.sailing.domain.base.impl.FleetImpl; -import com.sap.sailing.domain.base.impl.RegattaImpl; -import com.sap.sailing.domain.base.impl.SeriesImpl; -import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; -import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.leaderboard.impl.HighPoint; -import com.sap.sailing.domain.racelogtracking.DeviceMapping; -import com.sap.sailing.domain.racelogtracking.SmartphoneUUIDIdentifier; -import com.sap.sailing.domain.ranking.OneDesignRankingMetric; -import com.sap.sailing.server.gateway.jaxrs.api.LeaderboardsResource; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest { - private Competitor competitor; - private RegattaLog log; - private RegattaLeaderboard leaderboard; - - @Before - public void setUp() { - super.setUp(); - Competitor c = createCompetitors(1).get(0); - competitor = racingEventService.getBaseDomainFactory().getOrCreateCompetitor(c.getId(), c.getName(), - c.getColor(), c.getEmail(), c.getFlagImage(), (DynamicTeam) c.getTeam(), (DynamicBoat) c.getBoat(), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); - Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), MillisecondsTimePoint.now(), - MillisecondsTimePoint.now(), Collections.singleton(new SeriesImpl("series", false, Collections - .singleton(new FleetImpl("fleet")), Arrays.asList("column"), racingEventService)), false, - new HighPoint(), 0, null, OneDesignRankingMetric::new); - racingEventService.addRegattaWithoutReplication(regatta); - leaderboard = racingEventService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "regatta", new int[] {}); - regatta.registerCompetitor(competitor); - log = leaderboard.getRegattaLike().getRegattaLog(); - } - - @Test - public void testCheckinAndCheckout() throws Exception { - LeaderboardsResource resource = spyResource(new LeaderboardsResource()); - UUID deviceUuid = UUID.randomUUID(); - - // checkin - long fromMillis = 500; - JSONObject json = new JSONObject(); - json.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitor.getId().toString()); - json.put(DeviceMappingConstants.JSON_DEVICE_UUID, deviceUuid.toString()); - json.put(DeviceMappingConstants.JSON_FROM_MILLIS, fromMillis); - - Response response = resource.postCheckin(json.toString(), leaderboard.getName()); - assertThat("checkin returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode())); - - Set registeredCompetitors = new CompetitorsInLogAnalyzer<>(log).analyze(); - Map>> mappings = new RegattaLogDeviceCompetitorMappingFinder(log).analyze(); - - assertThat("competitor was registered", registeredCompetitors.size(), equalTo(1)); - assertThat("device mappings for competitor exist", mappings.size(), equalTo(1)); - List> mappingsForC = mappings.get(competitor); - assertThat("exactly one device mapping for competitor exists", mappingsForC.size(), equalTo(1)); - DeviceMapping mappingForC = mappingsForC.get(0); - assertThat("that mapping is for the correct device", - ((SmartphoneUUIDIdentifier) mappingForC.getDevice()).getUUID(), equalTo(deviceUuid)); - assertThat("that mapping starts at the correct timepoint", mappingForC.getTimeRange().from().asMillis(), - equalTo(fromMillis)); - assertThat("that mapping is open-ended", mappingForC.getTimeRange().hasOpenEnd(), equalTo(true)); - - // checkout - long toMillis = 1000; - json = new JSONObject(); - json.put(DeviceMappingConstants.JSON_TO_MILLIS, toMillis); - json.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitor.getId().toString()); - json.put(DeviceMappingConstants.JSON_DEVICE_UUID, deviceUuid.toString()); - - response = resource.postCheckout(json.toString(), leaderboard.getName()); - assertThat("checkout returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode())); - - mappings = new RegattaLogDeviceCompetitorMappingFinder(log).analyze(); - mappingForC = mappings.get(competitor).get(0); - assertThat("mapping now ends at checkout timepoint", mappingForC.getTimeRange().to().asMillis(), - equalTo(toMillis)); - } - -} +package com.sap.sailing.server.gateway.test.jaxrs; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import javax.ws.rs.core.Response; + +import org.json.simple.JSONObject; +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceCompetitorMappingFinder; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.base.impl.FleetImpl; +import com.sap.sailing.domain.base.impl.RegattaImpl; +import com.sap.sailing.domain.base.impl.SeriesImpl; +import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.impl.HighPoint; +import com.sap.sailing.domain.racelogtracking.DeviceMapping; +import com.sap.sailing.domain.racelogtracking.SmartphoneUUIDIdentifier; +import com.sap.sailing.domain.ranking.OneDesignRankingMetric; +import com.sap.sailing.server.gateway.jaxrs.api.LeaderboardsResource; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest { + private Competitor competitor; + private RegattaLog log; + private RegattaLeaderboard leaderboard; + + @Before + public void setUp() { + super.setUp(); + Competitor c = createCompetitors(1).get(0); + competitor = racingEventService.getBaseDomainFactory().getOrCreateCompetitor(c.getId(), c.getName(), + c.getColor(), c.getEmail(), c.getFlagImage(), (DynamicTeam) c.getTeam(), (DynamicBoat) c.getBoat(), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), MillisecondsTimePoint.now(), + MillisecondsTimePoint.now(), Collections.singleton(new SeriesImpl("series", false, Collections + .singleton(new FleetImpl("fleet")), Arrays.asList("column"), racingEventService)), false, + new HighPoint(), 0, null, OneDesignRankingMetric::new); + racingEventService.addRegattaWithoutReplication(regatta); + leaderboard = racingEventService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "regatta", new int[] {}); + regatta.registerCompetitor(competitor); + log = leaderboard.getRegattaLike().getRegattaLog(); + } + + @Test + public void testCheckinAndCheckout() throws Exception { + LeaderboardsResource resource = spyResource(new LeaderboardsResource()); + UUID deviceUuid = UUID.randomUUID(); + + // checkin + long fromMillis = 500; + JSONObject json = new JSONObject(); + json.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitor.getId().toString()); + json.put(DeviceMappingConstants.JSON_DEVICE_UUID, deviceUuid.toString()); + json.put(DeviceMappingConstants.JSON_FROM_MILLIS, fromMillis); + + Response response = resource.postCheckin(json.toString(), leaderboard.getName()); + assertThat("checkin returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode())); + + Set registeredCompetitors = new CompetitorsInLogAnalyzer<>(log).analyze(); + Map>> mappings = new RegattaLogDeviceCompetitorMappingFinder(log).analyze(); + + assertThat("competitor was registered", registeredCompetitors.size(), equalTo(1)); + assertThat("device mappings for competitor exist", mappings.size(), equalTo(1)); + List> mappingsForC = mappings.get(competitor); + assertThat("exactly one device mapping for competitor exists", mappingsForC.size(), equalTo(1)); + DeviceMapping mappingForC = mappingsForC.get(0); + assertThat("that mapping is for the correct device", + ((SmartphoneUUIDIdentifier) mappingForC.getDevice()).getUUID(), equalTo(deviceUuid)); + assertThat("that mapping starts at the correct timepoint", mappingForC.getTimeRange().from().asMillis(), + equalTo(fromMillis)); + assertThat("that mapping is open-ended", mappingForC.getTimeRange().hasOpenEnd(), equalTo(true)); + + // checkout + long toMillis = 1000; + json = new JSONObject(); + json.put(DeviceMappingConstants.JSON_TO_MILLIS, toMillis); + json.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitor.getId().toString()); + json.put(DeviceMappingConstants.JSON_DEVICE_UUID, deviceUuid.toString()); + + response = resource.postCheckout(json.toString(), leaderboard.getName()); + assertThat("checkout returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode())); + + mappings = new RegattaLogDeviceCompetitorMappingFinder(log).analyze(); + mappingForC = mappings.get(competitor).get(0); + assertThat("mapping now ends at checkout timepoint", mappingForC.getTimeRange().to().asMillis(), + equalTo(toMillis)); + } + +} diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusHtmlServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusHtmlServlet.java index c2cf479f793..dde74376cdb 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusHtmlServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusHtmlServlet.java @@ -54,10 +54,10 @@ public class WindStatusHtmlServlet extends WindStatusServlet implements IgtimiWi TimePoint latestTimePoint = copyOfLastIgtimiMessages.peek().getWind().getTimePoint(); long lastFixDiffInMs = System.currentTimeMillis() - latestTimePoint.asMillis(); out.println("    Last fix:"); - if(lastFixDiffInMs / 1000 < 60) { + if (lastFixDiffInMs / 1000 < 60) { out.println(lastFixDiffInMs / 1000 +"s ago"); } else { - out.println("" + lastFixDiffInMs / 1000 +"min ago"); + out.println("" + lastFixDiffInMs / 1000 / 60 +"min ago"); } } out.println("
"); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java index 15d50f2e66e..0606a8301d6 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java @@ -165,7 +165,8 @@ public class CompetitorsResource extends AbstractSailingServerResource { } getService().getCompetitorStore().updateCompetitor(competitorId, competitor.getName(), competitor.getColor(), competitor.getEmail(), - competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), imageUri, competitor.getFlagImage(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), imageUri, competitor.getFlagImage(), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, competitor.getSearchTag()); logger.log(Level.INFO, "Set team image for competitor " + competitor.getName()); JSONObject result = new JSONObject(); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java index a8db72dc5c7..cdd5f64d38a 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java @@ -1,138 +1,139 @@ -package com.sap.sailing.server.replication.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collections; - -import org.junit.Test; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CourseImpl; -import com.sap.sailing.domain.base.impl.NationalityImpl; -import com.sap.sailing.domain.base.impl.PersonImpl; -import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; -import com.sap.sailing.domain.base.impl.RegattaImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.RegattaName; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.impl.DegreeBearingImpl; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; -import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; -import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; -import com.sap.sailing.domain.ranking.OneDesignRankingMetric; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.impl.EmptyWindStore; -import com.sap.sailing.server.operationaltransformation.AddRaceDefinition; -import com.sap.sailing.server.operationaltransformation.AllowCompetitorResetToDefaults; -import com.sap.sailing.server.operationaltransformation.CreateTrackedRace; -import com.sap.sailing.server.operationaltransformation.UpdateCompetitor; -import com.sap.sse.common.Color; -import com.sap.sse.common.Util; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -/** - * Tests replication of competitors in conjunction with the {@link CompetitorStore} concepts, particularly the - * possibility to allow for competitor data to be updated, either explicitly or implicitly from a tracking provider - * after marking the competitor using - * {@link CompetitorStore#allowCompetitorResetToDefaults(com.sap.sailing.domain.base.Competitor)}. - * - * @author Axel Uhl (d043530) - * - */ -public class CompetitorReplicationTest extends AbstractServerReplicationTest { - /** - * Add a tracked race to the master that includes a competitor; check that the competitor was properly replicated to - * the replica's {@link CompetitorStore}. Afterwards, use the {@link UpdateCompetitor} operation on the master to - * perform an explicit update; ensure that the update arrived on the replica. Then execute an - * {@link AllowCompetitorResetToDefaults} operation on the master, afterwards update the competitor on the master, - * then force some competitor-related event to be sent to the replica, such as a GPS fix update. This will serialize - * the competitor with its modified state over to the replica where a - * {@link DomainFactory#getOrCreateCompetitor(java.io.Serializable, String, com.sap.sailing.domain.base.impl.DynamicTeam, com.sap.sailing.domain.base.impl.DynamicBoat)} - * will be triggered. This should also update the competitor on the client. - * @throws URISyntaxException - */ - @Test - public void testSimpleSpecificRegattaReplication() throws InterruptedException, URISyntaxException { - String baseEventName = "My Test Event"; - String boatClassName = "Kielzugvogel"; - Integer regattaId = 12345; - URI flagImageURI = new URI("http://www.sapsailing.com"); - Iterable series = Collections.emptyList(); - Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, - /*startDate*/ null, /*endDate*/ null, regattaId, series, - /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /* useStartTimeInference */ true, OneDesignRankingMetric::new); - Iterable emptyWaypointList = Collections.emptyList(); - final String competitorName = "Der mit dem Kiel zieht"; - Competitor competitor = master.getBaseDomainFactory().getOrCreateCompetitor( - 123, competitorName, Color.RED, "someone@nowhere.de", flagImageURI, - new TeamImpl("STG", Collections.singleton(new PersonImpl(competitorName, new NationalityImpl("GER"), - /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", - new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), - new BoatImpl(competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null); - Iterable competitors = Collections.singleton(competitor); - final String raceName = "Test Race"; - RaceDefinition raceDefinition = new RaceDefinitionImpl(raceName, new CourseImpl("Empty Course", emptyWaypointList), - masterRegatta.getBoatClass(), competitors); - master.apply(new AddRaceDefinition(masterRegatta.getRegattaIdentifier(), raceDefinition)); - Thread.sleep(1000); - Regatta replicatedRegatta = replica.getRegatta(new RegattaName(masterRegatta.getName())); - assertNotNull(replicatedRegatta); - assertTrue(replicatedRegatta.isPersistent()); - assertTrue(Util.isEmpty((replicatedRegatta.getSeries()))); - assertNull(replicatedRegatta.getDefaultCourseArea()); - assertTrue(regattaId.equals(replicatedRegatta.getId())); - RaceDefinition replicatedRace = replicatedRegatta.getRaceByName(raceName); - assertNotNull(replicatedRace); - Competitor replicatedCompetitor = replicatedRace.getCompetitors().iterator().next(); - assertNotSame(replicatedCompetitor, competitor); - assertEquals(competitor.getId(), replicatedCompetitor.getId()); - assertEquals(competitor.getName(), replicatedCompetitor.getName()); - assertEquals(competitor.getColor(), replicatedCompetitor.getColor()); - assertEquals(competitor.getFlagImage(), replicatedCompetitor.getFlagImage()); - assertEquals(competitor.getBoat().getSailID(), replicatedCompetitor.getBoat().getSailID()); - assertEquals(competitor.getTeam().getNationality(), replicatedCompetitor.getTeam().getNationality()); - - // now update competitor on master using replicating operation - final String newCompetitorName = "Der Vogel, der mit dem Kiel zieht"; - master.apply(new UpdateCompetitor(competitor.getId().toString(), newCompetitorName, competitor.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), - competitor.getTeam().getImage(), competitor.getFlagImage(), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); - Thread.sleep(1000); - assertEquals(newCompetitorName, replicatedCompetitor.getName()); // expect in-place update of existing competitor in replica - - // now allow for resetting to default through some event, such as receiving a GPS position - master.apply(new AllowCompetitorResetToDefaults(Collections.singleton(competitor.getId().toString()))); - // modify the competitor on the master "from below" without an UpdateCompetitor operation, only locally: - master.getBaseDomainFactory().getCompetitorStore().updateCompetitor(competitor.getId().toString(), competitorName, Color.RED, competitor.getEmail(), - competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); - final RegattaAndRaceIdentifier raceIdentifier = masterRegatta.getRaceIdentifier(raceDefinition); - DynamicTrackedRace trackedRace = (DynamicTrackedRace) master.apply(new CreateTrackedRace(raceIdentifier, - EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 3000, - /* millisecondsOverWhichToAverageWind */ 30000l, /* millisecondsOverWhichToAverageSpeed */ 30000l)); - trackedRace.getTrack(competitor).addGPSFix(new GPSFixMovingImpl(new DegreePosition(49.425, 8.293), MillisecondsTimePoint.now(), - new KnotSpeedWithBearingImpl(12.3, new DegreeBearingImpl(242.3)))); - Thread.sleep(1000); - TrackedRace replicatedTrackedRace = replica.getTrackedRace(raceIdentifier); - assertNotNull(replicatedTrackedRace); - assertNotNull(replicatedTrackedRace.getTrack(replicatedCompetitor).getFirstRawFix()); - assertEquals(competitorName, replicatedCompetitor.getName()); - } +package com.sap.sailing.server.replication.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.junit.Test; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CourseImpl; +import com.sap.sailing.domain.base.impl.NationalityImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; +import com.sap.sailing.domain.base.impl.RegattaImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.RegattaName; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.impl.DegreeBearingImpl; +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; +import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; +import com.sap.sailing.domain.ranking.OneDesignRankingMetric; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.impl.EmptyWindStore; +import com.sap.sailing.server.operationaltransformation.AddRaceDefinition; +import com.sap.sailing.server.operationaltransformation.AllowCompetitorResetToDefaults; +import com.sap.sailing.server.operationaltransformation.CreateTrackedRace; +import com.sap.sailing.server.operationaltransformation.UpdateCompetitor; +import com.sap.sse.common.Color; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +/** + * Tests replication of competitors in conjunction with the {@link CompetitorStore} concepts, particularly the + * possibility to allow for competitor data to be updated, either explicitly or implicitly from a tracking provider + * after marking the competitor using + * {@link CompetitorStore#allowCompetitorResetToDefaults(com.sap.sailing.domain.base.Competitor)}. + * + * @author Axel Uhl (d043530) + * + */ +public class CompetitorReplicationTest extends AbstractServerReplicationTest { + /** + * Add a tracked race to the master that includes a competitor; check that the competitor was properly replicated to + * the replica's {@link CompetitorStore}. Afterwards, use the {@link UpdateCompetitor} operation on the master to + * perform an explicit update; ensure that the update arrived on the replica. Then execute an + * {@link AllowCompetitorResetToDefaults} operation on the master, afterwards update the competitor on the master, + * then force some competitor-related event to be sent to the replica, such as a GPS fix update. This will serialize + * the competitor with its modified state over to the replica where a + * {@link DomainFactory#getOrCreateCompetitor(java.io.Serializable, String, com.sap.sailing.domain.base.impl.DynamicTeam, com.sap.sailing.domain.base.impl.DynamicBoat)} + * will be triggered. This should also update the competitor on the client. + * @throws URISyntaxException + */ + @Test + public void testSimpleSpecificRegattaReplication() throws InterruptedException, URISyntaxException { + String baseEventName = "My Test Event"; + String boatClassName = "Kielzugvogel"; + Integer regattaId = 12345; + URI flagImageURI = new URI("http://www.sapsailing.com"); + Iterable series = Collections.emptyList(); + Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, + /*startDate*/ null, /*endDate*/ null, regattaId, series, + /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + Iterable emptyWaypointList = Collections.emptyList(); + final String competitorName = "Der mit dem Kiel zieht"; + Competitor competitor = master.getBaseDomainFactory().getOrCreateCompetitor( + 123, competitorName, Color.RED, "someone@nowhere.de", flagImageURI, + new TeamImpl("STG", Collections.singleton(new PersonImpl(competitorName, new NationalityImpl("GER"), + /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", + new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), + new BoatImpl(competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + Iterable competitors = Collections.singleton(competitor); + final String raceName = "Test Race"; + RaceDefinition raceDefinition = new RaceDefinitionImpl(raceName, new CourseImpl("Empty Course", emptyWaypointList), + masterRegatta.getBoatClass(), competitors); + master.apply(new AddRaceDefinition(masterRegatta.getRegattaIdentifier(), raceDefinition)); + Thread.sleep(1000); + Regatta replicatedRegatta = replica.getRegatta(new RegattaName(masterRegatta.getName())); + assertNotNull(replicatedRegatta); + assertTrue(replicatedRegatta.isPersistent()); + assertTrue(Util.isEmpty((replicatedRegatta.getSeries()))); + assertNull(replicatedRegatta.getDefaultCourseArea()); + assertTrue(regattaId.equals(replicatedRegatta.getId())); + RaceDefinition replicatedRace = replicatedRegatta.getRaceByName(raceName); + assertNotNull(replicatedRace); + Competitor replicatedCompetitor = replicatedRace.getCompetitors().iterator().next(); + assertNotSame(replicatedCompetitor, competitor); + assertEquals(competitor.getId(), replicatedCompetitor.getId()); + assertEquals(competitor.getName(), replicatedCompetitor.getName()); + assertEquals(competitor.getColor(), replicatedCompetitor.getColor()); + assertEquals(competitor.getFlagImage(), replicatedCompetitor.getFlagImage()); + assertEquals(competitor.getBoat().getSailID(), replicatedCompetitor.getBoat().getSailID()); + assertEquals(competitor.getTeam().getNationality(), replicatedCompetitor.getTeam().getNationality()); + + // now update competitor on master using replicating operation + final String newCompetitorName = "Der Vogel, der mit dem Kiel zieht"; + master.apply(new UpdateCompetitor(competitor.getId().toString(), newCompetitorName, competitor.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), + competitor.getTeam().getImage(), competitor.getFlagImage(), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + Thread.sleep(1000); + assertEquals(newCompetitorName, replicatedCompetitor.getName()); // expect in-place update of existing competitor in replica + + // now allow for resetting to default through some event, such as receiving a GPS position + master.apply(new AllowCompetitorResetToDefaults(Collections.singleton(competitor.getId().toString()))); + // modify the competitor on the master "from below" without an UpdateCompetitor operation, only locally: + master.getBaseDomainFactory().getCompetitorStore().updateCompetitor(competitor.getId().toString(), competitorName, Color.RED, competitor.getEmail(), + competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + final RegattaAndRaceIdentifier raceIdentifier = masterRegatta.getRaceIdentifier(raceDefinition); + DynamicTrackedRace trackedRace = (DynamicTrackedRace) master.apply(new CreateTrackedRace(raceIdentifier, + EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 3000, + /* millisecondsOverWhichToAverageWind */ 30000l, /* millisecondsOverWhichToAverageSpeed */ 30000l)); + trackedRace.getTrack(competitor).addGPSFix(new GPSFixMovingImpl(new DegreePosition(49.425, 8.293), MillisecondsTimePoint.now(), + new KnotSpeedWithBearingImpl(12.3, new DegreeBearingImpl(242.3)))); + Thread.sleep(1000); + TrackedRace replicatedTrackedRace = replica.getTrackedRace(raceIdentifier); + assertNotNull(replicatedTrackedRace); + assertNotNull(replicatedTrackedRace.getTrack(replicatedCompetitor).getFirstRawFix()); + assertEquals(competitorName, replicatedCompetitor.getName()); + } } \ No newline at end of file diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java index d4fddc0fc24..21e8a90f8d2 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java @@ -83,7 +83,7 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio new PersonImpl("Tina Lutz", masterDomainFactory.getOrCreateNationality("GER"), null, null) }), new PersonImpl("Rigo de Mas", masterDomainFactory.getOrCreateNationality("NED"), null, null)), new BoatImpl("GER 61", masterDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null); + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); final String baseEventName = "Test Event"; AddDefaultRegatta addEventOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID()); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithGPSFixStoreContentsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithGPSFixStoreContentsReplicationTest.java index 16b9a824610..266d4555151 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithGPSFixStoreContentsReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithGPSFixStoreContentsReplicationTest.java @@ -84,7 +84,7 @@ public class TrackedRaceWithGPSFixStoreContentsReplicationTest extends AbstractS new PersonImpl("Tina Lutz", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null) }), new PersonImpl("Rigo de Mas", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), new BoatImpl("GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null); + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); final String baseEventName = "Test Event"; AddDefaultRegatta addEventOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID()); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java index 3b151c2c483..489922fbb1c 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java @@ -1,86 +1,86 @@ -package com.sap.sailing.server.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.impl.DynamicCompetitor; -import com.sap.sailing.domain.base.impl.DynamicTeam; -import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl; -import com.sap.sailing.domain.persistence.PersistenceFactory; -import com.sap.sailing.domain.test.AbstractLeaderboardTest; -import com.sap.sailing.server.impl.PersistentCompetitorStore; -import com.sap.sse.common.Duration; - -public class CompetitorStoreTest { - @Test - public void testAddingToTransientStore() { - CompetitorStore transientStore = new TransientCompetitorStoreImpl(); - DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); - Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(), - /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730)); - assertTrue(competitor != template); - Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), - template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), - template.getBoat(), /* timeOnTimeFactor */ 1.345, - /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(750.2)); - assertSame(competitor, competitor2); - assertEquals(DomainFactory.INSTANCE.getOrCreateNationality("GER"), competitor.getTeam().getNationality()); - DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); - differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana - Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null); - assertSame(competitor, competitor3); // use existing competitor despite the different team - assertSame(competitor.getTeam(), competitor3.getTeam()); - - // now mark the competitor as to update from defaults - transientStore.allowCompetitorResetToDefaults(competitor); - Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null); - assertSame(competitor, competitor4); // expecting an in-place update - assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); - } - - @Test - public void testPersistentCompetitorStore() { - CompetitorStore persistentStore1 = new PersistentCompetitorStore( - PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); - DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); - Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), - template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), - template.getBoat(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730)); - - CompetitorStore persistentStore2 = new PersistentCompetitorStore( - PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null); - Competitor competitor2 = persistentStore2.getExistingCompetitorById(template.getId()); - assertNotSame(competitor2, template); // the new store loads new instances from the database - assertEquals(template.getId(), competitor2.getId()); - assertEquals(template.getTeam().getNationality(), competitor2.getTeam().getNationality()); - assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001); - assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); - DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); - differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana - Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null); - assertSame(competitor2, competitor3); // use existing competitor despite the different team - assertNotSame(differentTeam, competitor2.getTeam()); // team expected to remain unchanged - assertEquals(competitor.getTeam().getNationality(), competitor3.getTeam().getNationality()); // no updatability requested; nationality - // expected to remain unchanged - // now mark the competitor as to update from defaults - persistentStore2.allowCompetitorResetToDefaults(competitor2); - Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null); - assertSame(competitor2, competitor4); // expecting an in-place update - assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); - } -} +package com.sap.sailing.server.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.impl.DynamicCompetitor; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sailing.domain.test.AbstractLeaderboardTest; +import com.sap.sailing.server.impl.PersistentCompetitorStore; +import com.sap.sse.common.Duration; + +public class CompetitorStoreTest { + @Test + public void testAddingToTransientStore() { + CompetitorStore transientStore = new TransientCompetitorStoreImpl(); + DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); + Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(), + /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); + assertTrue(competitor != template); + Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), + template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), + template.getBoat(), /* timeOnTimeFactor */ 1.345, + /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(750.2), null); + assertSame(competitor, competitor2); + assertEquals(DomainFactory.INSTANCE.getOrCreateNationality("GER"), competitor.getTeam().getNationality()); + DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); + differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana + Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); + assertSame(competitor, competitor3); // use existing competitor despite the different team + assertSame(competitor.getTeam(), competitor3.getTeam()); + + // now mark the competitor as to update from defaults + transientStore.allowCompetitorResetToDefaults(competitor); + Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); + assertSame(competitor, competitor4); // expecting an in-place update + assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); + } + + @Test + public void testPersistentCompetitorStore() { + CompetitorStore persistentStore1 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); + DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); + Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), + template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), + template.getBoat(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); + + CompetitorStore persistentStore2 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null); + Competitor competitor2 = persistentStore2.getExistingCompetitorById(template.getId()); + assertNotSame(competitor2, template); // the new store loads new instances from the database + assertEquals(template.getId(), competitor2.getId()); + assertEquals(template.getTeam().getNationality(), competitor2.getTeam().getNationality()); + assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001); + assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); + DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); + differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana + Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); + assertSame(competitor2, competitor3); // use existing competitor despite the different team + assertNotSame(differentTeam, competitor2.getTeam()); // team expected to remain unchanged + assertEquals(competitor.getTeam().getNationality(), competitor3.getTeam().getNationality()); // no updatability requested; nationality + // expected to remain unchanged + // now mark the competitor as to update from defaults + persistentStore2.allowCompetitorResetToDefaults(competitor2); + Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); + assertSame(competitor2, competitor4); // expecting an in-place update + assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); + } +} diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java index f81e76842f1..8b9c6cdad4a 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java @@ -1,90 +1,90 @@ -package com.sap.sailing.server.test; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import junit.framework.TestCase; - -import org.junit.Test; - -import com.mongodb.BasicDBList; -import com.mongodb.BasicDBObject; -import com.mongodb.DBCollection; -import com.mongodb.DBCursor; -import com.mongodb.DBObject; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; -import com.sap.sailing.domain.base.impl.DynamicPerson; -import com.sap.sailing.domain.base.impl.DynamicTeam; -import com.sap.sailing.domain.base.impl.NationalityImpl; -import com.sap.sailing.domain.base.impl.PersonImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.impl.RacingEventServiceImpl; -import com.sap.sse.mongodb.MongoDBService; - -public class LeaderboardStorageTest extends TestCase { - - private static final String LEADERBOARD_NAME = "test"; - - @Override - protected void setUp() throws Exception { - removeTestLeaderboard(); - } - - @Override - protected void tearDown() throws Exception { - removeTestLeaderboard(); - } - - private void removeTestLeaderboard() { - RacingEventService service = new RacingEventServiceImpl(); - if (service.getLeaderboardByName(LEADERBOARD_NAME) != null) { - service.removeLeaderboard(LEADERBOARD_NAME); - } - } - - @Test - public void testIfCarriedPointsAreStoredIfNoRacesAreTracked() { - RacingEventService service = new RacingEventServiceImpl(); - int[] dicardingThresholds = {}; - Leaderboard leaderboard = service.addFlexibleLeaderboard(LEADERBOARD_NAME, "testIt", dicardingThresholds, - new LowPoint(), "maaap"); - - List sailorList = new ArrayList(); - sailorList.add(new PersonImpl("sailor", new NationalityImpl("GER"), null, "")); - DynamicTeam team = new TeamImpl("team", sailorList, null); - DynamicBoat boat = new BoatImpl("woot", service.getBaseDomainFactory().getOrCreateBoatClass("H16"), "70155"); - String competitorId = "testC"; - Competitor competitor = service.getBaseDomainFactory().getOrCreateCompetitor(competitorId, "Test C", null, - null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null); - - double carriedPoints = 2.0; - leaderboard.setCarriedPoints(competitor, carriedPoints); - service.getMongoObjectFactory().storeLeaderboard(leaderboard); - - // Test in db - DBCollection leaderboardCollection = MongoDBService.INSTANCE.getDB().getCollection("LEADERBOARDS"); - BasicDBObject query = new BasicDBObject(); - query.put("LEADERBOARD_NAME", LEADERBOARD_NAME); - DBCursor leaderboardObjectCursor = leaderboardCollection.find(); - DBObject dbLeaderboard = leaderboardObjectCursor.next(); - BasicDBList carriedPointsById = (BasicDBList) dbLeaderboard.get("LEADERBOARD_CARRIED_POINTS_BY_ID"); - if (carriedPointsById != null) { - for (Object o : carriedPointsById) { - DBObject competitorIdAndCarriedPoints = (DBObject) o; - Serializable competitorIdFromDB = (Serializable) competitorIdAndCarriedPoints.get("COMPETITOR_ID"); - Double carriedPointsForCompetitor = ((Number) competitorIdAndCarriedPoints - .get("LEADERBOARD_CARRIED_POINTS")).doubleValue(); - assertEquals(competitorId, competitorIdFromDB); - assertEquals(carriedPoints, carriedPointsForCompetitor, 0.0001); - - } - } - } - -} +package com.sap.sailing.server.test; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.junit.Test; + +import com.mongodb.BasicDBList; +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.DBCursor; +import com.mongodb.DBObject; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicPerson; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.base.impl.NationalityImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.impl.LowPoint; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.impl.RacingEventServiceImpl; +import com.sap.sse.mongodb.MongoDBService; + +public class LeaderboardStorageTest extends TestCase { + + private static final String LEADERBOARD_NAME = "test"; + + @Override + protected void setUp() throws Exception { + removeTestLeaderboard(); + } + + @Override + protected void tearDown() throws Exception { + removeTestLeaderboard(); + } + + private void removeTestLeaderboard() { + RacingEventService service = new RacingEventServiceImpl(); + if (service.getLeaderboardByName(LEADERBOARD_NAME) != null) { + service.removeLeaderboard(LEADERBOARD_NAME); + } + } + + @Test + public void testIfCarriedPointsAreStoredIfNoRacesAreTracked() { + RacingEventService service = new RacingEventServiceImpl(); + int[] dicardingThresholds = {}; + Leaderboard leaderboard = service.addFlexibleLeaderboard(LEADERBOARD_NAME, "testIt", dicardingThresholds, + new LowPoint(), "maaap"); + + List sailorList = new ArrayList(); + sailorList.add(new PersonImpl("sailor", new NationalityImpl("GER"), null, "")); + DynamicTeam team = new TeamImpl("team", sailorList, null); + DynamicBoat boat = new BoatImpl("woot", service.getBaseDomainFactory().getOrCreateBoatClass("H16"), "70155"); + String competitorId = "testC"; + Competitor competitor = service.getBaseDomainFactory().getOrCreateCompetitor(competitorId, "Test C", null, + null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + + double carriedPoints = 2.0; + leaderboard.setCarriedPoints(competitor, carriedPoints); + service.getMongoObjectFactory().storeLeaderboard(leaderboard); + + // Test in db + DBCollection leaderboardCollection = MongoDBService.INSTANCE.getDB().getCollection("LEADERBOARDS"); + BasicDBObject query = new BasicDBObject(); + query.put("LEADERBOARD_NAME", LEADERBOARD_NAME); + DBCursor leaderboardObjectCursor = leaderboardCollection.find(); + DBObject dbLeaderboard = leaderboardObjectCursor.next(); + BasicDBList carriedPointsById = (BasicDBList) dbLeaderboard.get("LEADERBOARD_CARRIED_POINTS_BY_ID"); + if (carriedPointsById != null) { + for (Object o : carriedPointsById) { + DBObject competitorIdAndCarriedPoints = (DBObject) o; + Serializable competitorIdFromDB = (Serializable) competitorIdAndCarriedPoints.get("COMPETITOR_ID"); + Double carriedPointsForCompetitor = ((Number) competitorIdAndCarriedPoints + .get("LEADERBOARD_CARRIED_POINTS")).doubleValue(); + assertEquals(competitorId, competitorIdFromDB); + assertEquals(carriedPoints, carriedPointsForCompetitor, 0.0001); + + } + } + } + +} diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 03889f1a95b..c6da147d75f 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -1,2257 +1,2257 @@ -package com.sap.sailing.server.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; - -import junit.framework.Assert; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.mongodb.DB; -import com.mongodb.WriteConcern; -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; -import com.sap.sailing.domain.abstractlog.race.CompetitorResults; -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; -import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultImpl; -import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Event; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl; -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.CourseAreaImpl; -import com.sap.sailing.domain.base.impl.DomainFactoryImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; -import com.sap.sailing.domain.base.impl.DynamicPerson; -import com.sap.sailing.domain.base.impl.DynamicTeam; -import com.sap.sailing.domain.base.impl.FleetImpl; -import com.sap.sailing.domain.base.impl.NationalityImpl; -import com.sap.sailing.domain.base.impl.PersonImpl; -import com.sap.sailing.domain.base.impl.RegattaImpl; -import com.sap.sailing.domain.base.impl.SeriesImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; -import com.sap.sailing.domain.common.CourseDesignerMode; -import com.sap.sailing.domain.common.MasterDataImportObjectCreationCount; -import com.sap.sailing.domain.common.MaxPointsReason; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.RaceIdentifier; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.RegattaNameAndRaceName; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.SpeedWithBearing; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.impl.DataImportProgressImpl; -import com.sap.sailing.domain.common.impl.DegreeBearingImpl; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; -import com.sap.sailing.domain.common.impl.WindImpl; -import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID; -import com.sap.sailing.domain.common.media.MediaTrack; -import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; -import com.sap.sailing.domain.common.tracking.GPSFix; -import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; -import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.LeaderboardGroup; -import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; -import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; -import com.sap.sailing.domain.persistence.PersistenceFactory; -import com.sap.sailing.domain.persistence.media.MediaDBFactory; -import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; -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.ranking.OneDesignRankingMetric; -import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindTrack; -import com.sap.sailing.domain.tracking.impl.EmptyWindStore; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; -import com.sap.sailing.server.gateway.jaxrs.spi.MasterDataResource; -import com.sap.sailing.server.impl.MediaMasterDataExportTest; -import com.sap.sailing.server.impl.RacingEventServiceImpl; -import com.sap.sailing.server.masterdata.DummyTrackedRace; -import com.sap.sailing.server.masterdata.MasterDataImporter; -import com.sap.sse.common.Color; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsDurationImpl; -import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.MimeType; -import com.sap.sse.mongodb.MongoDBConfiguration; -import com.sap.sse.mongodb.MongoDBService; -import com.sap.sse.shared.media.ImageDescriptor; -import com.sap.sse.shared.media.VideoDescriptor; - -public class MasterDataImportTest { - - private static final String TEST_GROUP_NAME = "testGroup"; - private static final String TEST_EVENT_NAME = "testEvent"; - private static final String TEST_REGATTA_NAME = "testRegatta"; - private static final String TEST_BOAT_CLASS_NAME = "29er"; - private static final String TEST_LEADERBOARD_NAME = "testRegatta (29er)"; - private static final String TEST_GROUP_NAME2 = "testGroup2"; - - private final UUID eventUUID = UUID.randomUUID(); - private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1); - - private final TimePoint eventStartDate = new MillisecondsTimePoint(new Date()); - private final TimePoint eventEndDate = new MillisecondsTimePoint(new Date()); - - private final UUID raceId = UUID.randomUUID(); - - /** - * Log Events created when running test. Will be removed from db at teardown - */ - private Set storedLogUUIDs = new HashSet(); - - @After - public void tearDown() { - deleteAllDataFromDatabase(); - } - - @Before - public void setUp() { - deleteAllDataFromDatabase(); - } - - private T spyResource(T resource, RacingEventService service) { - T spyResource = spy(resource); - - doReturn(service).when(spyResource).getService(); - return spyResource; - } - - private void deleteAllDataFromDatabase() { - MongoDBService service = MongoDBConfiguration.getDefaultTestConfiguration().getService(); - service.getDB().getWriteConcern().fsync(); - service.getDB().dropDatabase(); - } - - @Test - public void testMasterDataImportWithoutHttpStack() throws MalformedURLException, IOException, InterruptedException, - ClassNotFoundException { - // Setup source service - MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory(); - RacingEventService sourceService = new RacingEventServiceImpl(null, null, serviceFinderFactory); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, - "testVenue", false, eventUUID); - UUID courseAreaUUID = UUID.randomUUID(); - CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); - event.getVenue().addCourseArea(courseArea); - - List raceColumnNames = new ArrayList(); - String raceColumnName = "T1"; - raceColumnNames.add(raceColumnName); - raceColumnNames.add("T2"); - final List emptyRaceColumnNamesList = Collections.emptyList(); - - List series = new ArrayList(); - List fleets = new ArrayList(); - String testFleet1Name = "testFleet1"; - FleetImpl testFleet1 = new FleetImpl(testFleet1Name); - fleets.add(testFleet1); - fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - event.addRegatta(regatta); - for (String name : raceColumnNames) { - series.get(0).addRaceColumn(name, sourceService); - } - double factor = 3.0; - series.get(0).getRaceColumnByName(raceColumnName).setFactor(factor); - - int[] discardRule = { 1, 2, 3, 4 }; - Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "testDisplayName", discardRule); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - event.addLeaderboardGroup(group); - - // Set tracked Race with competitors - List competitors = new ArrayList(); - UUID competitorUUID = UUID.randomUUID(); - Set sailors = new HashSet(); - sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), - "Oberhoschy")); - DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), - "Der Lennart halt"); - DynamicTeam team = new TeamImpl("Pros", sailors, coach); - BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitor); - UUID competitorToSuppressUUID = UUID.randomUUID(); - Set sailors2 = new HashSet(); - sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), - "segelt auch mit")); - DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), - "Bester Coach"); - DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitorToSuppress); - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); - - raceColumn.setTrackedRace(testFleet1, trackedRace); - - // Set log event - TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - TimePoint logTimePoint2 = new MillisecondsTimePoint(1372489201000L); - RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, logTimePoint, author, 1, - 0, logTimePoint, RaceLogRaceStatus.SCHEDULED); - raceColumn.getRaceLog(testFleet1).add(logEvent); - Position p = new DegreePosition(3, 3); - Wind wind = new WindImpl(p, logTimePoint2, new KnotSpeedWithBearingImpl(5, new DegreeBearingImpl(12))); - RaceLogWindFixEvent windEvent = new RaceLogWindFixEventImpl(logTimePoint2, logTimePoint2, author, - UUID.randomUUID(), 2, wind, /* isMagnetic */false); - raceColumn.getRaceLog(testFleet1).add(windEvent); - storedLogUUIDs.add(logEvent.getId()); - storedLogUUIDs.add(windEvent.getId()); - - // Set RegattaLog event - TimePoint regattaLogTimepoint = new MillisecondsTimePoint(84392048L); - RegattaLogRegisterCompetitorEvent registerEvent = new RegattaLogRegisterCompetitorEventImpl( - regattaLogTimepoint, regattaLogTimepoint, author, UUID.randomUUID(), competitor); - regatta.getRegattaLog().add(registerEvent); - - // Add some racelogtracking stuff - TimePoint logTimePoint3 = new MillisecondsTimePoint(1372489210000L); - TimePoint logTimePoint4 = new MillisecondsTimePoint(1372489200020L); - DeviceIdentifier deviceIdentifier = new SmartphoneImeiIdentifier("a"); - RegattaLogDeviceCompetitorMappingEvent mappingEvent = new RegattaLogDeviceCompetitorMappingEventImpl( - logTimePoint4, logTimePoint4, author, UUID.randomUUID(), competitor, deviceIdentifier, logTimePoint, - logTimePoint3); - regatta.getRegattaLog().add(mappingEvent); - GPSFix gpsFix = new GPSFixMovingImpl(new DegreePosition(54.333, 10.133), logTimePoint2, - new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(90))); - sourceService.getGPSFixStore().storeFix(deviceIdentifier, gpsFix); - - // Set score correction - double scoreCorrection = 12.0; - leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); - MaxPointsReason maxPointsReason = MaxPointsReason.DNS; - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); - - // Set carried Points - double carriedPoints = 2.0; - leaderboard.setCarriedPoints(competitor, carriedPoints); - - // Set suppressed competitor - leaderboard.setSuppressed(competitorToSuppress, true); - - // Set display name - String nickName = "Angie"; - leaderboard.setDisplayName(competitorToSuppress, nickName); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - InputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID), serviceFinderFactory); - domainFactory = destService.getBaseDomainFactory(); - DB db = destService.getMongoObjectFactory().getDatabase(); - db.setWriteConcern(WriteConcern.SAFE); - inputStream = new ByteArrayInputStream(os.toByteArray()); - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - Assert.assertNotNull(creationCount); - Event eventOnTarget = destService.getEvent(eventUUID); - Assert.assertNotNull(eventOnTarget); - LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); - Assert.assertNotNull(leaderboardGroupOnTarget); - assertSame(leaderboardGroupOnTarget, eventOnTarget.getLeaderboardGroups().iterator().next()); - Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(leaderboardOnTarget); - Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(regattaOnTarget); - - Assert.assertEquals(false, regattaOnTarget.getAllRaces().iterator().hasNext()); - - Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); - - RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); - Assert.assertNotNull(raceColumnOnTarget); - Assert.assertNull(raceColumnOnTarget.getTrackedRace(raceColumnOnTarget.getFleetByName(testFleet1Name))); - - raceColumnOnTarget.setTrackedRace(raceColumnOnTarget.getFleets().iterator().next(), new DummyTrackedRace( - raceId, competitors, regattaOnTarget, null, sourceService.getWindStore())); - - Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); - Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); - Set competitorsCreatedOnTarget = new HashSet(); - competitorsCreatedOnTarget.add(competitorOnTarget); - - Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, - null, sourceService.getWindStore()); - - raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); - - Assert.assertEquals(factor, raceColumnOnTarget.getFactor()); - - Iterable competitorsOnTarget = leaderboardOnTarget.getAllCompetitors(); - Iterator competitorIterator = competitorsOnTarget.iterator(); - Assert.assertTrue(competitorIterator.hasNext()); - Assert.assertEquals(competitorOnTarget, competitorIterator.next()); - - // Check for score corrections - Assert.assertEquals( - scoreCorrection, - leaderboardOnTarget.getScoreCorrection().getExplicitScoreCorrection(competitorOnTarget, - raceColumnOnTarget)); - Assert.assertEquals( - maxPointsReason, - leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, - MillisecondsTimePoint.now())); - - // Check for carried points - Assert.assertEquals(carriedPoints, leaderboardOnTarget.getCarriedPoints(competitorOnTarget)); - - // Check for suppressed competitor - Assert.assertTrue(leaderboardOnTarget.getSuppressedCompetitors().iterator().hasNext()); - Competitor suppressedCompetitorOnTarget = domainFactory.getCompetitorStore().getExistingCompetitorById( - competitorToSuppressUUID); - Assert.assertEquals(suppressedCompetitorOnTarget, leaderboardOnTarget.getSuppressedCompetitors().iterator() - .next()); - - // Check for competitor display name - Assert.assertEquals(nickName, leaderboardOnTarget.getDisplayName(suppressedCompetitorOnTarget)); - - // Check for race log event - Assert.assertNotNull(raceColumnOnTarget.getRaceLog(fleet1OnTarget).getFirstRawFixAtOrAfter(logTimePoint)); - Assert.assertEquals(logEvent.getId(), - raceColumnOnTarget.getRaceLog(fleet1OnTarget).getFirstRawFixAtOrAfter(logTimePoint).getId()); - Assert.assertNotNull(raceColumnOnTarget.getRaceLog(fleet1OnTarget).getFirstFixAtOrAfter(logTimePoint2)); - Assert.assertEquals(wind, ((RaceLogWindFixEvent) raceColumnOnTarget.getRaceLog(fleet1OnTarget) - .getFirstFixAtOrAfter(logTimePoint2)).getWindFix()); - - // Add new event to check persistence of post-import events (see bug 3230) - TimePoint logTimePoint5 = new MillisecondsTimePoint(1372489310000L); - UUID postImportEventId = UUID.randomUUID(); - RaceLogStartTimeEventImpl postImportLogEvent = new RaceLogStartTimeEventImpl(logTimePoint5, logTimePoint5, - author, postImportEventId, 3, logTimePoint5, RaceLogRaceStatus.SCHEDULED); - raceColumnOnTarget.getRaceLog(fleet1OnTarget).add(postImportLogEvent); - - // Check for regatta log event - RegattaLogRegisterCompetitorEvent registerEventOnTarget = (RegattaLogRegisterCompetitorEvent) regattaOnTarget - .getRegattaLog().getFirstFixAtOrAfter(regattaLogTimepoint); - Assert.assertNotNull(registerEventOnTarget); - Assert.assertEquals(registerEvent.getId(), registerEventOnTarget.getId()); - Assert.assertEquals(competitor.getId(), registerEventOnTarget.getCompetitor().getId()); - - // Check for import of racelogtracking fix - Assert.assertTrue(destService.getGPSFixStore().getNumberOfFixes(deviceIdentifier) == 1); - - // Check for persisting of race log events: - RacingEventService dest2 = new RacingEventServiceImplMock(); - Leaderboard lb2 = dest2.getLeaderboardByName(TEST_LEADERBOARD_NAME); - RaceColumn raceColumn2 = lb2.getRaceColumns().iterator().next(); - RaceLog raceLog2 = raceColumn2.getRaceLog(raceColumn2.getFleetByName(fleet1OnTarget.getName())); - Assert.assertEquals(logEvent.getId(), raceLog2.getFirstRawFixAtOrAfter(logTimePoint).getId()); - - RaceLogEvent postImportLogEventFromDB = raceLog2.getFirstRawFixAtOrAfter(logTimePoint5); - Assert.assertEquals(postImportEventId, postImportLogEventFromDB.getId()); - - // Check for persisting of regatta log events - Regatta regattaOnTarget2 = dest2.getRegattaByName(TEST_LEADERBOARD_NAME); - RegattaLogRegisterCompetitorEvent registerEventOnTarget2 = (RegattaLogRegisterCompetitorEvent) regattaOnTarget2 - .getRegattaLog().getFirstFixAtOrAfter(regattaLogTimepoint); - Assert.assertNotNull(registerEventOnTarget2); - Assert.assertEquals(registerEvent.getId(), registerEventOnTarget2.getId()); - } - - @Test - public void testMasterDataImportForScoreCorrections() throws MalformedURLException, IOException, - InterruptedException, ClassNotFoundException { - // Setup source service - RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, - "testVenue", false, eventUUID); - UUID courseAreaUUID = UUID.randomUUID(); - CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); - event.getVenue().addCourseArea(courseArea); - - List raceColumnNames = new ArrayList(); - String raceColumnName = "T1"; - raceColumnNames.add(raceColumnName); - raceColumnNames.add("T2"); - final List emptyRaceColumnNamesList = Collections.emptyList(); - - List series = new ArrayList(); - List fleets = new ArrayList(); - FleetImpl testFleet1 = new FleetImpl("testFleet1"); - fleets.add(testFleet1); - fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - event.addRegatta(regatta); - for (String name : raceColumnNames) { - series.get(0).addRaceColumn(name, sourceService); - } - - int[] discardRule = { 1, 2, 3, 4 }; - Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "testDisplayName", discardRule); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - - // Set tracked Race with competitors - Set competitors = new HashSet(); - UUID competitorUUID = UUID.randomUUID(); - Set sailors = new HashSet(); - sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), - "Oberhoschy")); - DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), - "Der Lennart halt"); - DynamicTeam team = new TeamImpl("Pros", sailors, coach); - BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitor); - UUID competitor2UUID = UUID.randomUUID(); - Set sailors2 = new HashSet(); - sailors2.add(new PersonImpl("Test Mustermann", new NationalityImpl("GER"), new Date(645487200000L), "desc")); - DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); - DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); - CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", Color.RED, null, null, team2, - boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitor2); - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); - - raceColumn.setTrackedRace(testFleet1, trackedRace); - - // Set log event - TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); - raceColumn.getRaceLog(testFleet1).add(logEvent); - storedLogUUIDs.add(logEvent.getId()); - - // Set score correction - double scoreCorrection = 12.0; - leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); - MaxPointsReason maxPointsReason = MaxPointsReason.DNS; - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - Assert.assertNotNull(creationCount); - Event eventOnTarget = destService.getEvent(eventUUID); - Assert.assertNotNull(eventOnTarget); - LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); - Assert.assertNotNull(leaderboardGroupOnTarget); - Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(leaderboardOnTarget); - Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(regattaOnTarget); - - Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); - - RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); - Assert.assertNotNull(raceColumnOnTarget); - - Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); - Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); - Competitor competitorOnTarget2 = domainFactory.getCompetitorStore().getExistingCompetitorById(competitor2UUID); - Set competitorsCreatedOnTarget = new HashSet(); - competitorsCreatedOnTarget.add(competitorOnTarget); - - Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, - null, sourceService.getWindStore()); - - raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); - - Iterable competitorsOnTarget = leaderboardOnTarget.getAllCompetitors(); - Iterator competitorIterator = competitorsOnTarget.iterator(); - Assert.assertTrue(competitorIterator.hasNext()); - Assert.assertEquals(competitorOnTarget, competitorIterator.next()); - - // Check for score corrections - Assert.assertEquals( - scoreCorrection, - leaderboardOnTarget.getScoreCorrection().getExplicitScoreCorrection(competitorOnTarget, - raceColumnOnTarget)); - Assert.assertEquals( - maxPointsReason, - leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, - MillisecondsTimePoint.now())); - - // Checks if score correction was not set if not set on source - Assert.assertFalse(leaderboardOnTarget.getScoreCorrection().isScoreCorrected(competitorOnTarget2, - raceColumnOnTarget, MillisecondsTimePoint.now())); - } - - @Test - public void testMasterDataImportForWind() throws MalformedURLException, IOException, InterruptedException, - ClassNotFoundException { - // Setup source service - RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, - "testVenue", false, eventUUID); - UUID courseAreaUUID = UUID.randomUUID(); - CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); - event.getVenue().addCourseArea(courseArea); - - List raceColumnNames = new ArrayList(); - String raceColumnName = "T1"; - raceColumnNames.add(raceColumnName); - final List emptyRaceColumnNamesList = Collections.emptyList(); - - List series = new ArrayList(); - List fleets = new ArrayList(); - FleetImpl testFleet1 = new FleetImpl("testFleet1"); - fleets.add(testFleet1); - series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName("testRegatta", "29er"), "29er", - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - event.addRegatta(regatta); - for (String name : raceColumnNames) { - series.get(0).addRaceColumn(name, sourceService); - } - - int[] discardRule = { 1, 2, 3, 4 }; - Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "testDisplayName", discardRule); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - - // Set tracked Race with competitors - Set competitors = new HashSet(); - UUID competitorUUID = UUID.randomUUID(); - Set sailors = new HashSet(); - sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), - "Oberhoschy")); - DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), - "Der Lennart halt"); - DynamicTeam team = new TeamImpl("Pros", sailors, coach); - BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitor); - - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - DynamicTrackedRegatta trackedRegatta = sourceService.getOrCreateTrackedRegatta(regatta); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, trackedRegatta, - sourceService.getWindStore()); - regatta.addRace(trackedRace.getRace()); // make sure the competitor is serialized together with the regatta - raceColumn.setTrackedRace(testFleet1, trackedRace); - WindSource windSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION, "Igtimi1"); - WindTrack windTrackOnSource = trackedRace.getOrCreateWindTrack(windSource); - - Position p = new DegreePosition(54, 30); - TimePoint at = new MillisecondsTimePoint(20000); - SpeedWithBearing windSpeedWithBearing = new KnotSpeedWithBearingImpl(20, new DegreeBearingImpl(12)); - windTrackOnSource.add(new WindImpl(p, at, windSpeedWithBearing)); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - Assert.assertNotNull(creationCount); - Event eventOnTarget = destService.getEvent(eventUUID); - Assert.assertNotNull(eventOnTarget); - LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); - Assert.assertNotNull(leaderboardGroupOnTarget); - Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(leaderboardOnTarget); - Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(regattaOnTarget); - - Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); - - RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); - Assert.assertNotNull(raceColumnOnTarget); - - Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); - Set competitorsCreatedOnTarget = new HashSet(); - competitorsCreatedOnTarget.add(competitorOnTarget); - - Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); - DynamicTrackedRegatta trackedRegattaForTarget = destService.getOrCreateTrackedRegatta(regattaOnTarget); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, - trackedRegattaForTarget, sourceService.getWindStore()); - - raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); - - WindTrack windTrackOnDest = trackedRaceForTarget.getOrCreateWindTrack(windSource); - windTrackOnDest.lockForRead(); - try { - Iterable fixes = windTrackOnDest.getFixes(); - Assert.assertNotNull(fixes); - Iterator iterator = fixes.iterator(); - Assert.assertTrue(iterator.hasNext()); - Wind firstWindFix = iterator.next(); - Assert.assertNotNull(firstWindFix); - - Assert.assertFalse(iterator.hasNext()); - } finally { - windTrackOnDest.unlockAfterRead(); - } - - // Reimport again to see if db throws exceptions (see console for error for now, since exception is caught deep - // inside) - try { - streamingOutput.write(os); - os.flush(); - - inputStream = new ByteArrayInputStream(os.toByteArray()); - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - } - - @Test - public void testMasterDataImportForRaceLogEventsReferencingCompetitors() throws MalformedURLException, IOException, - InterruptedException, ClassNotFoundException { - // Setup source service - DomainFactory sourceDomainFactory = new DomainFactoryImpl((srlid) -> null); - RacingEventService sourceService = new RacingEventServiceImpl( - PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, sourceDomainFactory), - PersistenceFactory.INSTANCE.getMongoObjectFactory(MongoDBService.INSTANCE), - MediaDBFactory.INSTANCE.getDefaultMediaDB(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, - "testVenue", false, eventUUID); - UUID courseAreaUUID = UUID.randomUUID(); - CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); - event.getVenue().addCourseArea(courseArea); - - List raceColumnNames = new ArrayList(); - String raceColumnName = "T1"; - raceColumnNames.add(raceColumnName); - raceColumnNames.add("T2"); - final List emptyRaceColumnNamesList = Collections.emptyList(); - - List series = new ArrayList(); - List fleets = new ArrayList(); - FleetImpl testFleet1 = new FleetImpl("testFleet1"); - fleets.add(testFleet1); - fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - event.addRegatta(regatta); - for (String name : raceColumnNames) { - series.get(0).addRaceColumn(name, sourceService); - } - - int[] discardRule = { 1, 2, 3, 4 }; - Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "testDisplayName", discardRule); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - - // Set tracked Race with competitors - Set competitors = new HashSet(); - UUID competitorUUID = UUID.randomUUID(); - Set sailors = new HashSet(); - sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), - "Oberhoschy")); - DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), - "Der Lennart halt"); - DynamicTeam team = new TeamImpl("Pros", sailors, coach); - BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", Color.RED, - "noone@nowhere.de", null, team, boat, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ - null); - competitors.add(competitor); - UUID competitor2UUID = UUID.randomUUID(); - Set sailors2 = new HashSet(); - sailors2.add(new PersonImpl("Test Mustermann", new NationalityImpl("GER"), new Date(645487200000L), "desc")); - DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); - DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); - Competitor competitor2 = sourceDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitor2UUID, - "Froderik", Color.RED, "noone@nowhere.de", null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ - null); - competitors.add(competitor2); - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); - - raceColumn.setTrackedRace(testFleet1, trackedRace); - - // Set log event - TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); - raceColumn.getRaceLog(testFleet1).add(logEvent); - storedLogUUIDs.add(logEvent.getId()); - - // Add a competitor-related race log event to ensure that no competitor resolution is attempted while receiving - TimePoint logTimePoint2 = logTimePoint.plus(10); - CompetitorResults positionedCompetitors = new CompetitorResultsImpl(); - positionedCompetitors.add(new CompetitorResultImpl( - competitor.getId(), competitor.getName(), /* rank */ 1, MaxPointsReason.DNS, /* score */ null, /* finishingTime */ null, /* comment */ null)); - positionedCompetitors.add(new CompetitorResultImpl( - competitor2.getId(), competitor2.getName(), /* rank */ 2, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null)); - RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent = new RaceLogFinishPositioningConfirmedEventImpl( - logTimePoint2, author, 1, positionedCompetitors); - raceColumn.getRaceLog(testFleet1).add(finishPositioningConfirmedEvent); - storedLogUUIDs.add(finishPositioningConfirmedEvent.getId()); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - Assert.assertNotNull(creationCount); - Event eventOnTarget = destService.getEvent(eventUUID); - Assert.assertNotNull(eventOnTarget); - LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); - Assert.assertNotNull(leaderboardGroupOnTarget); - Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(leaderboardOnTarget); - Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(regattaOnTarget); - - Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); - - RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); - Assert.assertNotNull(raceColumnOnTarget); - - Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); - Competitor competitorOnTarget = domainFactory.getCompetitorStore().getExistingCompetitorById(competitorUUID); - Set competitorsCreatedOnTarget = new HashSet(); - competitorsCreatedOnTarget.add(competitorOnTarget); - - Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, - null, sourceService.getWindStore()); - - raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); - - Iterable competitorsOnTarget = leaderboardOnTarget.getAllCompetitors(); - Iterator competitorIterator = competitorsOnTarget.iterator(); - Assert.assertTrue(competitorIterator.hasNext()); - Assert.assertEquals(competitorOnTarget, competitorIterator.next()); - - // Check for score corrections - Assert.assertEquals( - MaxPointsReason.DNS, - leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, - MillisecondsTimePoint.now())); - } - - @Test - public void testMasterDataImportWithoutOverrideWithoutHttpStack() throws MalformedURLException, IOException, - InterruptedException, ClassNotFoundException { - // Setup source service - RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, - "testVenue", false, eventUUID); - UUID courseAreaUUID = UUID.randomUUID(); - CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); - event.getVenue().addCourseArea(courseArea); - - List raceColumnNames = new ArrayList(); - String raceColumnName = "T1"; - raceColumnNames.add(raceColumnName); - raceColumnNames.add("T2"); - List emptyRaceColumnNamesList = Collections.emptyList(); - - List series = new ArrayList(); - List fleets = new ArrayList(); - FleetImpl testFleet1 = new FleetImpl("testFleet1"); - fleets.add(testFleet1); - fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - event.addRegatta(regatta); - for (String name : raceColumnNames) { - series.get(0).addRaceColumn(name, sourceService); - } - - int[] discardRule = { 1, 2, 3, 4 }; - Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "testDisplayName", discardRule); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - - // Set tracked Race with competitors - Set competitors = new HashSet(); - UUID competitorUUID = UUID.randomUUID(); - Set sailors = new HashSet(); - sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), - "Oberhoschy")); - DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), - "Der Lennart halt"); - DynamicTeam team = new TeamImpl("Pros", sailors, coach); - BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitor); - UUID competitorToSuppressUUID = UUID.randomUUID(); - Set sailors2 = new HashSet(); - sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), - "segelt auch mit")); - DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), - "Bester Coach"); - DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitorToSuppress); - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); - - raceColumn.setTrackedRace(testFleet1, trackedRace); - - // Set log event - TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); - raceColumn.getRaceLog(testFleet1).add(logEvent); - storedLogUUIDs.add(logEvent.getId()); - - // Set score correction - double scoreCorrection = 12.0; - leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); - MaxPointsReason maxPointsReason = MaxPointsReason.DNS; - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); - - // Set carried Points - double carriedPoints = 2.0; - leaderboard.setCarriedPoints(competitor, carriedPoints); - - // Set suppressed competitor - leaderboard.setSuppressed(competitorToSuppress, true); - - // Set display name - String nickName = "Angie"; - leaderboard.setDisplayName(competitorToSuppress, nickName); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - String venueNameNotToOverride; - CourseAreaImpl courseAreaNotToOverride; - String raceColumnNameNotToOveride; - RegattaLeaderboard leaderboardNotToOverride; - LeaderboardGroup groupNotToOverride; - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - // Create existing data on target - venueNameNotToOverride = "doNotOverride"; - Event eventNotToOverride = destService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, - eventStartDate, eventEndDate, venueNameNotToOverride, false, eventUUID); - courseAreaNotToOverride = new CourseAreaImpl("testAreaNotToOverride", courseAreaUUID); - eventNotToOverride.getVenue().addCourseArea(courseAreaNotToOverride); - - List raceColumnNamesNotToOverride = new ArrayList(); - raceColumnNameNotToOveride = "T1nottooverride"; - raceColumnNamesNotToOverride.add(raceColumnNameNotToOveride); - emptyRaceColumnNamesList = Collections.emptyList(); - - List seriesNotToOverride = new ArrayList(); - List fleetsNotToOverride = new ArrayList(); - FleetImpl testFleet1NotToOverride = new FleetImpl("testFleet1"); - fleetsNotToOverride.add(testFleet1NotToOverride); - seriesNotToOverride.add(new SeriesImpl("testSeries", false, fleetsNotToOverride, emptyRaceColumnNamesList, - destService)); - Regatta regattaNotToOverride = destService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ - null, /* endDate */null, regattaUUID, seriesNotToOverride, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - event.addRegatta(regattaNotToOverride); - for (String name : raceColumnNamesNotToOverride) { - seriesNotToOverride.get(0).addRaceColumn(name, destService); - } - - leaderboardNotToOverride = destService.addRegattaLeaderboard(regattaNotToOverride.getRegattaIdentifier(), - "testDisplayNameNotToOverride", discardRule); - List leaderboardNamesNotToOverride = new ArrayList(); - leaderboardNamesNotToOverride.add(leaderboardNotToOverride.getName()); - groupNotToOverride = destService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, - "testGroupDescNotToOverride", /* displayName */null, false, leaderboardNamesNotToOverride, null, - null); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - // ---Asserts--- - // Test correct number of creations - Assert.assertNotNull(creationCount); - Assert.assertEquals(0, creationCount.getEventCount()); - Assert.assertEquals(0, creationCount.getRegattaCount()); - Assert.assertEquals(0, creationCount.getLeaderboardCount()); - Assert.assertEquals(0, creationCount.getLeaderboardGroupCount()); - - Event eventOnTarget = destService.getEvent(eventUUID); - Assert.assertNotNull(eventOnTarget); - - // Check if existing event survived import - Assert.assertEquals(venueNameNotToOverride, eventOnTarget.getVenue().getName()); - - // Check if existing course area survived import - Assert.assertEquals(courseAreaNotToOverride.getName(), eventOnTarget.getVenue().getCourseAreas().iterator() - .next().getName()); - LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); - Assert.assertNotNull(leaderboardGroupOnTarget); - // Check if existing leaderboard group survived import - Assert.assertEquals(groupNotToOverride.getDescription(), leaderboardGroupOnTarget.getDescription()); - Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(leaderboardOnTarget); - Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(regattaOnTarget); - - Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); - - RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnNameNotToOveride); - Assert.assertNotNull(raceColumnOnTarget); - // Check if existing leaderboard survived import - Assert.assertEquals(leaderboardNotToOverride.getDisplayName(), leaderboardOnTarget.getDisplayName()); - Assert.assertFalse(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); - - } - - @Test - public void testMasterDataImportWithOverrideWithoutHttpStack() throws MalformedURLException, IOException, - InterruptedException, ClassNotFoundException { - // Setup source service - RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, - "testVenue", false, eventUUID); - UUID courseAreaUUID = UUID.randomUUID(); - CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); - event.getVenue().addCourseArea(courseArea); - - List raceColumnNames = new ArrayList(); - String raceColumnName = "T1"; - raceColumnNames.add(raceColumnName); - raceColumnNames.add("T2"); - List emptyRaceColumnNamesList = Collections.emptyList(); - - List series = new ArrayList(); - List fleets = new ArrayList(); - FleetImpl testFleet1 = new FleetImpl("testFleet1"); - fleets.add(testFleet1); - fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - event.addRegatta(regatta); - for (String name : raceColumnNames) { - series.get(0).addRaceColumn(name, sourceService); - } - - int[] discardRule = { 1, 2, 3, 4 }; - Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "testDisplayName", discardRule); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - - // Set tracked Race with competitors - Set competitors = new HashSet(); - UUID competitorUUID = UUID.randomUUID(); - Set sailors = new HashSet(); - sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), - "Oberhoschy")); - DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), - "Der Lennart halt"); - DynamicTeam team = new TeamImpl("Pros", sailors, coach); - BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitor); - UUID competitorToSuppressUUID = UUID.randomUUID(); - Set sailors2 = new HashSet(); - sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), - "segelt auch mit")); - DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), - "Bester Coach"); - DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitorToSuppress); - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); - - raceColumn.setTrackedRace(testFleet1, trackedRace); - - // Set log event - TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); - raceColumn.getRaceLog(testFleet1).add(logEvent); - storedLogUUIDs.add(logEvent.getId()); - - // Set score correction - double scoreCorrection = 12.0; - leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); - MaxPointsReason maxPointsReason = MaxPointsReason.DNS; - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); - - // Set carried Points - double carriedPoints = 2.0; - leaderboard.setCarriedPoints(competitor, carriedPoints); - - // Set suppressed competitor - leaderboard.setSuppressed(competitorToSuppress, true); - - // Set display name - String nickName = "Angie"; - leaderboard.setDisplayName(competitorToSuppress, nickName); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - RegattaAndRaceIdentifier identifierOfRegattaTrackedRace; - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - // Create existing data on target - String venueNameToOverride = "Override"; - Event eventToOverride = destService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, - eventEndDate, venueNameToOverride, false, eventUUID); - CourseArea courseAreaToOverride = new CourseAreaImpl("testAreaToOverride", courseAreaUUID); - eventToOverride.getVenue().addCourseArea(courseAreaToOverride); - - List raceColumnNamesToOverride = new ArrayList(); - String raceColumnNameToOveride = raceColumnName; - raceColumnNamesToOverride.add(raceColumnNameToOveride); - emptyRaceColumnNamesList = Collections.emptyList(); - - List seriesToOverride = new ArrayList(); - List fleetsToOverride = new ArrayList(); - FleetImpl testFleet1ToOverride = new FleetImpl("testFleet1"); - fleetsToOverride.add(testFleet1ToOverride); - seriesToOverride.add(new SeriesImpl("testSeries", false, fleetsToOverride, emptyRaceColumnNamesList, - destService)); - Regatta regattaToOverride = destService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ - null, /* endDate */null, regattaUUID, seriesToOverride, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - event.addRegatta(regattaToOverride); - for (String name : raceColumnNamesToOverride) { - seriesToOverride.get(0).addRaceColumn(name, destService); - } - - // Create competitor with same ID and other details - Set competitorsToOverride = new HashSet(); - Set sailorsToOverride = new HashSet(); - sailorsToOverride.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date( - 645487200000L), "Oberhoschy")); - DynamicPerson coachToOverride = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date( - 645487200000L), "Der Lennart halt"); - DynamicTeam teamToOverride = new TeamImpl("Pros", sailorsToOverride, coachToOverride); - BoatClass boatClassToOverride = new BoatClassImpl("H16", true); - DynamicBoat boatToOverride = new BoatImpl("Wingy", boatClassToOverride, "GER70133"); - String competitorOldName = "oldName"; - Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, - Color.BLUE, "noone@nowhere.de", null, teamToOverride, boatToOverride, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ - null); - competitorsToOverride.add(competitorToOverride); - - Leaderboard leaderboardToOverride = destService.addRegattaLeaderboard( - regattaToOverride.getRegattaIdentifier(), "testDisplayNameNotToOverride", discardRule); - TrackedRace trackedRace2 = new DummyTrackedRace(raceId, competitorsToOverride, regattaToOverride, null, - sourceService.getWindStore()); - RaceColumn columnToOverride = leaderboardToOverride.getRaceColumns().iterator().next(); - columnToOverride.setTrackedRace(testFleet1ToOverride, trackedRace2); - identifierOfRegattaTrackedRace = regattaToOverride.getRaceIdentifier(columnToOverride - .getRaceDefinition(testFleet1ToOverride)); - - destService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDescToOverride", /* displayName */ - null, false, new ArrayList(), null, null); - destService.getLeaderboardGroupByName(TEST_GROUP_NAME).addLeaderboard(leaderboardToOverride); - destService.addLeaderboard(leaderboardToOverride); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, true); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - // ---Asserts--- - // Test correct number of creations - Assert.assertNotNull(creationCount); - Assert.assertEquals(1, creationCount.getEventCount()); - Assert.assertEquals(1, creationCount.getRegattaCount()); - Assert.assertEquals(1, creationCount.getLeaderboardCount()); - Assert.assertEquals(1, creationCount.getLeaderboardGroupCount()); - - Event eventOnTarget = destService.getEvent(eventUUID); - Assert.assertNotNull(eventOnTarget); - - // Check if existing event didn't survive import - Assert.assertEquals(event.getVenue().getName(), eventOnTarget.getVenue().getName()); - - // Check if existing course area survive import - Assert.assertEquals(courseArea.getName(), eventOnTarget.getVenue().getCourseAreas().iterator().next().getName()); - LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); - Assert.assertNotNull(leaderboardGroupOnTarget); - // Check if existing leaderboard group didn't survive import - Assert.assertEquals(group.getDescription(), leaderboardGroupOnTarget.getDescription()); - Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(leaderboardOnTarget); - Regatta regattaOnTarget = destService.getRegattaByName(TEST_REGATTA_NAME + " (" + TEST_BOAT_CLASS_NAME + ")"); - Assert.assertNotNull(regattaOnTarget); - - RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboardOnTarget; - Regatta regattaInLeaderboard = regattaLeaderboard.getRegatta(); - Assert.assertSame(regattaOnTarget, regattaInLeaderboard); - - Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); - - RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); - Assert.assertNotNull(raceColumnOnTarget); - // Check if existing leaderboard didn't survive import - Assert.assertEquals(leaderboard.getDisplayName(), leaderboardOnTarget.getDisplayName()); - Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); - - // Check that tracked race of regatta leaderboard has been removed - Assert.assertNull(destService.getTrackedRace(identifierOfRegattaTrackedRace)); - - // Assert that competitor details were overridden - Competitor competitorOnTarget = destService.getBaseDomainFactory().getExistingCompetitorById(competitorUUID); - Assert.assertEquals(competitor.getName(), competitorOnTarget.getName()); - Assert.assertEquals(competitor.getColor(), competitorOnTarget.getColor()); - - } - - @Test - public void testMasterDataImportForRegattaDefaultProcedureAndDesigner() throws MalformedURLException, IOException, - InterruptedException, ClassNotFoundException { - RacingEventService sourceService = new RacingEventServiceImpl(); - - Event event = sourceService.createEventWithoutReplication("Test Event", /* eventDescription */null, - new MillisecondsTimePoint(0), new MillisecondsTimePoint(10), "testvenue", false, UUID.randomUUID(), - /* officialWebsiteURL */null, /* sailorsInfoWebsiteURL */null, - /* images */Collections. emptyList(), /* videos */ - Collections. emptyList()); - CourseArea defaultCourseArea = sourceService.addCourseAreas(event.getId(), new String[] { "ECHO" }, - new UUID[] { UUID.randomUUID() })[0]; - - Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ - null, /* endDate */null, UUID.randomUUID(), new ArrayList(), true, new LowPoint(), - defaultCourseArea.getId(), /* useStartTimeInference */true, OneDesignRankingMetric::new); - // Let's use the setters directly because we are not testing replication - RegattaConfigurationImpl configuration = new RegattaConfigurationImpl(); - configuration.setDefaultCourseDesignerMode(CourseDesignerMode.BY_MAP); - regatta.setRegattaConfiguration(configuration); - - Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "testDisplayName", new int[] { 1, 2, 3, 4 }); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - destService.getDataImportLock().getProgress(randomUUID).getResult(); - Regatta importedRegatta = destService.getRegattaByName(regatta.getName()); - - assertNotNull(importedRegatta.getRegattaConfiguration()); - assertEquals(CourseDesignerMode.BY_MAP, importedRegatta.getRegattaConfiguration() - .getDefaultCourseDesignerMode()); - } - - @Test - public void testMasterDataImportForRegattaWithoutCourseArea() throws MalformedURLException, IOException, - InterruptedException, ClassNotFoundException { - // Setup source service - RacingEventService sourceService = new RacingEventServiceImpl(); - - Event event = sourceService.createEventWithoutReplication("Test Event", /* eventDescription */null, - new MillisecondsTimePoint(0), new MillisecondsTimePoint(10), "testvenue", false, UUID.randomUUID(), - /* officialWebsiteURL */null, /* sailorsInfoWebsiteURL */null, - /* images */Collections. emptyList(), /* videos */ - Collections. emptyList()); - CourseArea defaultCourseArea = sourceService.addCourseAreas(event.getId(), new String[] { "ECHO" }, - new UUID[] { UUID.randomUUID() })[0]; - - List raceColumnNames = new ArrayList(); - String raceColumnName = "T1"; - raceColumnNames.add(raceColumnName); - raceColumnNames.add("T2"); - List emptyRaceColumnNamesList = Collections.emptyList(); - - List series = new ArrayList(); - List fleets = new ArrayList(); - FleetImpl testFleet1 = new FleetImpl("testFleet1"); - fleets.add(testFleet1); - fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - UUID regattaUUID = UUID.randomUUID(); - - Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), - defaultCourseArea.getId(), /* useStartTimeInference */true, OneDesignRankingMetric::new); - for (String name : raceColumnNames) { - series.get(0).addRaceColumn(name, sourceService); - } - int[] discardRule = { 1, 2, 3, 4 }; - Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "testDisplayName", discardRule); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - - // Set tracked Race with competitors - Set competitors = new HashSet(); - UUID competitorUUID = UUID.randomUUID(); - Set sailors = new HashSet(); - sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), - "Oberhoschy")); - DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), - "Der Lennart halt"); - DynamicTeam team = new TeamImpl("Pros", sailors, coach); - BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitor); - UUID competitorToSuppressUUID = UUID.randomUUID(); - Set sailors2 = new HashSet(); - sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), - "segelt auch mit")); - DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), - "Bester Coach"); - DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitorToSuppress); - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); - - raceColumn.setTrackedRace(testFleet1, trackedRace); - - // Set log event - TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); - raceColumn.getRaceLog(testFleet1).add(logEvent); - storedLogUUIDs.add(logEvent.getId()); - - // Set score correction - double scoreCorrection = 12.0; - leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); - MaxPointsReason maxPointsReason = MaxPointsReason.DNS; - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); - - // Set carried Points - double carriedPoints = 2.0; - leaderboard.setCarriedPoints(competitor, carriedPoints); - - // Set suppressed competitor - leaderboard.setSuppressed(competitorToSuppress, true); - - // Set display name - String nickName = "Angie"; - leaderboard.setDisplayName(competitorToSuppress, nickName); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - // ---Asserts--- - Assert.assertNotNull(creationCount); - - // Check if existing event survived import - Assert.assertNotNull(destService.getRegattaByName(regatta.getName())); - - } - - @Test - public void testMasterDataImportForPersistentRegattaRaceIDsWithoutHttpStack() throws MalformedURLException, - IOException, InterruptedException, ClassNotFoundException { - // Setup source service - RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, - "testVenue", false, eventUUID); - UUID courseAreaUUID = UUID.randomUUID(); - CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); - event.getVenue().addCourseArea(courseArea); - - List raceColumnNames = new ArrayList(); - String raceColumnName = "T1"; - raceColumnNames.add(raceColumnName); - String raceColumnName2 = "T2"; - raceColumnNames.add(raceColumnName2); - final List emptyRaceColumnNamesList = Collections.emptyList(); - - List series = new ArrayList(); - List fleets = new ArrayList(); - FleetImpl testFleet1 = new FleetImpl("testFleet1"); - fleets.add(testFleet1); - fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - event.addRegatta(regatta); - for (String name : raceColumnNames) { - series.get(0).addRaceColumn(name, sourceService); - } - - int[] discardRule = { 1, 2, 3, 4 }; - Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "testDisplayName", discardRule); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - - // Set tracked Race with competitors - Set competitors = new HashSet(); - UUID competitorUUID = UUID.randomUUID(); - Set sailors = new HashSet(); - sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), - "Oberhoschy")); - DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), - "Der Lennart halt"); - DynamicTeam team = new TeamImpl("Pros", sailors, coach); - BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitor); - UUID competitorToSuppressUUID = UUID.randomUUID(); - Set sailors2 = new HashSet(); - sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), - "segelt auch mit")); - DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), - "Bester Coach"); - DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitorToSuppress); - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); - - raceColumn.setTrackedRace(testFleet1, trackedRace); - sourceService.setRegattaForRace(regatta, "dummy"); - sourceService.setRegattaForRace(regatta, "dummy2"); - - // Set log event - TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); - raceColumn.getRaceLog(testFleet1).add(logEvent); - storedLogUUIDs.add(logEvent.getId()); - - // Set score correction - double scoreCorrection = 12.0; - leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); - MaxPointsReason maxPointsReason = MaxPointsReason.DNS; - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); - - // Set carried Points - double carriedPoints = 2.0; - leaderboard.setCarriedPoints(competitor, carriedPoints); - - // Set suppressed competitor - leaderboard.setSuppressed(competitorToSuppress, true); - - // Set display name - String nickName = "Angie"; - leaderboard.setDisplayName(competitorToSuppress, nickName); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - // ---Asserts--- - - Assert.assertNotNull(creationCount); - Event eventOnTarget = destService.getEvent(eventUUID); - Assert.assertNotNull(eventOnTarget); - - Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); - Assert.assertNotNull(regattaOnTarget); - - // Check if dummy race id has been imported to destination service - ConcurrentHashMap map = destService.getPersistentRegattasForRaceIDs(); - Assert.assertEquals(regattaOnTarget, map.get("dummy")); - Assert.assertEquals(regattaOnTarget, map.get("dummy2")); - - // Check if persistent regatta for race id has been persisted - RacingEventServiceImplMock destService2 = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - ConcurrentHashMap map2 = destService2.getPersistentRegattasForRaceIDs(); - Regatta regattaOnTarget2 = destService2.getRegattaByName(TEST_LEADERBOARD_NAME); - Assert.assertEquals(regattaOnTarget2, map2.get("dummy")); - - } - - @Test - public void testMasterDataImportForMediaTracks() throws MalformedURLException, IOException, InterruptedException, - ClassNotFoundException { - // Setup source service - RacingEventService sourceService = new RacingEventServiceImpl(); - Set assignedRaces = new HashSet(); - String regattaName1 = "49er"; - String regattaName2 = "49er FX"; - String missingRegattaName = "Missing Regatta"; - String raceName1 = "R1"; - String raceName2 = "R2"; - String raceName3 = "R3"; - String raceName4 = "R4"; - String raceName5 = "R5"; - String missingRaceName = "Missing Race"; - assignedRaces.add(new RegattaNameAndRaceName(regattaName1, raceName1)); - assignedRaces.add(new RegattaNameAndRaceName(regattaName1, raceName2)); - assignedRaces.add(new RegattaNameAndRaceName(regattaName1, raceName3)); - assignedRaces.add(new RegattaNameAndRaceName(regattaName2, raceName4)); - assignedRaces.add(new RegattaNameAndRaceName(regattaName2, raceName5)); - assignedRaces.add(new RegattaNameAndRaceName(missingRegattaName, missingRaceName)); - MediaTrack trackOnSource = new MediaTrack("testTitle", "http://test/test.mp4", new MillisecondsTimePoint(0), - MillisecondsDurationImpl.ONE_HOUR, MimeType.mp4, assignedRaces); - sourceService.mediaTrackAdded(trackOnSource); - - Collection raceColumnNames = Arrays.asList(raceName1, raceName2, raceName3, raceName4, raceName5); - Regatta regatta = MediaMasterDataExportTest.createTestRegatta(regattaName1, raceColumnNames); - sourceService.addRegattaWithoutReplication(regatta); - int[] discardThresholds = new int[0]; - RegattaLeaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "leaderboard display name", discardThresholds); - Collection raceIdentifiers = Arrays.asList(new RegattaNameAndRaceName(regattaName1, raceName1), - new RegattaNameAndRaceName(regattaName1, raceName2), - new RegattaNameAndRaceName(regattaName1, raceName3), - new RegattaNameAndRaceName(regattaName2, raceName4), - new RegattaNameAndRaceName(regattaName2, raceName5)); - MediaMasterDataExportTest.assignRacesToRegattaLeaderboardColumns(leaderboard, raceIdentifiers); - boolean displayGroupsInReverseOrder = false; - int[] overallLeaderboardDiscardThresholds = new int[0]; - UUID leaderboardGropuUuid = UUID.randomUUID(); - LeaderboardGroup leaderboardGroup = sourceService.addLeaderboardGroup(leaderboardGropuUuid, - "leaderboard group name", "leaderboard group description", "leaderboard group display name", - displayGroupsInReverseOrder, Collections.singletonList(leaderboard.getName()), - overallLeaderboardDiscardThresholds, ScoringSchemeType.LOW_POINT); - - // Serialize - List groupNamesToExport = Collections.singletonList(leaderboardGroup.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - // ---Asserts--- - - Assert.assertNotNull(creationCount); - - Collection targetTracks = destService.getAllMediaTracks(); - - Assert.assertEquals(1, targetTracks.size()); - - MediaTrack trackOnTarget = targetTracks.iterator().next(); - - Assert.assertEquals(trackOnSource.dbId, trackOnTarget.dbId); - - Assert.assertEquals(trackOnSource.url, trackOnTarget.url); - - Assert.assertEquals(trackOnSource.assignedRaces, trackOnTarget.assignedRaces); - - } - - @Test - public void testMasterDataImportWithTwoLgsWithSameLeaderboard() throws MalformedURLException, IOException, - InterruptedException, ClassNotFoundException { - // Setup source service - RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, - "testVenue", false, eventUUID); - UUID courseAreaUUID = UUID.randomUUID(); - CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); - event.getVenue().addCourseArea(courseArea); - - List raceColumnNames = new ArrayList(); - String raceColumnName = "T1"; - raceColumnNames.add(raceColumnName); - raceColumnNames.add("T2"); - final List emptyRaceColumnNamesList = Collections.emptyList(); - - List series = new ArrayList(); - List fleets = new ArrayList(); - FleetImpl testFleet1 = new FleetImpl("testFleet1"); - fleets.add(testFleet1); - fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - event.addRegatta(regatta); - for (String name : raceColumnNames) { - series.get(0).addRaceColumn(name, sourceService); - } - - int[] discardRule = { 1, 2, 3, 4 }; - Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), - "testDisplayName", discardRule); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group1 = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, - "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - LeaderboardGroup group2 = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME2, - "testGroupDesc2", - /* displayName */null, false, leaderboardNames, null, null); - - // Set tracked Race with competitors - Set competitors = new HashSet(); - UUID competitorUUID = UUID.randomUUID(); - Set sailors = new HashSet(); - sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), - "Oberhoschy")); - DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), - "Der Lennart halt"); - DynamicTeam team = new TeamImpl("Pros", sailors, coach); - BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitor); - UUID competitorToSuppressUUID = UUID.randomUUID(); - Set sailors2 = new HashSet(); - sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), - "segelt auch mit")); - DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), - "Bester Coach"); - DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitorToSuppress); - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); - - raceColumn.setTrackedRace(testFleet1, trackedRace); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group1.getName()); - groupNamesToExport.add(group2.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - // Test correct number of creations - Assert.assertNotNull(creationCount); - Assert.assertEquals(1, creationCount.getEventCount()); - Assert.assertEquals(1, creationCount.getRegattaCount()); - Assert.assertEquals(1, creationCount.getLeaderboardCount()); - Assert.assertEquals(2, creationCount.getLeaderboardGroupCount()); - - Event eventOnTarget = destService.getEvent(eventUUID); - Assert.assertNotNull(eventOnTarget); - LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); - Assert.assertNotNull(leaderboardGroupOnTarget); - Assert.assertTrue(leaderboardGroupOnTarget.getLeaderboards().iterator().hasNext()); - LeaderboardGroup leaderboardGroup2OnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME2); - Assert.assertNotNull(leaderboardGroup2OnTarget); - Assert.assertTrue(leaderboardGroup2OnTarget.getLeaderboards().iterator().hasNext()); - - } - - @Test - public void testMasterDataImportWithOverallLeaderboard() throws MalformedURLException, IOException, - InterruptedException, ClassNotFoundException { - // Setup source service - RacingEventService sourceService = new RacingEventServiceImpl(); - - int[] discardRule = { 1, 2, 3, 4 }; - ScoringScheme scheme = new LowPoint(); - List leaderboardNames = new ArrayList(); - LeaderboardGroup sourceGroup = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, - "testGroupDesc", - /* displayName */null, false, leaderboardNames, discardRule, scheme.getType()); - FlexibleLeaderboard sourceLeaderboard1 = new FlexibleLeaderboardImpl("Leaderboard1", null, scheme, null); - sourceService.addLeaderboard(sourceLeaderboard1); - sourceGroup.addLeaderboard(sourceLeaderboard1); - - LeaderboardGroupMetaLeaderboard metaLeaderboard = (LeaderboardGroupMetaLeaderboard) sourceGroup - .getOverallLeaderboard(); - double factor = 2.6; - metaLeaderboard.getRaceColumns().iterator().next().setFactor(factor); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(sourceGroup.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - ByteArrayInputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - // Test correct number of creations - Assert.assertEquals(1, creationCount.getLeaderboardGroupCount()); - - LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); - Assert.assertNotNull(leaderboardGroupOnTarget); - LeaderboardGroupMetaLeaderboard overallLeaderboard = (LeaderboardGroupMetaLeaderboard) leaderboardGroupOnTarget - .getOverallLeaderboard(); - Assert.assertNotNull(overallLeaderboard); - Leaderboard overallLeaderboardRetrievedByName = destService.getLeaderboardByName(overallLeaderboard.getName()); - assertSame(overallLeaderboard, overallLeaderboardRetrievedByName); - - Assert.assertNotNull(overallLeaderboard.getResultDiscardingRule()); - - Assert.assertNotNull(overallLeaderboard.getScoringScheme()); - - Assert.assertEquals(scheme.getType(), overallLeaderboard.getScoringScheme().getType()); - - Assert.assertEquals(3, ((ThresholdBasedResultDiscardingRule) overallLeaderboard.getResultDiscardingRule()) - .getDiscardIndexResultsStartingWithHowManyRaces()[2]); - - Iterable metaColumns = overallLeaderboard.getRaceColumns(); - - RaceColumn metaColumn = metaColumns.iterator().next(); - Assert.assertNotNull(metaColumn); - Assert.assertEquals(factor, metaColumn.getFactor()); - - // Verify that overall leaderboard data has been persisted - RacingEventService persistenceVerifier = new RacingEventServiceImplMock(); - LeaderboardGroup lg = persistenceVerifier.getLeaderboardGroupByName(TEST_GROUP_NAME); - Assert.assertNotNull(lg); - overallLeaderboard = (LeaderboardGroupMetaLeaderboard) lg.getOverallLeaderboard(); - Assert.assertNotNull(overallLeaderboard); - - Assert.assertNotNull(overallLeaderboard.getResultDiscardingRule()); - - Assert.assertNotNull(overallLeaderboard.getScoringScheme()); - - Assert.assertEquals(scheme.getType(), overallLeaderboard.getScoringScheme().getType()); - - Assert.assertEquals(3, ((ThresholdBasedResultDiscardingRule) overallLeaderboard.getResultDiscardingRule()) - .getDiscardIndexResultsStartingWithHowManyRaces()[2]); - - metaColumns = overallLeaderboard.getRaceColumns(); - - metaColumn = metaColumns.iterator().next(); - Assert.assertNotNull(metaColumn); - Assert.assertEquals(factor, metaColumn.getFactor()); - - } - - @Test - public void testMasterDataImportWithFlexibleLeaderboard() throws MalformedURLException, IOException, - InterruptedException, ClassNotFoundException { - // Setup source service - RacingEventService sourceService = new RacingEventServiceImpl(); - UUID courseAreaUUID = UUID.randomUUID(); - - List raceColumnNames = new ArrayList(); - String raceColumnName = "T1"; - raceColumnNames.add(raceColumnName); - raceColumnNames.add("T2"); - final List emptyRaceColumnNamesList = Collections.emptyList(); - - List seriesOnSource = new ArrayList<>(); - List seriesOnTarget = new ArrayList<>(); - List fleets = new ArrayList(); - String testFleet1Name = "testFleet1"; - FleetImpl testFleet1 = new FleetImpl(testFleet1Name); - fleets.add(testFleet1); - fleets.add(new FleetImpl("testFleet2")); - seriesOnSource.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - seriesOnTarget.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); - UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ - null, /* endDate */null, regattaUUID, seriesOnSource, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ - true, OneDesignRankingMetric::new); - for (String name : raceColumnNames) { - seriesOnSource.get(0).addRaceColumn(name, sourceService); - } - double factor = 3.0; - seriesOnSource.get(0).getRaceColumnByName(raceColumnName).setFactor(factor); - - int[] discardRule = { 1, 2, 3, 4 }; - ScoringScheme scoringScheme = new LowPoint(); - String flexLeaderboardName = "FlexName"; - FlexibleLeaderboard leaderboard = sourceService.addFlexibleLeaderboard(flexLeaderboardName, "TestFlex", - discardRule, scoringScheme, courseAreaUUID); - List leaderboardNames = new ArrayList(); - leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */null, false, leaderboardNames, null, null); - - // Set tracked Race with competitors - List competitors = new ArrayList(); - UUID competitorUUID = UUID.randomUUID(); - Set sailors = new HashSet(); - sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), - "Oberhoschy")); - DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), - "Der Lennart halt"); - DynamicTeam team = new TeamImpl("Pros", sailors, coach); - BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitor); - UUID competitorToSuppressUUID = UUID.randomUUID(); - Set sailors2 = new HashSet(); - sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), - "segelt auch mit")); - DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), - "Bester Coach"); - DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); - competitors.add(competitorToSuppress); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); - - leaderboard.addRace(trackedRace, raceColumnName, false); - RaceColumn raceColumnOnLeaderboard = leaderboard.getRaceColumnByName(raceColumnName); - raceColumnOnLeaderboard.setFactor(3.0); - - // Set log event - TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - TimePoint logTimePoint2 = new MillisecondsTimePoint(1372489201000L); - RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); - Fleet defaultFleet = leaderboard.getFleet(null); - raceColumnOnLeaderboard.getRaceLog(defaultFleet).add(logEvent); - Position p = new DegreePosition(3, 3); - Wind wind = new WindImpl(p, logTimePoint2, new KnotSpeedWithBearingImpl(5, new DegreeBearingImpl(12))); - RaceLogWindFixEvent windEvent = new RaceLogWindFixEventImpl(logTimePoint2, author, 2, wind, /* isMagnetic */false); - raceColumnOnLeaderboard.getRaceLog(defaultFleet).add(windEvent); - storedLogUUIDs.add(logEvent.getId()); - storedLogUUIDs.add(windEvent.getId()); - - // Set score correction - double scoreCorrection = 12.0; - leaderboard.getScoreCorrection().correctScore(competitor, raceColumnOnLeaderboard, scoreCorrection); - MaxPointsReason maxPointsReason = MaxPointsReason.DNS; - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumnOnLeaderboard, maxPointsReason); - - // Set carried Points - double carriedPoints = 2.0; - leaderboard.setCarriedPoints(competitor, carriedPoints); - - // Set suppressed competitor - leaderboard.setSuppressed(competitorToSuppress, true); - - // Set display name - String nickName = "Angie"; - leaderboard.setDisplayName(competitorToSuppress, nickName); - - // Serialize - List groupNamesToExport = new ArrayList(); - groupNamesToExport.add(group.getName()); - - RacingEventService destService; - DomainFactory domainFactory; - MasterDataResource resource = new MasterDataResource(); - MasterDataResource spyResource = spyResource(resource, sourceService); - Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); - StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UUID randomUUID = UUID.randomUUID(); - InputStream inputStream = null; - try { - streamingOutput.write(os); - os.flush(); - // Delete all data above from the database, to allow recreating all of it on target server - deleteAllDataFromDatabase(); - // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); - domainFactory = destService.getBaseDomainFactory(); - inputStream = new ByteArrayInputStream(os.toByteArray()); - - MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); - importer.importFromStream(inputStream, randomUUID, false); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } finally { - os.close(); - inputStream.close(); - } - - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) - .getResult(); - - Assert.assertNotNull(creationCount); - LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); - Assert.assertNotNull(leaderboardGroupOnTarget); - Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(flexLeaderboardName); - Assert.assertNotNull(leaderboardOnTarget); - - RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumns().iterator().next(); - Fleet defaultFleetOnTarget = raceColumnOnTarget.getFleets().iterator().next(); - Assert.assertNotNull(raceColumnOnTarget); - Assert.assertNull(raceColumnOnTarget.getTrackedRace(defaultFleetOnTarget)); - - Regatta regattaOnTarget = destService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, seriesOnTarget, true, new LowPoint(), - courseAreaUUID, /* useStartTimeInference */true, OneDesignRankingMetric::new); - - raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, new DummyTrackedRace(raceId, competitors, - regattaOnTarget, null, sourceService.getWindStore())); - - Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); - Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); - Set competitorsCreatedOnTarget = new HashSet(); - competitorsCreatedOnTarget.add(competitorOnTarget); - - Assert.assertEquals(defaultFleetOnTarget, leaderboardOnTarget.getFleet(null)); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, - null, sourceService.getWindStore()); - - raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, trackedRaceForTarget); - - Assert.assertEquals(factor, raceColumnOnTarget.getFactor()); - - // Check for score corrections - Assert.assertEquals( - scoreCorrection, - leaderboardOnTarget.getScoreCorrection().getExplicitScoreCorrection(competitorOnTarget, - raceColumnOnTarget)); - Assert.assertEquals( - maxPointsReason, - leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, - MillisecondsTimePoint.now())); - - // Check for carried points - Assert.assertEquals(carriedPoints, leaderboardOnTarget.getCarriedPoints(competitorOnTarget)); - - // Check for suppressed competitor - Assert.assertTrue(leaderboardOnTarget.getSuppressedCompetitors().iterator().hasNext()); - Competitor suppressedCompetitorOnTarget = domainFactory.getCompetitorStore().getExistingCompetitorById( - competitorToSuppressUUID); - Assert.assertEquals(suppressedCompetitorOnTarget, leaderboardOnTarget.getSuppressedCompetitors().iterator() - .next()); - - // Check for competitor display name - Assert.assertEquals(nickName, leaderboardOnTarget.getDisplayName(suppressedCompetitorOnTarget)); - - // Check for race log event - Assert.assertNotNull(raceColumnOnTarget.getRaceLog(defaultFleetOnTarget).getFirstRawFixAtOrAfter(logTimePoint)); - Assert.assertEquals(logEvent.getId(), raceColumnOnTarget.getRaceLog(defaultFleetOnTarget) - .getFirstRawFixAtOrAfter(logTimePoint).getId()); - Assert.assertNotNull(raceColumnOnTarget.getRaceLog(defaultFleetOnTarget).getFirstFixAtOrAfter(logTimePoint2)); - Assert.assertEquals(wind, ((RaceLogWindFixEvent) raceColumnOnTarget.getRaceLog(defaultFleetOnTarget) - .getFirstFixAtOrAfter(logTimePoint2)).getWindFix()); - - // Check for persisting of race log events: - RacingEventService dest2 = new RacingEventServiceImplMock(); - Leaderboard lb2 = dest2.getLeaderboardByName(flexLeaderboardName); - RaceColumn raceColumn2 = lb2.getRaceColumns().iterator().next(); - RaceLog raceLog2 = raceColumn2.getRaceLog(raceColumn2.getFleets().iterator().next()); - Assert.assertEquals(logEvent.getId(), raceLog2.getFirstRawFixAtOrAfter(logTimePoint).getId()); - } - -} +package com.sap.sailing.server.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; + +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.mongodb.DB; +import com.mongodb.WriteConcern; +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; +import com.sap.sailing.domain.abstractlog.race.CompetitorResults; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; +import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultImpl; +import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl; +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.CourseAreaImpl; +import com.sap.sailing.domain.base.impl.DomainFactoryImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicPerson; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.base.impl.FleetImpl; +import com.sap.sailing.domain.base.impl.NationalityImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.RegattaImpl; +import com.sap.sailing.domain.base.impl.SeriesImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; +import com.sap.sailing.domain.common.CourseDesignerMode; +import com.sap.sailing.domain.common.MasterDataImportObjectCreationCount; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.SpeedWithBearing; +import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.WindSource; +import com.sap.sailing.domain.common.WindSourceType; +import com.sap.sailing.domain.common.impl.DataImportProgressImpl; +import com.sap.sailing.domain.common.impl.DegreeBearingImpl; +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.common.impl.WindImpl; +import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID; +import com.sap.sailing.domain.common.media.MediaTrack; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.domain.common.tracking.GPSFix; +import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; +import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.LowPoint; +import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sailing.domain.persistence.media.MediaDBFactory; +import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; +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.ranking.OneDesignRankingMetric; +import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.WindTrack; +import com.sap.sailing.domain.tracking.impl.EmptyWindStore; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; +import com.sap.sailing.server.gateway.jaxrs.spi.MasterDataResource; +import com.sap.sailing.server.impl.MediaMasterDataExportTest; +import com.sap.sailing.server.impl.RacingEventServiceImpl; +import com.sap.sailing.server.masterdata.DummyTrackedRace; +import com.sap.sailing.server.masterdata.MasterDataImporter; +import com.sap.sse.common.Color; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsDurationImpl; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.common.media.MimeType; +import com.sap.sse.mongodb.MongoDBConfiguration; +import com.sap.sse.mongodb.MongoDBService; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; + +public class MasterDataImportTest { + + private static final String TEST_GROUP_NAME = "testGroup"; + private static final String TEST_EVENT_NAME = "testEvent"; + private static final String TEST_REGATTA_NAME = "testRegatta"; + private static final String TEST_BOAT_CLASS_NAME = "29er"; + private static final String TEST_LEADERBOARD_NAME = "testRegatta (29er)"; + private static final String TEST_GROUP_NAME2 = "testGroup2"; + + private final UUID eventUUID = UUID.randomUUID(); + private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1); + + private final TimePoint eventStartDate = new MillisecondsTimePoint(new Date()); + private final TimePoint eventEndDate = new MillisecondsTimePoint(new Date()); + + private final UUID raceId = UUID.randomUUID(); + + /** + * Log Events created when running test. Will be removed from db at teardown + */ + private Set storedLogUUIDs = new HashSet(); + + @After + public void tearDown() { + deleteAllDataFromDatabase(); + } + + @Before + public void setUp() { + deleteAllDataFromDatabase(); + } + + private T spyResource(T resource, RacingEventService service) { + T spyResource = spy(resource); + + doReturn(service).when(spyResource).getService(); + return spyResource; + } + + private void deleteAllDataFromDatabase() { + MongoDBService service = MongoDBConfiguration.getDefaultTestConfiguration().getService(); + service.getDB().getWriteConcern().fsync(); + service.getDB().dropDatabase(); + } + + @Test + public void testMasterDataImportWithoutHttpStack() throws MalformedURLException, IOException, InterruptedException, + ClassNotFoundException { + // Setup source service + MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory(); + RacingEventService sourceService = new RacingEventServiceImpl(null, null, serviceFinderFactory); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); + UUID courseAreaUUID = UUID.randomUUID(); + CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); + event.getVenue().addCourseArea(courseArea); + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + raceColumnNames.add("T2"); + final List emptyRaceColumnNamesList = Collections.emptyList(); + + List series = new ArrayList(); + List fleets = new ArrayList(); + String testFleet1Name = "testFleet1"; + FleetImpl testFleet1 = new FleetImpl(testFleet1Name); + fleets.add(testFleet1); + fleets.add(new FleetImpl("testFleet2")); + series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + event.addRegatta(regatta); + for (String name : raceColumnNames) { + series.get(0).addRaceColumn(name, sourceService); + } + double factor = 3.0; + series.get(0).getRaceColumnByName(raceColumnName).setFactor(factor); + + int[] discardRule = { 1, 2, 3, 4 }; + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", discardRule); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + event.addLeaderboardGroup(group); + + // Set tracked Race with competitors + List competitors = new ArrayList(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + DynamicTeam team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitor); + UUID competitorToSuppressUUID = UUID.randomUUID(); + Set sailors2 = new HashSet(); + sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), + "segelt auch mit")); + DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), + "Bester Coach"); + DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); + DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitorToSuppress); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + + raceColumn.setTrackedRace(testFleet1, trackedRace); + + // Set log event + TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); + TimePoint logTimePoint2 = new MillisecondsTimePoint(1372489201000L); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, logTimePoint, author, 1, + 0, logTimePoint, RaceLogRaceStatus.SCHEDULED); + raceColumn.getRaceLog(testFleet1).add(logEvent); + Position p = new DegreePosition(3, 3); + Wind wind = new WindImpl(p, logTimePoint2, new KnotSpeedWithBearingImpl(5, new DegreeBearingImpl(12))); + RaceLogWindFixEvent windEvent = new RaceLogWindFixEventImpl(logTimePoint2, logTimePoint2, author, + UUID.randomUUID(), 2, wind, /* isMagnetic */false); + raceColumn.getRaceLog(testFleet1).add(windEvent); + storedLogUUIDs.add(logEvent.getId()); + storedLogUUIDs.add(windEvent.getId()); + + // Set RegattaLog event + TimePoint regattaLogTimepoint = new MillisecondsTimePoint(84392048L); + RegattaLogRegisterCompetitorEvent registerEvent = new RegattaLogRegisterCompetitorEventImpl( + regattaLogTimepoint, regattaLogTimepoint, author, UUID.randomUUID(), competitor); + regatta.getRegattaLog().add(registerEvent); + + // Add some racelogtracking stuff + TimePoint logTimePoint3 = new MillisecondsTimePoint(1372489210000L); + TimePoint logTimePoint4 = new MillisecondsTimePoint(1372489200020L); + DeviceIdentifier deviceIdentifier = new SmartphoneImeiIdentifier("a"); + RegattaLogDeviceCompetitorMappingEvent mappingEvent = new RegattaLogDeviceCompetitorMappingEventImpl( + logTimePoint4, logTimePoint4, author, UUID.randomUUID(), competitor, deviceIdentifier, logTimePoint, + logTimePoint3); + regatta.getRegattaLog().add(mappingEvent); + GPSFix gpsFix = new GPSFixMovingImpl(new DegreePosition(54.333, 10.133), logTimePoint2, + new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(90))); + sourceService.getGPSFixStore().storeFix(deviceIdentifier, gpsFix); + + // Set score correction + double scoreCorrection = 12.0; + leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); + MaxPointsReason maxPointsReason = MaxPointsReason.DNS; + leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); + + // Set carried Points + double carriedPoints = 2.0; + leaderboard.setCarriedPoints(competitor, carriedPoints); + + // Set suppressed competitor + leaderboard.setSuppressed(competitorToSuppress, true); + + // Set display name + String nickName = "Angie"; + leaderboard.setDisplayName(competitorToSuppress, nickName); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + InputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID), serviceFinderFactory); + domainFactory = destService.getBaseDomainFactory(); + DB db = destService.getMongoObjectFactory().getDatabase(); + db.setWriteConcern(WriteConcern.SAFE); + inputStream = new ByteArrayInputStream(os.toByteArray()); + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + Assert.assertNotNull(creationCount); + Event eventOnTarget = destService.getEvent(eventUUID); + Assert.assertNotNull(eventOnTarget); + LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(leaderboardGroupOnTarget); + assertSame(leaderboardGroupOnTarget, eventOnTarget.getLeaderboardGroups().iterator().next()); + Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(leaderboardOnTarget); + Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(regattaOnTarget); + + Assert.assertEquals(false, regattaOnTarget.getAllRaces().iterator().hasNext()); + + Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); + + RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); + Assert.assertNotNull(raceColumnOnTarget); + Assert.assertNull(raceColumnOnTarget.getTrackedRace(raceColumnOnTarget.getFleetByName(testFleet1Name))); + + raceColumnOnTarget.setTrackedRace(raceColumnOnTarget.getFleets().iterator().next(), new DummyTrackedRace( + raceId, competitors, regattaOnTarget, null, sourceService.getWindStore())); + + Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); + Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); + Set competitorsCreatedOnTarget = new HashSet(); + competitorsCreatedOnTarget.add(competitorOnTarget); + + Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + null, sourceService.getWindStore()); + + raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); + + Assert.assertEquals(factor, raceColumnOnTarget.getFactor()); + + Iterable competitorsOnTarget = leaderboardOnTarget.getAllCompetitors(); + Iterator competitorIterator = competitorsOnTarget.iterator(); + Assert.assertTrue(competitorIterator.hasNext()); + Assert.assertEquals(competitorOnTarget, competitorIterator.next()); + + // Check for score corrections + Assert.assertEquals( + scoreCorrection, + leaderboardOnTarget.getScoreCorrection().getExplicitScoreCorrection(competitorOnTarget, + raceColumnOnTarget)); + Assert.assertEquals( + maxPointsReason, + leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, + MillisecondsTimePoint.now())); + + // Check for carried points + Assert.assertEquals(carriedPoints, leaderboardOnTarget.getCarriedPoints(competitorOnTarget)); + + // Check for suppressed competitor + Assert.assertTrue(leaderboardOnTarget.getSuppressedCompetitors().iterator().hasNext()); + Competitor suppressedCompetitorOnTarget = domainFactory.getCompetitorStore().getExistingCompetitorById( + competitorToSuppressUUID); + Assert.assertEquals(suppressedCompetitorOnTarget, leaderboardOnTarget.getSuppressedCompetitors().iterator() + .next()); + + // Check for competitor display name + Assert.assertEquals(nickName, leaderboardOnTarget.getDisplayName(suppressedCompetitorOnTarget)); + + // Check for race log event + Assert.assertNotNull(raceColumnOnTarget.getRaceLog(fleet1OnTarget).getFirstRawFixAtOrAfter(logTimePoint)); + Assert.assertEquals(logEvent.getId(), + raceColumnOnTarget.getRaceLog(fleet1OnTarget).getFirstRawFixAtOrAfter(logTimePoint).getId()); + Assert.assertNotNull(raceColumnOnTarget.getRaceLog(fleet1OnTarget).getFirstFixAtOrAfter(logTimePoint2)); + Assert.assertEquals(wind, ((RaceLogWindFixEvent) raceColumnOnTarget.getRaceLog(fleet1OnTarget) + .getFirstFixAtOrAfter(logTimePoint2)).getWindFix()); + + // Add new event to check persistence of post-import events (see bug 3230) + TimePoint logTimePoint5 = new MillisecondsTimePoint(1372489310000L); + UUID postImportEventId = UUID.randomUUID(); + RaceLogStartTimeEventImpl postImportLogEvent = new RaceLogStartTimeEventImpl(logTimePoint5, logTimePoint5, + author, postImportEventId, 3, logTimePoint5, RaceLogRaceStatus.SCHEDULED); + raceColumnOnTarget.getRaceLog(fleet1OnTarget).add(postImportLogEvent); + + // Check for regatta log event + RegattaLogRegisterCompetitorEvent registerEventOnTarget = (RegattaLogRegisterCompetitorEvent) regattaOnTarget + .getRegattaLog().getFirstFixAtOrAfter(regattaLogTimepoint); + Assert.assertNotNull(registerEventOnTarget); + Assert.assertEquals(registerEvent.getId(), registerEventOnTarget.getId()); + Assert.assertEquals(competitor.getId(), registerEventOnTarget.getCompetitor().getId()); + + // Check for import of racelogtracking fix + Assert.assertTrue(destService.getGPSFixStore().getNumberOfFixes(deviceIdentifier) == 1); + + // Check for persisting of race log events: + RacingEventService dest2 = new RacingEventServiceImplMock(); + Leaderboard lb2 = dest2.getLeaderboardByName(TEST_LEADERBOARD_NAME); + RaceColumn raceColumn2 = lb2.getRaceColumns().iterator().next(); + RaceLog raceLog2 = raceColumn2.getRaceLog(raceColumn2.getFleetByName(fleet1OnTarget.getName())); + Assert.assertEquals(logEvent.getId(), raceLog2.getFirstRawFixAtOrAfter(logTimePoint).getId()); + + RaceLogEvent postImportLogEventFromDB = raceLog2.getFirstRawFixAtOrAfter(logTimePoint5); + Assert.assertEquals(postImportEventId, postImportLogEventFromDB.getId()); + + // Check for persisting of regatta log events + Regatta regattaOnTarget2 = dest2.getRegattaByName(TEST_LEADERBOARD_NAME); + RegattaLogRegisterCompetitorEvent registerEventOnTarget2 = (RegattaLogRegisterCompetitorEvent) regattaOnTarget2 + .getRegattaLog().getFirstFixAtOrAfter(regattaLogTimepoint); + Assert.assertNotNull(registerEventOnTarget2); + Assert.assertEquals(registerEvent.getId(), registerEventOnTarget2.getId()); + } + + @Test + public void testMasterDataImportForScoreCorrections() throws MalformedURLException, IOException, + InterruptedException, ClassNotFoundException { + // Setup source service + RacingEventService sourceService = new RacingEventServiceImpl(); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); + UUID courseAreaUUID = UUID.randomUUID(); + CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); + event.getVenue().addCourseArea(courseArea); + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + raceColumnNames.add("T2"); + final List emptyRaceColumnNamesList = Collections.emptyList(); + + List series = new ArrayList(); + List fleets = new ArrayList(); + FleetImpl testFleet1 = new FleetImpl("testFleet1"); + fleets.add(testFleet1); + fleets.add(new FleetImpl("testFleet2")); + series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + event.addRegatta(regatta); + for (String name : raceColumnNames) { + series.get(0).addRaceColumn(name, sourceService); + } + + int[] discardRule = { 1, 2, 3, 4 }; + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", discardRule); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + + // Set tracked Race with competitors + Set competitors = new HashSet(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + DynamicTeam team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitor); + UUID competitor2UUID = UUID.randomUUID(); + Set sailors2 = new HashSet(); + sailors2.add(new PersonImpl("Test Mustermann", new NationalityImpl("GER"), new Date(645487200000L), "desc")); + DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); + DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); + DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); + CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", Color.RED, null, null, team2, + boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitor2); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + + raceColumn.setTrackedRace(testFleet1, trackedRace); + + // Set log event + TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); + raceColumn.getRaceLog(testFleet1).add(logEvent); + storedLogUUIDs.add(logEvent.getId()); + + // Set score correction + double scoreCorrection = 12.0; + leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); + MaxPointsReason maxPointsReason = MaxPointsReason.DNS; + leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + Assert.assertNotNull(creationCount); + Event eventOnTarget = destService.getEvent(eventUUID); + Assert.assertNotNull(eventOnTarget); + LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(leaderboardGroupOnTarget); + Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(leaderboardOnTarget); + Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(regattaOnTarget); + + Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); + + RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); + Assert.assertNotNull(raceColumnOnTarget); + + Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); + Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); + Competitor competitorOnTarget2 = domainFactory.getCompetitorStore().getExistingCompetitorById(competitor2UUID); + Set competitorsCreatedOnTarget = new HashSet(); + competitorsCreatedOnTarget.add(competitorOnTarget); + + Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + null, sourceService.getWindStore()); + + raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); + + Iterable competitorsOnTarget = leaderboardOnTarget.getAllCompetitors(); + Iterator competitorIterator = competitorsOnTarget.iterator(); + Assert.assertTrue(competitorIterator.hasNext()); + Assert.assertEquals(competitorOnTarget, competitorIterator.next()); + + // Check for score corrections + Assert.assertEquals( + scoreCorrection, + leaderboardOnTarget.getScoreCorrection().getExplicitScoreCorrection(competitorOnTarget, + raceColumnOnTarget)); + Assert.assertEquals( + maxPointsReason, + leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, + MillisecondsTimePoint.now())); + + // Checks if score correction was not set if not set on source + Assert.assertFalse(leaderboardOnTarget.getScoreCorrection().isScoreCorrected(competitorOnTarget2, + raceColumnOnTarget, MillisecondsTimePoint.now())); + } + + @Test + public void testMasterDataImportForWind() throws MalformedURLException, IOException, InterruptedException, + ClassNotFoundException { + // Setup source service + RacingEventService sourceService = new RacingEventServiceImpl(); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); + UUID courseAreaUUID = UUID.randomUUID(); + CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); + event.getVenue().addCourseArea(courseArea); + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + final List emptyRaceColumnNamesList = Collections.emptyList(); + + List series = new ArrayList(); + List fleets = new ArrayList(); + FleetImpl testFleet1 = new FleetImpl("testFleet1"); + fleets.add(testFleet1); + series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName("testRegatta", "29er"), "29er", + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + event.addRegatta(regatta); + for (String name : raceColumnNames) { + series.get(0).addRaceColumn(name, sourceService); + } + + int[] discardRule = { 1, 2, 3, 4 }; + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", discardRule); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + + // Set tracked Race with competitors + Set competitors = new HashSet(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + DynamicTeam team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitor); + + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + DynamicTrackedRegatta trackedRegatta = sourceService.getOrCreateTrackedRegatta(regatta); + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, trackedRegatta, + sourceService.getWindStore()); + regatta.addRace(trackedRace.getRace()); // make sure the competitor is serialized together with the regatta + raceColumn.setTrackedRace(testFleet1, trackedRace); + WindSource windSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION, "Igtimi1"); + WindTrack windTrackOnSource = trackedRace.getOrCreateWindTrack(windSource); + + Position p = new DegreePosition(54, 30); + TimePoint at = new MillisecondsTimePoint(20000); + SpeedWithBearing windSpeedWithBearing = new KnotSpeedWithBearingImpl(20, new DegreeBearingImpl(12)); + windTrackOnSource.add(new WindImpl(p, at, windSpeedWithBearing)); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + Assert.assertNotNull(creationCount); + Event eventOnTarget = destService.getEvent(eventUUID); + Assert.assertNotNull(eventOnTarget); + LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(leaderboardGroupOnTarget); + Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(leaderboardOnTarget); + Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(regattaOnTarget); + + Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); + + RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); + Assert.assertNotNull(raceColumnOnTarget); + + Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); + Set competitorsCreatedOnTarget = new HashSet(); + competitorsCreatedOnTarget.add(competitorOnTarget); + + Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); + DynamicTrackedRegatta trackedRegattaForTarget = destService.getOrCreateTrackedRegatta(regattaOnTarget); + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + trackedRegattaForTarget, sourceService.getWindStore()); + + raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); + + WindTrack windTrackOnDest = trackedRaceForTarget.getOrCreateWindTrack(windSource); + windTrackOnDest.lockForRead(); + try { + Iterable fixes = windTrackOnDest.getFixes(); + Assert.assertNotNull(fixes); + Iterator iterator = fixes.iterator(); + Assert.assertTrue(iterator.hasNext()); + Wind firstWindFix = iterator.next(); + Assert.assertNotNull(firstWindFix); + + Assert.assertFalse(iterator.hasNext()); + } finally { + windTrackOnDest.unlockAfterRead(); + } + + // Reimport again to see if db throws exceptions (see console for error for now, since exception is caught deep + // inside) + try { + streamingOutput.write(os); + os.flush(); + + inputStream = new ByteArrayInputStream(os.toByteArray()); + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + } + + @Test + public void testMasterDataImportForRaceLogEventsReferencingCompetitors() throws MalformedURLException, IOException, + InterruptedException, ClassNotFoundException { + // Setup source service + DomainFactory sourceDomainFactory = new DomainFactoryImpl((srlid) -> null); + RacingEventService sourceService = new RacingEventServiceImpl( + PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, sourceDomainFactory), + PersistenceFactory.INSTANCE.getMongoObjectFactory(MongoDBService.INSTANCE), + MediaDBFactory.INSTANCE.getDefaultMediaDB(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); + UUID courseAreaUUID = UUID.randomUUID(); + CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); + event.getVenue().addCourseArea(courseArea); + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + raceColumnNames.add("T2"); + final List emptyRaceColumnNamesList = Collections.emptyList(); + + List series = new ArrayList(); + List fleets = new ArrayList(); + FleetImpl testFleet1 = new FleetImpl("testFleet1"); + fleets.add(testFleet1); + fleets.add(new FleetImpl("testFleet2")); + series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + event.addRegatta(regatta); + for (String name : raceColumnNames) { + series.get(0).addRaceColumn(name, sourceService); + } + + int[] discardRule = { 1, 2, 3, 4 }; + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", discardRule); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + + // Set tracked Race with competitors + Set competitors = new HashSet(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + DynamicTeam team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", Color.RED, + "noone@nowhere.de", null, team, boat, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ + null, null); + competitors.add(competitor); + UUID competitor2UUID = UUID.randomUUID(); + Set sailors2 = new HashSet(); + sailors2.add(new PersonImpl("Test Mustermann", new NationalityImpl("GER"), new Date(645487200000L), "desc")); + DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); + DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); + DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); + Competitor competitor2 = sourceDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitor2UUID, + "Froderik", Color.RED, "noone@nowhere.de", null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ + null, null); + competitors.add(competitor2); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + + raceColumn.setTrackedRace(testFleet1, trackedRace); + + // Set log event + TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); + raceColumn.getRaceLog(testFleet1).add(logEvent); + storedLogUUIDs.add(logEvent.getId()); + + // Add a competitor-related race log event to ensure that no competitor resolution is attempted while receiving + TimePoint logTimePoint2 = logTimePoint.plus(10); + CompetitorResults positionedCompetitors = new CompetitorResultsImpl(); + positionedCompetitors.add(new CompetitorResultImpl( + competitor.getId(), competitor.getName(), /* rank */ 1, MaxPointsReason.DNS, /* score */ null, /* finishingTime */ null, /* comment */ null)); + positionedCompetitors.add(new CompetitorResultImpl( + competitor2.getId(), competitor2.getName(), /* rank */ 2, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null)); + RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent = new RaceLogFinishPositioningConfirmedEventImpl( + logTimePoint2, author, 1, positionedCompetitors); + raceColumn.getRaceLog(testFleet1).add(finishPositioningConfirmedEvent); + storedLogUUIDs.add(finishPositioningConfirmedEvent.getId()); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + Assert.assertNotNull(creationCount); + Event eventOnTarget = destService.getEvent(eventUUID); + Assert.assertNotNull(eventOnTarget); + LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(leaderboardGroupOnTarget); + Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(leaderboardOnTarget); + Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(regattaOnTarget); + + Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); + + RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); + Assert.assertNotNull(raceColumnOnTarget); + + Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); + Competitor competitorOnTarget = domainFactory.getCompetitorStore().getExistingCompetitorById(competitorUUID); + Set competitorsCreatedOnTarget = new HashSet(); + competitorsCreatedOnTarget.add(competitorOnTarget); + + Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + null, sourceService.getWindStore()); + + raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); + + Iterable competitorsOnTarget = leaderboardOnTarget.getAllCompetitors(); + Iterator competitorIterator = competitorsOnTarget.iterator(); + Assert.assertTrue(competitorIterator.hasNext()); + Assert.assertEquals(competitorOnTarget, competitorIterator.next()); + + // Check for score corrections + Assert.assertEquals( + MaxPointsReason.DNS, + leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, + MillisecondsTimePoint.now())); + } + + @Test + public void testMasterDataImportWithoutOverrideWithoutHttpStack() throws MalformedURLException, IOException, + InterruptedException, ClassNotFoundException { + // Setup source service + RacingEventService sourceService = new RacingEventServiceImpl(); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); + UUID courseAreaUUID = UUID.randomUUID(); + CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); + event.getVenue().addCourseArea(courseArea); + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + raceColumnNames.add("T2"); + List emptyRaceColumnNamesList = Collections.emptyList(); + + List series = new ArrayList(); + List fleets = new ArrayList(); + FleetImpl testFleet1 = new FleetImpl("testFleet1"); + fleets.add(testFleet1); + fleets.add(new FleetImpl("testFleet2")); + series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + event.addRegatta(regatta); + for (String name : raceColumnNames) { + series.get(0).addRaceColumn(name, sourceService); + } + + int[] discardRule = { 1, 2, 3, 4 }; + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", discardRule); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + + // Set tracked Race with competitors + Set competitors = new HashSet(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + DynamicTeam team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitor); + UUID competitorToSuppressUUID = UUID.randomUUID(); + Set sailors2 = new HashSet(); + sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), + "segelt auch mit")); + DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), + "Bester Coach"); + DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); + DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitorToSuppress); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + + raceColumn.setTrackedRace(testFleet1, trackedRace); + + // Set log event + TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); + raceColumn.getRaceLog(testFleet1).add(logEvent); + storedLogUUIDs.add(logEvent.getId()); + + // Set score correction + double scoreCorrection = 12.0; + leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); + MaxPointsReason maxPointsReason = MaxPointsReason.DNS; + leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); + + // Set carried Points + double carriedPoints = 2.0; + leaderboard.setCarriedPoints(competitor, carriedPoints); + + // Set suppressed competitor + leaderboard.setSuppressed(competitorToSuppress, true); + + // Set display name + String nickName = "Angie"; + leaderboard.setDisplayName(competitorToSuppress, nickName); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + String venueNameNotToOverride; + CourseAreaImpl courseAreaNotToOverride; + String raceColumnNameNotToOveride; + RegattaLeaderboard leaderboardNotToOverride; + LeaderboardGroup groupNotToOverride; + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + // Create existing data on target + venueNameNotToOverride = "doNotOverride"; + Event eventNotToOverride = destService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, + eventStartDate, eventEndDate, venueNameNotToOverride, false, eventUUID); + courseAreaNotToOverride = new CourseAreaImpl("testAreaNotToOverride", courseAreaUUID); + eventNotToOverride.getVenue().addCourseArea(courseAreaNotToOverride); + + List raceColumnNamesNotToOverride = new ArrayList(); + raceColumnNameNotToOveride = "T1nottooverride"; + raceColumnNamesNotToOverride.add(raceColumnNameNotToOveride); + emptyRaceColumnNamesList = Collections.emptyList(); + + List seriesNotToOverride = new ArrayList(); + List fleetsNotToOverride = new ArrayList(); + FleetImpl testFleet1NotToOverride = new FleetImpl("testFleet1"); + fleetsNotToOverride.add(testFleet1NotToOverride); + seriesNotToOverride.add(new SeriesImpl("testSeries", false, fleetsNotToOverride, emptyRaceColumnNamesList, + destService)); + Regatta regattaNotToOverride = destService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ + null, /* endDate */null, regattaUUID, seriesNotToOverride, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + event.addRegatta(regattaNotToOverride); + for (String name : raceColumnNamesNotToOverride) { + seriesNotToOverride.get(0).addRaceColumn(name, destService); + } + + leaderboardNotToOverride = destService.addRegattaLeaderboard(regattaNotToOverride.getRegattaIdentifier(), + "testDisplayNameNotToOverride", discardRule); + List leaderboardNamesNotToOverride = new ArrayList(); + leaderboardNamesNotToOverride.add(leaderboardNotToOverride.getName()); + groupNotToOverride = destService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, + "testGroupDescNotToOverride", /* displayName */null, false, leaderboardNamesNotToOverride, null, + null); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + // ---Asserts--- + // Test correct number of creations + Assert.assertNotNull(creationCount); + Assert.assertEquals(0, creationCount.getEventCount()); + Assert.assertEquals(0, creationCount.getRegattaCount()); + Assert.assertEquals(0, creationCount.getLeaderboardCount()); + Assert.assertEquals(0, creationCount.getLeaderboardGroupCount()); + + Event eventOnTarget = destService.getEvent(eventUUID); + Assert.assertNotNull(eventOnTarget); + + // Check if existing event survived import + Assert.assertEquals(venueNameNotToOverride, eventOnTarget.getVenue().getName()); + + // Check if existing course area survived import + Assert.assertEquals(courseAreaNotToOverride.getName(), eventOnTarget.getVenue().getCourseAreas().iterator() + .next().getName()); + LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(leaderboardGroupOnTarget); + // Check if existing leaderboard group survived import + Assert.assertEquals(groupNotToOverride.getDescription(), leaderboardGroupOnTarget.getDescription()); + Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(leaderboardOnTarget); + Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(regattaOnTarget); + + Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); + + RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnNameNotToOveride); + Assert.assertNotNull(raceColumnOnTarget); + // Check if existing leaderboard survived import + Assert.assertEquals(leaderboardNotToOverride.getDisplayName(), leaderboardOnTarget.getDisplayName()); + Assert.assertFalse(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); + + } + + @Test + public void testMasterDataImportWithOverrideWithoutHttpStack() throws MalformedURLException, IOException, + InterruptedException, ClassNotFoundException { + // Setup source service + RacingEventService sourceService = new RacingEventServiceImpl(); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); + UUID courseAreaUUID = UUID.randomUUID(); + CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); + event.getVenue().addCourseArea(courseArea); + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + raceColumnNames.add("T2"); + List emptyRaceColumnNamesList = Collections.emptyList(); + + List series = new ArrayList(); + List fleets = new ArrayList(); + FleetImpl testFleet1 = new FleetImpl("testFleet1"); + fleets.add(testFleet1); + fleets.add(new FleetImpl("testFleet2")); + series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + event.addRegatta(regatta); + for (String name : raceColumnNames) { + series.get(0).addRaceColumn(name, sourceService); + } + + int[] discardRule = { 1, 2, 3, 4 }; + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", discardRule); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + + // Set tracked Race with competitors + Set competitors = new HashSet(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + DynamicTeam team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitor); + UUID competitorToSuppressUUID = UUID.randomUUID(); + Set sailors2 = new HashSet(); + sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), + "segelt auch mit")); + DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), + "Bester Coach"); + DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); + DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitorToSuppress); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + + raceColumn.setTrackedRace(testFleet1, trackedRace); + + // Set log event + TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); + raceColumn.getRaceLog(testFleet1).add(logEvent); + storedLogUUIDs.add(logEvent.getId()); + + // Set score correction + double scoreCorrection = 12.0; + leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); + MaxPointsReason maxPointsReason = MaxPointsReason.DNS; + leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); + + // Set carried Points + double carriedPoints = 2.0; + leaderboard.setCarriedPoints(competitor, carriedPoints); + + // Set suppressed competitor + leaderboard.setSuppressed(competitorToSuppress, true); + + // Set display name + String nickName = "Angie"; + leaderboard.setDisplayName(competitorToSuppress, nickName); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + RegattaAndRaceIdentifier identifierOfRegattaTrackedRace; + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + // Create existing data on target + String venueNameToOverride = "Override"; + Event eventToOverride = destService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, + eventEndDate, venueNameToOverride, false, eventUUID); + CourseArea courseAreaToOverride = new CourseAreaImpl("testAreaToOverride", courseAreaUUID); + eventToOverride.getVenue().addCourseArea(courseAreaToOverride); + + List raceColumnNamesToOverride = new ArrayList(); + String raceColumnNameToOveride = raceColumnName; + raceColumnNamesToOverride.add(raceColumnNameToOveride); + emptyRaceColumnNamesList = Collections.emptyList(); + + List seriesToOverride = new ArrayList(); + List fleetsToOverride = new ArrayList(); + FleetImpl testFleet1ToOverride = new FleetImpl("testFleet1"); + fleetsToOverride.add(testFleet1ToOverride); + seriesToOverride.add(new SeriesImpl("testSeries", false, fleetsToOverride, emptyRaceColumnNamesList, + destService)); + Regatta regattaToOverride = destService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ + null, /* endDate */null, regattaUUID, seriesToOverride, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + event.addRegatta(regattaToOverride); + for (String name : raceColumnNamesToOverride) { + seriesToOverride.get(0).addRaceColumn(name, destService); + } + + // Create competitor with same ID and other details + Set competitorsToOverride = new HashSet(); + Set sailorsToOverride = new HashSet(); + sailorsToOverride.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date( + 645487200000L), "Oberhoschy")); + DynamicPerson coachToOverride = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date( + 645487200000L), "Der Lennart halt"); + DynamicTeam teamToOverride = new TeamImpl("Pros", sailorsToOverride, coachToOverride); + BoatClass boatClassToOverride = new BoatClassImpl("H16", true); + DynamicBoat boatToOverride = new BoatImpl("Wingy", boatClassToOverride, "GER70133"); + String competitorOldName = "oldName"; + Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, + Color.BLUE, "noone@nowhere.de", null, teamToOverride, boatToOverride, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ + null, null); + competitorsToOverride.add(competitorToOverride); + + Leaderboard leaderboardToOverride = destService.addRegattaLeaderboard( + regattaToOverride.getRegattaIdentifier(), "testDisplayNameNotToOverride", discardRule); + TrackedRace trackedRace2 = new DummyTrackedRace(raceId, competitorsToOverride, regattaToOverride, null, + sourceService.getWindStore()); + RaceColumn columnToOverride = leaderboardToOverride.getRaceColumns().iterator().next(); + columnToOverride.setTrackedRace(testFleet1ToOverride, trackedRace2); + identifierOfRegattaTrackedRace = regattaToOverride.getRaceIdentifier(columnToOverride + .getRaceDefinition(testFleet1ToOverride)); + + destService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDescToOverride", /* displayName */ + null, false, new ArrayList(), null, null); + destService.getLeaderboardGroupByName(TEST_GROUP_NAME).addLeaderboard(leaderboardToOverride); + destService.addLeaderboard(leaderboardToOverride); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, true); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + // ---Asserts--- + // Test correct number of creations + Assert.assertNotNull(creationCount); + Assert.assertEquals(1, creationCount.getEventCount()); + Assert.assertEquals(1, creationCount.getRegattaCount()); + Assert.assertEquals(1, creationCount.getLeaderboardCount()); + Assert.assertEquals(1, creationCount.getLeaderboardGroupCount()); + + Event eventOnTarget = destService.getEvent(eventUUID); + Assert.assertNotNull(eventOnTarget); + + // Check if existing event didn't survive import + Assert.assertEquals(event.getVenue().getName(), eventOnTarget.getVenue().getName()); + + // Check if existing course area survive import + Assert.assertEquals(courseArea.getName(), eventOnTarget.getVenue().getCourseAreas().iterator().next().getName()); + LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(leaderboardGroupOnTarget); + // Check if existing leaderboard group didn't survive import + Assert.assertEquals(group.getDescription(), leaderboardGroupOnTarget.getDescription()); + Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(leaderboardOnTarget); + Regatta regattaOnTarget = destService.getRegattaByName(TEST_REGATTA_NAME + " (" + TEST_BOAT_CLASS_NAME + ")"); + Assert.assertNotNull(regattaOnTarget); + + RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboardOnTarget; + Regatta regattaInLeaderboard = regattaLeaderboard.getRegatta(); + Assert.assertSame(regattaOnTarget, regattaInLeaderboard); + + Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId()); + + RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName); + Assert.assertNotNull(raceColumnOnTarget); + // Check if existing leaderboard didn't survive import + Assert.assertEquals(leaderboard.getDisplayName(), leaderboardOnTarget.getDisplayName()); + Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); + + // Check that tracked race of regatta leaderboard has been removed + Assert.assertNull(destService.getTrackedRace(identifierOfRegattaTrackedRace)); + + // Assert that competitor details were overridden + Competitor competitorOnTarget = destService.getBaseDomainFactory().getExistingCompetitorById(competitorUUID); + Assert.assertEquals(competitor.getName(), competitorOnTarget.getName()); + Assert.assertEquals(competitor.getColor(), competitorOnTarget.getColor()); + + } + + @Test + public void testMasterDataImportForRegattaDefaultProcedureAndDesigner() throws MalformedURLException, IOException, + InterruptedException, ClassNotFoundException { + RacingEventService sourceService = new RacingEventServiceImpl(); + + Event event = sourceService.createEventWithoutReplication("Test Event", /* eventDescription */null, + new MillisecondsTimePoint(0), new MillisecondsTimePoint(10), "testvenue", false, UUID.randomUUID(), + /* officialWebsiteURL */null, /* sailorsInfoWebsiteURL */null, + /* images */Collections. emptyList(), /* videos */ + Collections. emptyList()); + CourseArea defaultCourseArea = sourceService.addCourseAreas(event.getId(), new String[] { "ECHO" }, + new UUID[] { UUID.randomUUID() })[0]; + + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ + null, /* endDate */null, UUID.randomUUID(), new ArrayList(), true, new LowPoint(), + defaultCourseArea.getId(), /* useStartTimeInference */true, OneDesignRankingMetric::new); + // Let's use the setters directly because we are not testing replication + RegattaConfigurationImpl configuration = new RegattaConfigurationImpl(); + configuration.setDefaultCourseDesignerMode(CourseDesignerMode.BY_MAP); + regatta.setRegattaConfiguration(configuration); + + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", new int[] { 1, 2, 3, 4 }); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + destService.getDataImportLock().getProgress(randomUUID).getResult(); + Regatta importedRegatta = destService.getRegattaByName(regatta.getName()); + + assertNotNull(importedRegatta.getRegattaConfiguration()); + assertEquals(CourseDesignerMode.BY_MAP, importedRegatta.getRegattaConfiguration() + .getDefaultCourseDesignerMode()); + } + + @Test + public void testMasterDataImportForRegattaWithoutCourseArea() throws MalformedURLException, IOException, + InterruptedException, ClassNotFoundException { + // Setup source service + RacingEventService sourceService = new RacingEventServiceImpl(); + + Event event = sourceService.createEventWithoutReplication("Test Event", /* eventDescription */null, + new MillisecondsTimePoint(0), new MillisecondsTimePoint(10), "testvenue", false, UUID.randomUUID(), + /* officialWebsiteURL */null, /* sailorsInfoWebsiteURL */null, + /* images */Collections. emptyList(), /* videos */ + Collections. emptyList()); + CourseArea defaultCourseArea = sourceService.addCourseAreas(event.getId(), new String[] { "ECHO" }, + new UUID[] { UUID.randomUUID() })[0]; + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + raceColumnNames.add("T2"); + List emptyRaceColumnNamesList = Collections.emptyList(); + + List series = new ArrayList(); + List fleets = new ArrayList(); + FleetImpl testFleet1 = new FleetImpl("testFleet1"); + fleets.add(testFleet1); + fleets.add(new FleetImpl("testFleet2")); + series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), + defaultCourseArea.getId(), /* useStartTimeInference */true, OneDesignRankingMetric::new); + for (String name : raceColumnNames) { + series.get(0).addRaceColumn(name, sourceService); + } + int[] discardRule = { 1, 2, 3, 4 }; + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", discardRule); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + + // Set tracked Race with competitors + Set competitors = new HashSet(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + DynamicTeam team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitor); + UUID competitorToSuppressUUID = UUID.randomUUID(); + Set sailors2 = new HashSet(); + sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), + "segelt auch mit")); + DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), + "Bester Coach"); + DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); + DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitorToSuppress); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + + raceColumn.setTrackedRace(testFleet1, trackedRace); + + // Set log event + TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); + raceColumn.getRaceLog(testFleet1).add(logEvent); + storedLogUUIDs.add(logEvent.getId()); + + // Set score correction + double scoreCorrection = 12.0; + leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); + MaxPointsReason maxPointsReason = MaxPointsReason.DNS; + leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); + + // Set carried Points + double carriedPoints = 2.0; + leaderboard.setCarriedPoints(competitor, carriedPoints); + + // Set suppressed competitor + leaderboard.setSuppressed(competitorToSuppress, true); + + // Set display name + String nickName = "Angie"; + leaderboard.setDisplayName(competitorToSuppress, nickName); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + // ---Asserts--- + Assert.assertNotNull(creationCount); + + // Check if existing event survived import + Assert.assertNotNull(destService.getRegattaByName(regatta.getName())); + + } + + @Test + public void testMasterDataImportForPersistentRegattaRaceIDsWithoutHttpStack() throws MalformedURLException, + IOException, InterruptedException, ClassNotFoundException { + // Setup source service + RacingEventService sourceService = new RacingEventServiceImpl(); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); + UUID courseAreaUUID = UUID.randomUUID(); + CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); + event.getVenue().addCourseArea(courseArea); + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + String raceColumnName2 = "T2"; + raceColumnNames.add(raceColumnName2); + final List emptyRaceColumnNamesList = Collections.emptyList(); + + List series = new ArrayList(); + List fleets = new ArrayList(); + FleetImpl testFleet1 = new FleetImpl("testFleet1"); + fleets.add(testFleet1); + fleets.add(new FleetImpl("testFleet2")); + series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + event.addRegatta(regatta); + for (String name : raceColumnNames) { + series.get(0).addRaceColumn(name, sourceService); + } + + int[] discardRule = { 1, 2, 3, 4 }; + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", discardRule); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + + // Set tracked Race with competitors + Set competitors = new HashSet(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + DynamicTeam team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitor); + UUID competitorToSuppressUUID = UUID.randomUUID(); + Set sailors2 = new HashSet(); + sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), + "segelt auch mit")); + DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), + "Bester Coach"); + DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); + DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitorToSuppress); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + + raceColumn.setTrackedRace(testFleet1, trackedRace); + sourceService.setRegattaForRace(regatta, "dummy"); + sourceService.setRegattaForRace(regatta, "dummy2"); + + // Set log event + TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); + raceColumn.getRaceLog(testFleet1).add(logEvent); + storedLogUUIDs.add(logEvent.getId()); + + // Set score correction + double scoreCorrection = 12.0; + leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection); + MaxPointsReason maxPointsReason = MaxPointsReason.DNS; + leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason); + + // Set carried Points + double carriedPoints = 2.0; + leaderboard.setCarriedPoints(competitor, carriedPoints); + + // Set suppressed competitor + leaderboard.setSuppressed(competitorToSuppress, true); + + // Set display name + String nickName = "Angie"; + leaderboard.setDisplayName(competitorToSuppress, nickName); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + // ---Asserts--- + + Assert.assertNotNull(creationCount); + Event eventOnTarget = destService.getEvent(eventUUID); + Assert.assertNotNull(eventOnTarget); + + Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME); + Assert.assertNotNull(regattaOnTarget); + + // Check if dummy race id has been imported to destination service + ConcurrentHashMap map = destService.getPersistentRegattasForRaceIDs(); + Assert.assertEquals(regattaOnTarget, map.get("dummy")); + Assert.assertEquals(regattaOnTarget, map.get("dummy2")); + + // Check if persistent regatta for race id has been persisted + RacingEventServiceImplMock destService2 = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + ConcurrentHashMap map2 = destService2.getPersistentRegattasForRaceIDs(); + Regatta regattaOnTarget2 = destService2.getRegattaByName(TEST_LEADERBOARD_NAME); + Assert.assertEquals(regattaOnTarget2, map2.get("dummy")); + + } + + @Test + public void testMasterDataImportForMediaTracks() throws MalformedURLException, IOException, InterruptedException, + ClassNotFoundException { + // Setup source service + RacingEventService sourceService = new RacingEventServiceImpl(); + Set assignedRaces = new HashSet(); + String regattaName1 = "49er"; + String regattaName2 = "49er FX"; + String missingRegattaName = "Missing Regatta"; + String raceName1 = "R1"; + String raceName2 = "R2"; + String raceName3 = "R3"; + String raceName4 = "R4"; + String raceName5 = "R5"; + String missingRaceName = "Missing Race"; + assignedRaces.add(new RegattaNameAndRaceName(regattaName1, raceName1)); + assignedRaces.add(new RegattaNameAndRaceName(regattaName1, raceName2)); + assignedRaces.add(new RegattaNameAndRaceName(regattaName1, raceName3)); + assignedRaces.add(new RegattaNameAndRaceName(regattaName2, raceName4)); + assignedRaces.add(new RegattaNameAndRaceName(regattaName2, raceName5)); + assignedRaces.add(new RegattaNameAndRaceName(missingRegattaName, missingRaceName)); + MediaTrack trackOnSource = new MediaTrack("testTitle", "http://test/test.mp4", new MillisecondsTimePoint(0), + MillisecondsDurationImpl.ONE_HOUR, MimeType.mp4, assignedRaces); + sourceService.mediaTrackAdded(trackOnSource); + + Collection raceColumnNames = Arrays.asList(raceName1, raceName2, raceName3, raceName4, raceName5); + Regatta regatta = MediaMasterDataExportTest.createTestRegatta(regattaName1, raceColumnNames); + sourceService.addRegattaWithoutReplication(regatta); + int[] discardThresholds = new int[0]; + RegattaLeaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "leaderboard display name", discardThresholds); + Collection raceIdentifiers = Arrays.asList(new RegattaNameAndRaceName(regattaName1, raceName1), + new RegattaNameAndRaceName(regattaName1, raceName2), + new RegattaNameAndRaceName(regattaName1, raceName3), + new RegattaNameAndRaceName(regattaName2, raceName4), + new RegattaNameAndRaceName(regattaName2, raceName5)); + MediaMasterDataExportTest.assignRacesToRegattaLeaderboardColumns(leaderboard, raceIdentifiers); + boolean displayGroupsInReverseOrder = false; + int[] overallLeaderboardDiscardThresholds = new int[0]; + UUID leaderboardGropuUuid = UUID.randomUUID(); + LeaderboardGroup leaderboardGroup = sourceService.addLeaderboardGroup(leaderboardGropuUuid, + "leaderboard group name", "leaderboard group description", "leaderboard group display name", + displayGroupsInReverseOrder, Collections.singletonList(leaderboard.getName()), + overallLeaderboardDiscardThresholds, ScoringSchemeType.LOW_POINT); + + // Serialize + List groupNamesToExport = Collections.singletonList(leaderboardGroup.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + // ---Asserts--- + + Assert.assertNotNull(creationCount); + + Collection targetTracks = destService.getAllMediaTracks(); + + Assert.assertEquals(1, targetTracks.size()); + + MediaTrack trackOnTarget = targetTracks.iterator().next(); + + Assert.assertEquals(trackOnSource.dbId, trackOnTarget.dbId); + + Assert.assertEquals(trackOnSource.url, trackOnTarget.url); + + Assert.assertEquals(trackOnSource.assignedRaces, trackOnTarget.assignedRaces); + + } + + @Test + public void testMasterDataImportWithTwoLgsWithSameLeaderboard() throws MalformedURLException, IOException, + InterruptedException, ClassNotFoundException { + // Setup source service + RacingEventService sourceService = new RacingEventServiceImpl(); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); + UUID courseAreaUUID = UUID.randomUUID(); + CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); + event.getVenue().addCourseArea(courseArea); + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + raceColumnNames.add("T2"); + final List emptyRaceColumnNamesList = Collections.emptyList(); + + List series = new ArrayList(); + List fleets = new ArrayList(); + FleetImpl testFleet1 = new FleetImpl("testFleet1"); + fleets.add(testFleet1); + fleets.add(new FleetImpl("testFleet2")); + series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + event.addRegatta(regatta); + for (String name : raceColumnNames) { + series.get(0).addRaceColumn(name, sourceService); + } + + int[] discardRule = { 1, 2, 3, 4 }; + Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "testDisplayName", discardRule); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group1 = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, + "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + LeaderboardGroup group2 = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME2, + "testGroupDesc2", + /* displayName */null, false, leaderboardNames, null, null); + + // Set tracked Race with competitors + Set competitors = new HashSet(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + DynamicTeam team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitor); + UUID competitorToSuppressUUID = UUID.randomUUID(); + Set sailors2 = new HashSet(); + sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), + "segelt auch mit")); + DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), + "Bester Coach"); + DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); + DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitorToSuppress); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + + raceColumn.setTrackedRace(testFleet1, trackedRace); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group1.getName()); + groupNamesToExport.add(group2.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + // Test correct number of creations + Assert.assertNotNull(creationCount); + Assert.assertEquals(1, creationCount.getEventCount()); + Assert.assertEquals(1, creationCount.getRegattaCount()); + Assert.assertEquals(1, creationCount.getLeaderboardCount()); + Assert.assertEquals(2, creationCount.getLeaderboardGroupCount()); + + Event eventOnTarget = destService.getEvent(eventUUID); + Assert.assertNotNull(eventOnTarget); + LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(leaderboardGroupOnTarget); + Assert.assertTrue(leaderboardGroupOnTarget.getLeaderboards().iterator().hasNext()); + LeaderboardGroup leaderboardGroup2OnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME2); + Assert.assertNotNull(leaderboardGroup2OnTarget); + Assert.assertTrue(leaderboardGroup2OnTarget.getLeaderboards().iterator().hasNext()); + + } + + @Test + public void testMasterDataImportWithOverallLeaderboard() throws MalformedURLException, IOException, + InterruptedException, ClassNotFoundException { + // Setup source service + RacingEventService sourceService = new RacingEventServiceImpl(); + + int[] discardRule = { 1, 2, 3, 4 }; + ScoringScheme scheme = new LowPoint(); + List leaderboardNames = new ArrayList(); + LeaderboardGroup sourceGroup = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, + "testGroupDesc", + /* displayName */null, false, leaderboardNames, discardRule, scheme.getType()); + FlexibleLeaderboard sourceLeaderboard1 = new FlexibleLeaderboardImpl("Leaderboard1", null, scheme, null); + sourceService.addLeaderboard(sourceLeaderboard1); + sourceGroup.addLeaderboard(sourceLeaderboard1); + + LeaderboardGroupMetaLeaderboard metaLeaderboard = (LeaderboardGroupMetaLeaderboard) sourceGroup + .getOverallLeaderboard(); + double factor = 2.6; + metaLeaderboard.getRaceColumns().iterator().next().setFactor(factor); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(sourceGroup.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + ByteArrayInputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + // Test correct number of creations + Assert.assertEquals(1, creationCount.getLeaderboardGroupCount()); + + LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(leaderboardGroupOnTarget); + LeaderboardGroupMetaLeaderboard overallLeaderboard = (LeaderboardGroupMetaLeaderboard) leaderboardGroupOnTarget + .getOverallLeaderboard(); + Assert.assertNotNull(overallLeaderboard); + Leaderboard overallLeaderboardRetrievedByName = destService.getLeaderboardByName(overallLeaderboard.getName()); + assertSame(overallLeaderboard, overallLeaderboardRetrievedByName); + + Assert.assertNotNull(overallLeaderboard.getResultDiscardingRule()); + + Assert.assertNotNull(overallLeaderboard.getScoringScheme()); + + Assert.assertEquals(scheme.getType(), overallLeaderboard.getScoringScheme().getType()); + + Assert.assertEquals(3, ((ThresholdBasedResultDiscardingRule) overallLeaderboard.getResultDiscardingRule()) + .getDiscardIndexResultsStartingWithHowManyRaces()[2]); + + Iterable metaColumns = overallLeaderboard.getRaceColumns(); + + RaceColumn metaColumn = metaColumns.iterator().next(); + Assert.assertNotNull(metaColumn); + Assert.assertEquals(factor, metaColumn.getFactor()); + + // Verify that overall leaderboard data has been persisted + RacingEventService persistenceVerifier = new RacingEventServiceImplMock(); + LeaderboardGroup lg = persistenceVerifier.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(lg); + overallLeaderboard = (LeaderboardGroupMetaLeaderboard) lg.getOverallLeaderboard(); + Assert.assertNotNull(overallLeaderboard); + + Assert.assertNotNull(overallLeaderboard.getResultDiscardingRule()); + + Assert.assertNotNull(overallLeaderboard.getScoringScheme()); + + Assert.assertEquals(scheme.getType(), overallLeaderboard.getScoringScheme().getType()); + + Assert.assertEquals(3, ((ThresholdBasedResultDiscardingRule) overallLeaderboard.getResultDiscardingRule()) + .getDiscardIndexResultsStartingWithHowManyRaces()[2]); + + metaColumns = overallLeaderboard.getRaceColumns(); + + metaColumn = metaColumns.iterator().next(); + Assert.assertNotNull(metaColumn); + Assert.assertEquals(factor, metaColumn.getFactor()); + + } + + @Test + public void testMasterDataImportWithFlexibleLeaderboard() throws MalformedURLException, IOException, + InterruptedException, ClassNotFoundException { + // Setup source service + RacingEventService sourceService = new RacingEventServiceImpl(); + UUID courseAreaUUID = UUID.randomUUID(); + + List raceColumnNames = new ArrayList(); + String raceColumnName = "T1"; + raceColumnNames.add(raceColumnName); + raceColumnNames.add("T2"); + final List emptyRaceColumnNamesList = Collections.emptyList(); + + List seriesOnSource = new ArrayList<>(); + List seriesOnTarget = new ArrayList<>(); + List fleets = new ArrayList(); + String testFleet1Name = "testFleet1"; + FleetImpl testFleet1 = new FleetImpl(testFleet1Name); + fleets.add(testFleet1); + fleets.add(new FleetImpl("testFleet2")); + seriesOnSource.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + seriesOnTarget.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); + UUID regattaUUID = UUID.randomUUID(); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ + null, /* endDate */null, regattaUUID, seriesOnSource, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); + for (String name : raceColumnNames) { + seriesOnSource.get(0).addRaceColumn(name, sourceService); + } + double factor = 3.0; + seriesOnSource.get(0).getRaceColumnByName(raceColumnName).setFactor(factor); + + int[] discardRule = { 1, 2, 3, 4 }; + ScoringScheme scoringScheme = new LowPoint(); + String flexLeaderboardName = "FlexName"; + FlexibleLeaderboard leaderboard = sourceService.addFlexibleLeaderboard(flexLeaderboardName, "TestFlex", + discardRule, scoringScheme, courseAreaUUID); + List leaderboardNames = new ArrayList(); + leaderboardNames.add(leaderboard.getName()); + LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + + // Set tracked Race with competitors + List competitors = new ArrayList(); + UUID competitorUUID = UUID.randomUUID(); + Set sailors = new HashSet(); + sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), + "Oberhoschy")); + DynamicPerson coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L), + "Der Lennart halt"); + DynamicTeam team = new TeamImpl("Pros", sailors, coach); + BoatClass boatClass = new BoatClassImpl("H16", true); + DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitor); + UUID competitorToSuppressUUID = UUID.randomUUID(); + Set sailors2 = new HashSet(); + sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L), + "segelt auch mit")); + DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), + "Bester Coach"); + DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); + DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + competitors.add(competitorToSuppress); + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + + leaderboard.addRace(trackedRace, raceColumnName, false); + RaceColumn raceColumnOnLeaderboard = leaderboard.getRaceColumnByName(raceColumnName); + raceColumnOnLeaderboard.setFactor(3.0); + + // Set log event + TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); + TimePoint logTimePoint2 = new MillisecondsTimePoint(1372489201000L); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); + Fleet defaultFleet = leaderboard.getFleet(null); + raceColumnOnLeaderboard.getRaceLog(defaultFleet).add(logEvent); + Position p = new DegreePosition(3, 3); + Wind wind = new WindImpl(p, logTimePoint2, new KnotSpeedWithBearingImpl(5, new DegreeBearingImpl(12))); + RaceLogWindFixEvent windEvent = new RaceLogWindFixEventImpl(logTimePoint2, author, 2, wind, /* isMagnetic */false); + raceColumnOnLeaderboard.getRaceLog(defaultFleet).add(windEvent); + storedLogUUIDs.add(logEvent.getId()); + storedLogUUIDs.add(windEvent.getId()); + + // Set score correction + double scoreCorrection = 12.0; + leaderboard.getScoreCorrection().correctScore(competitor, raceColumnOnLeaderboard, scoreCorrection); + MaxPointsReason maxPointsReason = MaxPointsReason.DNS; + leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumnOnLeaderboard, maxPointsReason); + + // Set carried Points + double carriedPoints = 2.0; + leaderboard.setCarriedPoints(competitor, carriedPoints); + + // Set suppressed competitor + leaderboard.setSuppressed(competitorToSuppress, true); + + // Set display name + String nickName = "Angie"; + leaderboard.setDisplayName(competitorToSuppress, nickName); + + // Serialize + List groupNamesToExport = new ArrayList(); + groupNamesToExport.add(group.getName()); + + RacingEventService destService; + DomainFactory domainFactory; + MasterDataResource resource = new MasterDataResource(); + MasterDataResource spyResource = spyResource(resource, sourceService); + Response response = spyResource.getMasterDataByLeaderboardGroups(groupNamesToExport, false, true, false); + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + UUID randomUUID = UUID.randomUUID(); + InputStream inputStream = null; + try { + streamingOutput.write(os); + os.flush(); + // Delete all data above from the database, to allow recreating all of it on target server + deleteAllDataFromDatabase(); + // Import in new service + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)); + domainFactory = destService.getBaseDomainFactory(); + inputStream = new ByteArrayInputStream(os.toByteArray()); + + MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); + importer.importFromStream(inputStream, randomUUID, false); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + os.close(); + inputStream.close(); + } + + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID) + .getResult(); + + Assert.assertNotNull(creationCount); + LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME); + Assert.assertNotNull(leaderboardGroupOnTarget); + Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(flexLeaderboardName); + Assert.assertNotNull(leaderboardOnTarget); + + RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumns().iterator().next(); + Fleet defaultFleetOnTarget = raceColumnOnTarget.getFleets().iterator().next(); + Assert.assertNotNull(raceColumnOnTarget); + Assert.assertNull(raceColumnOnTarget.getTrackedRace(defaultFleetOnTarget)); + + Regatta regattaOnTarget = destService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, seriesOnTarget, true, new LowPoint(), + courseAreaUUID, /* useStartTimeInference */true, OneDesignRankingMetric::new); + + raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, new DummyTrackedRace(raceId, competitors, + regattaOnTarget, null, sourceService.getWindStore())); + + Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); + Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); + Set competitorsCreatedOnTarget = new HashSet(); + competitorsCreatedOnTarget.add(competitorOnTarget); + + Assert.assertEquals(defaultFleetOnTarget, leaderboardOnTarget.getFleet(null)); + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + null, sourceService.getWindStore()); + + raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, trackedRaceForTarget); + + Assert.assertEquals(factor, raceColumnOnTarget.getFactor()); + + // Check for score corrections + Assert.assertEquals( + scoreCorrection, + leaderboardOnTarget.getScoreCorrection().getExplicitScoreCorrection(competitorOnTarget, + raceColumnOnTarget)); + Assert.assertEquals( + maxPointsReason, + leaderboardOnTarget.getScoreCorrection().getMaxPointsReason(competitorOnTarget, raceColumnOnTarget, + MillisecondsTimePoint.now())); + + // Check for carried points + Assert.assertEquals(carriedPoints, leaderboardOnTarget.getCarriedPoints(competitorOnTarget)); + + // Check for suppressed competitor + Assert.assertTrue(leaderboardOnTarget.getSuppressedCompetitors().iterator().hasNext()); + Competitor suppressedCompetitorOnTarget = domainFactory.getCompetitorStore().getExistingCompetitorById( + competitorToSuppressUUID); + Assert.assertEquals(suppressedCompetitorOnTarget, leaderboardOnTarget.getSuppressedCompetitors().iterator() + .next()); + + // Check for competitor display name + Assert.assertEquals(nickName, leaderboardOnTarget.getDisplayName(suppressedCompetitorOnTarget)); + + // Check for race log event + Assert.assertNotNull(raceColumnOnTarget.getRaceLog(defaultFleetOnTarget).getFirstRawFixAtOrAfter(logTimePoint)); + Assert.assertEquals(logEvent.getId(), raceColumnOnTarget.getRaceLog(defaultFleetOnTarget) + .getFirstRawFixAtOrAfter(logTimePoint).getId()); + Assert.assertNotNull(raceColumnOnTarget.getRaceLog(defaultFleetOnTarget).getFirstFixAtOrAfter(logTimePoint2)); + Assert.assertEquals(wind, ((RaceLogWindFixEvent) raceColumnOnTarget.getRaceLog(defaultFleetOnTarget) + .getFirstFixAtOrAfter(logTimePoint2)).getWindFix()); + + // Check for persisting of race log events: + RacingEventService dest2 = new RacingEventServiceImplMock(); + Leaderboard lb2 = dest2.getLeaderboardByName(flexLeaderboardName); + RaceColumn raceColumn2 = lb2.getRaceColumns().iterator().next(); + RaceLog raceLog2 = raceColumn2.getRaceLog(raceColumn2.getFleets().iterator().next()); + Assert.assertEquals(logEvent.getId(), raceLog2.getFirstRawFixAtOrAfter(logTimePoint).getId()); + } + +} diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java index d4e925cb997..9e2bac83960 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java @@ -1,220 +1,220 @@ -package com.sap.sailing.server.test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.UUID; - -import org.junit.Before; -import org.junit.Test; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CourseImpl; -import com.sap.sailing.domain.base.impl.PersonImpl; -import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; -import com.sap.sailing.domain.base.impl.RegattaImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; -import com.sap.sailing.domain.common.RegattaName; -import com.sap.sailing.domain.common.RegattaNameAndRaceName; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.impl.DegreeBearingImpl; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; -import com.sap.sailing.domain.common.impl.WindImpl; -import com.sap.sailing.domain.common.impl.WindSourceImpl; -import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.WindTrack; -import com.sap.sailing.domain.tracking.impl.EmptyWindStore; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.impl.RacingEventServiceImpl; -import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard; -import com.sap.sailing.server.operationaltransformation.AddDefaultRegatta; -import com.sap.sailing.server.operationaltransformation.AddRaceDefinition; -import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn; -import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard; -import com.sap.sailing.server.operationaltransformation.CreateTrackedRace; -import com.sap.sailing.server.operationaltransformation.DisconnectLeaderboardColumnFromTrackedRace; -import com.sap.sailing.server.operationaltransformation.TrackRegatta; -import com.sap.sse.common.Color; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class WindByRaceLogTest { - - private DynamicTrackedRace trackedRace; - private RegattaNameAndRaceName raceIdentifier; - - private RaceColumn raceColumn; - private Fleet defaultFleet; - - private RacingEventService service; - private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1); - - @Before - public void setup() throws Exception { - this.service = new RacingEventServiceImpl(); - - final String boatClassName = "49er"; - // FIXME use master DomainFactory; see bug 592 - final DomainFactory masterDomainFactory = service.getBaseDomainFactory(); - BoatClass boatClass = masterDomainFactory.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */true); - Competitor competitor = createCompetitor(masterDomainFactory); - int[] discardThreshold = {1, 2}; - CreateFlexibleLeaderboard createLeaderboardOperation = new CreateFlexibleLeaderboard("Test Leaderboard", "Test", discardThreshold, new LowPoint(), null); - service.apply(createLeaderboardOperation); - AddColumnToLeaderboard leaderboardColumnOperation = new AddColumnToLeaderboard("R1", "Test Leaderboard", false); - raceColumn = service.apply(leaderboardColumnOperation); - - final String baseRegattaName = "Test Event"; - AddDefaultRegatta addRegattaOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseRegattaName, boatClassName), boatClassName, - /*startDate*/ null, /*endDate*/ null, UUID.randomUUID()); - Regatta regatta = service.apply(addRegattaOperation); - final String raceName = "Test Race"; - final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList()); - RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, Collections.singletonList(competitor)); - AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race); - service.apply(addRaceOperation); - masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingInstruction*/ null)); - raceIdentifier = new RegattaNameAndRaceName(regatta.getName(), raceName); - service.apply(new TrackRegatta(raceIdentifier)); - trackedRace = (DynamicTrackedRace) service.apply(new CreateTrackedRace(raceIdentifier, EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE,/* delayToLiveInMillis */ 5000, - /* millisecondsOverWhichToAverageWind */ 10000, /* millisecondsOverWhichToAverageSpeed */10000)); - trackedRace.setStartOfTrackingReceived(MillisecondsTimePoint.now()); - defaultFleet = Util.get(raceColumn.getFleets(), 0); - } - - private Competitor createCompetitor(final DomainFactory masterDomainFactory) { - return masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor", - (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Sailor 1", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null)}), - new PersonImpl("Sailor 2", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), - new BoatImpl("GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null); - } - - private void attachTrackedRaceToRaceColumn() { - ConnectTrackedRaceToLeaderboardColumn connectColumn = new ConnectTrackedRaceToLeaderboardColumn("Test Leaderboard", "R1", - defaultFleet.getName(), raceIdentifier); - service.apply(connectColumn); - } - - private void detachTrackedRaceFromRaceColumn() { - DisconnectLeaderboardColumnFromTrackedRace disconnectColumn = new DisconnectLeaderboardColumnFromTrackedRace("Test Leaderboard", "R1", defaultFleet.getName()); - service.apply(disconnectColumn); - } - - @Test - public void testAttachingRaceLogContainingWindFixes() { - RaceLog raceLog = raceColumn.getRaceLog(defaultFleet); - TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20); - TimePoint timeMinus2 = MillisecondsTimePoint.now().minus(10); - - Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3, - new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234))); - Wind wind2 = new WindImpl(new DegreePosition(49, 3), timeMinus2, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); - RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false); - RaceLogWindFixEvent windEvent2 = new RaceLogWindFixEventImpl(timeMinus2, author, 0, wind2, /* isMagnetic */ false); - raceLog.add(windEvent1); - raceLog.add(windEvent2); - - attachTrackedRaceToRaceColumn(); - - WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE); - assertTrue(Util.contains(trackedRace.getWindSources(), source)); - - WindTrack windTrack = trackedRace.getOrCreateWindTrack(source); - - try { - windTrack.lockForRead(); - assertTrue(Util.contains(windTrack.getFixes(), wind1)); - assertTrue(Util.contains(windTrack.getFixes(), wind2)); - } finally { - windTrack.unlockAfterRead(); - } - } - - @Test - public void testAttachingRaceLogAndAddWindFixes() { - RaceLog raceLog = raceColumn.getRaceLog(defaultFleet); - TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20); - - attachTrackedRaceToRaceColumn(); - - Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3, - new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234))); - RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false); - raceLog.add(windEvent1); - - WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE); - assertTrue(Util.contains(trackedRace.getWindSources(), source)); - - WindTrack windTrack = trackedRace.getOrCreateWindTrack(source); - - try { - windTrack.lockForRead(); - assertTrue(Util.contains(windTrack.getFixes(), wind1)); - } finally { - windTrack.unlockAfterRead(); - } - } - - @Test - public void testDetachingRaceLogWithWindFixes() { - RaceLog raceLog = raceColumn.getRaceLog(defaultFleet); - TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20); - TimePoint timeMinus2 = MillisecondsTimePoint.now().minus(10); - TimePoint timeMinus1 = MillisecondsTimePoint.now().minus(5); - - Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3, - new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234))); - Wind wind2 = new WindImpl(new DegreePosition(49, 3), timeMinus2, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); - Wind wind3 = new WindImpl(new DegreePosition(48, 1), timeMinus2, - new KnotSpeedWithBearingImpl(18, new DegreeBearingImpl(270))); - RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false); - RaceLogWindFixEvent windEvent2 = new RaceLogWindFixEventImpl(timeMinus2, author, 0, wind2, /* isMagnetic */ false); - RaceLogWindFixEvent windEvent3 = new RaceLogWindFixEventImpl(timeMinus1, author, 0, wind3, /* isMagnetic */ false); - raceLog.add(windEvent1); - raceLog.add(windEvent2); - - attachTrackedRaceToRaceColumn(); - raceLog.add(windEvent3); - detachTrackedRaceFromRaceColumn(); - - WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE); - assertTrue(Util.contains(trackedRace.getWindSources(), source)); - - WindTrack windTrack = trackedRace.getOrCreateWindTrack(source); - - try { - windTrack.lockForRead(); - assertFalse(Util.contains(windTrack.getFixes(), wind1)); - assertFalse(Util.contains(windTrack.getFixes(), wind2)); - assertFalse(Util.contains(windTrack.getFixes(), wind3)); - } finally { - windTrack.unlockAfterRead(); - } - } - -} +package com.sap.sailing.server.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CourseImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; +import com.sap.sailing.domain.base.impl.RegattaImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; +import com.sap.sailing.domain.common.RegattaName; +import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.WindSource; +import com.sap.sailing.domain.common.WindSourceType; +import com.sap.sailing.domain.common.impl.DegreeBearingImpl; +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.common.impl.WindImpl; +import com.sap.sailing.domain.common.impl.WindSourceImpl; +import com.sap.sailing.domain.leaderboard.impl.LowPoint; +import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.WindTrack; +import com.sap.sailing.domain.tracking.impl.EmptyWindStore; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.impl.RacingEventServiceImpl; +import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard; +import com.sap.sailing.server.operationaltransformation.AddDefaultRegatta; +import com.sap.sailing.server.operationaltransformation.AddRaceDefinition; +import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn; +import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard; +import com.sap.sailing.server.operationaltransformation.CreateTrackedRace; +import com.sap.sailing.server.operationaltransformation.DisconnectLeaderboardColumnFromTrackedRace; +import com.sap.sailing.server.operationaltransformation.TrackRegatta; +import com.sap.sse.common.Color; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class WindByRaceLogTest { + + private DynamicTrackedRace trackedRace; + private RegattaNameAndRaceName raceIdentifier; + + private RaceColumn raceColumn; + private Fleet defaultFleet; + + private RacingEventService service; + private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1); + + @Before + public void setup() throws Exception { + this.service = new RacingEventServiceImpl(); + + final String boatClassName = "49er"; + // FIXME use master DomainFactory; see bug 592 + final DomainFactory masterDomainFactory = service.getBaseDomainFactory(); + BoatClass boatClass = masterDomainFactory.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */true); + Competitor competitor = createCompetitor(masterDomainFactory); + int[] discardThreshold = {1, 2}; + CreateFlexibleLeaderboard createLeaderboardOperation = new CreateFlexibleLeaderboard("Test Leaderboard", "Test", discardThreshold, new LowPoint(), null); + service.apply(createLeaderboardOperation); + AddColumnToLeaderboard leaderboardColumnOperation = new AddColumnToLeaderboard("R1", "Test Leaderboard", false); + raceColumn = service.apply(leaderboardColumnOperation); + + final String baseRegattaName = "Test Event"; + AddDefaultRegatta addRegattaOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseRegattaName, boatClassName), boatClassName, + /*startDate*/ null, /*endDate*/ null, UUID.randomUUID()); + Regatta regatta = service.apply(addRegattaOperation); + final String raceName = "Test Race"; + final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList()); + RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, Collections.singletonList(competitor)); + AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race); + service.apply(addRaceOperation); + masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingInstruction*/ null)); + raceIdentifier = new RegattaNameAndRaceName(regatta.getName(), raceName); + service.apply(new TrackRegatta(raceIdentifier)); + trackedRace = (DynamicTrackedRace) service.apply(new CreateTrackedRace(raceIdentifier, EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE,/* delayToLiveInMillis */ 5000, + /* millisecondsOverWhichToAverageWind */ 10000, /* millisecondsOverWhichToAverageSpeed */10000)); + trackedRace.setStartOfTrackingReceived(MillisecondsTimePoint.now()); + defaultFleet = Util.get(raceColumn.getFleets(), 0); + } + + private Competitor createCompetitor(final DomainFactory masterDomainFactory) { + return masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor", + (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Sailor 1", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null)}), + new PersonImpl("Sailor 2", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), + new BoatImpl("GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + } + + private void attachTrackedRaceToRaceColumn() { + ConnectTrackedRaceToLeaderboardColumn connectColumn = new ConnectTrackedRaceToLeaderboardColumn("Test Leaderboard", "R1", + defaultFleet.getName(), raceIdentifier); + service.apply(connectColumn); + } + + private void detachTrackedRaceFromRaceColumn() { + DisconnectLeaderboardColumnFromTrackedRace disconnectColumn = new DisconnectLeaderboardColumnFromTrackedRace("Test Leaderboard", "R1", defaultFleet.getName()); + service.apply(disconnectColumn); + } + + @Test + public void testAttachingRaceLogContainingWindFixes() { + RaceLog raceLog = raceColumn.getRaceLog(defaultFleet); + TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20); + TimePoint timeMinus2 = MillisecondsTimePoint.now().minus(10); + + Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3, + new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234))); + Wind wind2 = new WindImpl(new DegreePosition(49, 3), timeMinus2, + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); + RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent2 = new RaceLogWindFixEventImpl(timeMinus2, author, 0, wind2, /* isMagnetic */ false); + raceLog.add(windEvent1); + raceLog.add(windEvent2); + + attachTrackedRaceToRaceColumn(); + + WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE); + assertTrue(Util.contains(trackedRace.getWindSources(), source)); + + WindTrack windTrack = trackedRace.getOrCreateWindTrack(source); + + try { + windTrack.lockForRead(); + assertTrue(Util.contains(windTrack.getFixes(), wind1)); + assertTrue(Util.contains(windTrack.getFixes(), wind2)); + } finally { + windTrack.unlockAfterRead(); + } + } + + @Test + public void testAttachingRaceLogAndAddWindFixes() { + RaceLog raceLog = raceColumn.getRaceLog(defaultFleet); + TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20); + + attachTrackedRaceToRaceColumn(); + + Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3, + new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234))); + RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false); + raceLog.add(windEvent1); + + WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE); + assertTrue(Util.contains(trackedRace.getWindSources(), source)); + + WindTrack windTrack = trackedRace.getOrCreateWindTrack(source); + + try { + windTrack.lockForRead(); + assertTrue(Util.contains(windTrack.getFixes(), wind1)); + } finally { + windTrack.unlockAfterRead(); + } + } + + @Test + public void testDetachingRaceLogWithWindFixes() { + RaceLog raceLog = raceColumn.getRaceLog(defaultFleet); + TimePoint timeMinus3 = MillisecondsTimePoint.now().minus(20); + TimePoint timeMinus2 = MillisecondsTimePoint.now().minus(10); + TimePoint timeMinus1 = MillisecondsTimePoint.now().minus(5); + + Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3, + new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234))); + Wind wind2 = new WindImpl(new DegreePosition(49, 3), timeMinus2, + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); + Wind wind3 = new WindImpl(new DegreePosition(48, 1), timeMinus2, + new KnotSpeedWithBearingImpl(18, new DegreeBearingImpl(270))); + RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent2 = new RaceLogWindFixEventImpl(timeMinus2, author, 0, wind2, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent3 = new RaceLogWindFixEventImpl(timeMinus1, author, 0, wind3, /* isMagnetic */ false); + raceLog.add(windEvent1); + raceLog.add(windEvent2); + + attachTrackedRaceToRaceColumn(); + raceLog.add(windEvent3); + detachTrackedRaceFromRaceColumn(); + + WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE); + assertTrue(Util.contains(trackedRace.getWindSources(), source)); + + WindTrack windTrack = trackedRace.getOrCreateWindTrack(source); + + try { + windTrack.lockForRead(); + assertFalse(Util.contains(windTrack.getFixes(), wind1)); + assertFalse(Util.contains(windTrack.getFixes(), wind2)); + assertFalse(Util.contains(windTrack.getFixes(), wind3)); + } finally { + windTrack.unlockAfterRead(); + } + } + +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java index f51f0c722d7..87020418d70 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java @@ -1,109 +1,110 @@ -package com.sap.sailing.server.impl; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.net.URI; - -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Nationality; -import com.sap.sailing.domain.base.impl.DomainFactoryImpl; -import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl; -import com.sap.sailing.domain.persistence.DomainObjectFactory; -import com.sap.sailing.domain.persistence.MongoObjectFactory; -import com.sap.sailing.domain.persistence.PersistenceFactory; -import com.sap.sse.common.Color; -import com.sap.sse.common.Duration; -import com.sap.sse.common.TypeBasedServiceFinderFactory; -import com.sap.sse.mongodb.MongoDBService; - -/** - * Manages a persistent set of {@link Competitor}s using a {@link MongoObjectFactory} to update the persistent store, - * and a {@link DomainObjectFactory} for initially filling this store's in-memory representation from the persistent - * store.

- * - * Note that the results of calling {@link CompetitorStore#allowCompetitorResetToDefaults(Competitor)} are not stored - * persistently and therefore will be reset when re-initializing a competitor store from the database. - * - * @author Axel Uhl (d043530) - * - */ -public class PersistentCompetitorStore extends TransientCompetitorStoreImpl implements CompetitorStore { - private static final long serialVersionUID = 9205956018421790908L; - private transient MongoObjectFactory storeTo; - private transient DomainObjectFactory loadFrom; - - /** - * @param clear - * if true, the persistent competitor store is initially cleared, with all persistent - * competitor data removed; use with caution! - */ - public PersistentCompetitorStore(MongoObjectFactory storeTo, boolean clear, - TypeBasedServiceFinderFactory serviceFinderFactory, RaceLogResolver raceLogResolver) { - DomainFactoryImpl baseDomainFactory = new DomainFactoryImpl(this, raceLogResolver); - this.loadFrom = PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, baseDomainFactory, serviceFinderFactory); - this.storeTo = storeTo; - if (clear) { - storeTo.removeAllCompetitors(); - } else { - for (Competitor competitor : loadFrom.loadAllCompetitors()) { - addCompetitorToTransientStore(competitor.getId(), competitor); - } - } - } - - DomainObjectFactory getDomainObjectFactory() { - return loadFrom; - } - - MongoObjectFactory getMongoObjectFactory() { - return storeTo; - } - - DomainFactory getBaseDomainFactory() { - return loadFrom.getBaseDomainFactory(); - } - - /** - * Uses the {@link PersistenceFactory#getDefaultMongoObjectFactory() default DB persistence} to store new competitors. - * Use {@link #setStoreTo} to change this after de-serialization. - */ - private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { - ois.defaultReadObject(); - storeTo = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(); - } - - private void addCompetitorToTransientStore(Serializable id, Competitor competitor) { - super.addNewCompetitor(id, competitor); - } - - @Override - protected void addNewCompetitor(Serializable id, Competitor competitor) { - storeTo.storeCompetitor(competitor); - super.addNewCompetitor(id, competitor); - } - - @Override - public void clear() { - storeTo.removeAllCompetitors(); - super.clear(); - } - - @Override - public void removeCompetitor(Competitor competitor) { - storeTo.removeCompetitor(competitor); - super.removeCompetitor(competitor); - } - - @Override - public Competitor updateCompetitor(String idAsString, String newName, Color newRgbDisplayColor, String newEmail, String newSailId, - Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) { - Competitor result = super.updateCompetitor(idAsString, newName, newRgbDisplayColor, newEmail, newSailId, newNationality, - newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile); - storeTo.storeCompetitor(result); - return result; - } -} +package com.sap.sailing.server.impl; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.net.URI; + +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Nationality; +import com.sap.sailing.domain.base.impl.DomainFactoryImpl; +import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl; +import com.sap.sailing.domain.persistence.DomainObjectFactory; +import com.sap.sailing.domain.persistence.MongoObjectFactory; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; +import com.sap.sse.common.TypeBasedServiceFinderFactory; +import com.sap.sse.mongodb.MongoDBService; + +/** + * Manages a persistent set of {@link Competitor}s using a {@link MongoObjectFactory} to update the persistent store, + * and a {@link DomainObjectFactory} for initially filling this store's in-memory representation from the persistent + * store.

+ * + * Note that the results of calling {@link CompetitorStore#allowCompetitorResetToDefaults(Competitor)} are not stored + * persistently and therefore will be reset when re-initializing a competitor store from the database. + * + * @author Axel Uhl (d043530) + * + */ +public class PersistentCompetitorStore extends TransientCompetitorStoreImpl implements CompetitorStore { + private static final long serialVersionUID = 9205956018421790908L; + private transient MongoObjectFactory storeTo; + private transient DomainObjectFactory loadFrom; + + /** + * @param clear + * if true, the persistent competitor store is initially cleared, with all persistent + * competitor data removed; use with caution! + */ + public PersistentCompetitorStore(MongoObjectFactory storeTo, boolean clear, + TypeBasedServiceFinderFactory serviceFinderFactory, RaceLogResolver raceLogResolver) { + DomainFactoryImpl baseDomainFactory = new DomainFactoryImpl(this, raceLogResolver); + this.loadFrom = PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, baseDomainFactory, serviceFinderFactory); + this.storeTo = storeTo; + if (clear) { + storeTo.removeAllCompetitors(); + } else { + for (Competitor competitor : loadFrom.loadAllCompetitors()) { + addCompetitorToTransientStore(competitor.getId(), competitor); + } + } + } + + DomainObjectFactory getDomainObjectFactory() { + return loadFrom; + } + + MongoObjectFactory getMongoObjectFactory() { + return storeTo; + } + + DomainFactory getBaseDomainFactory() { + return loadFrom.getBaseDomainFactory(); + } + + /** + * Uses the {@link PersistenceFactory#getDefaultMongoObjectFactory() default DB persistence} to store new competitors. + * Use {@link #setStoreTo} to change this after de-serialization. + */ + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + ois.defaultReadObject(); + storeTo = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(); + } + + private void addCompetitorToTransientStore(Serializable id, Competitor competitor) { + super.addNewCompetitor(id, competitor); + } + + @Override + protected void addNewCompetitor(Serializable id, Competitor competitor) { + storeTo.storeCompetitor(competitor); + super.addNewCompetitor(id, competitor); + } + + @Override + public void clear() { + storeTo.removeAllCompetitors(); + super.clear(); + } + + @Override + public void removeCompetitor(Competitor competitor) { + storeTo.removeCompetitor(competitor); + super.removeCompetitor(competitor); + } + + @Override + public Competitor updateCompetitor(String idAsString, String newName, Color newRgbDisplayColor, String newEmail, String newSailId, + Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, + String searchTag) { + Competitor result = super.updateCompetitor(idAsString, newName, newRgbDisplayColor, newEmail, newSailId, newNationality, + newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); + storeTo.storeCompetitor(result); + return result; + } +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index 6d643ae6619..6541b9a4d8c 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -547,7 +547,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes replicate(new UpdateCompetitor(competitor.getId().toString(), competitor.getName(), competitor .getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), - competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile())); + competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), + competitor.getSearchTag())); } }); this.windStore = windStore; @@ -2510,7 +2511,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes competitorStore.getOrCreateCompetitor(dynamicCompetitor.getId(), dynamicCompetitor.getName(), dynamicCompetitor.getColor(), dynamicCompetitor.getEmail(), dynamicCompetitor.getFlagImage(), dynamicCompetitor.getTeam(), dynamicCompetitor.getBoat(), dynamicCompetitor.getTimeOnTimeFactor(), - dynamicCompetitor.getTimeOnDistanceAllowancePerNauticalMile()); + dynamicCompetitor.getTimeOnDistanceAllowancePerNauticalMile(), dynamicCompetitor.getSearchTag()); } logoutput.append("Received " + competitorStore.size() + " NEW competitors\n"); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java index 6e08938c352..78f528c2e90 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java @@ -1,76 +1,78 @@ -package com.sap.sailing.server.operationaltransformation; - -import java.net.URI; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Nationality; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.RacingEventServiceOperation; -import com.sap.sse.common.Color; -import com.sap.sse.common.Duration; - -public class UpdateCompetitor extends AbstractRacingEventServiceOperation { - private static final long serialVersionUID = 1172181354320184263L; - private final String idAsString; - private final String newName; - private final Color newDisplayColor; - private final String newSailId; - private final String newEmail; - private final Nationality newNationality; - private final URI newTeamImageUri; - private final URI newFlagImageUri; - private final Double timeOnTimeFactor; - private final Duration timeOnDistanceAllowancePerNauticalMile; - - /** - * @param idAsString - * Identified the competitor to update - * @param newNationality - * if null, the competitor obtains the "NONE" nationality, usually represented by a white - * flag - */ - public UpdateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail, - String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, - Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) { - super(); - this.idAsString = idAsString; - this.newName = newName; - this.newDisplayColor = newDisplayColor; - this.newSailId = newSailId; - this.newNationality = newNationality; - this.newTeamImageUri = newTeamImageUri; - this.newEmail = newEmail; - this.newFlagImageUri = newFlagImageUri; - this.timeOnTimeFactor = timeOnTimeFactor; - this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; - } - - /** - * {@link #internalApplyTo(RacingEventService)} already replicates the effects - */ - @Override - public boolean isRequiresExplicitTransitiveReplication() { - return false; - } - - @Override - public Competitor internalApplyTo(RacingEventService toState) throws Exception { - Competitor result = toState.getBaseDomainFactory().getCompetitorStore() - .updateCompetitor(idAsString, newName, newDisplayColor, newEmail, newSailId, newNationality, - newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile); - return result; - } - - @Override - public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { - // TODO Auto-generated method stub - return null; - } - - @Override - public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { - // TODO Auto-generated method stub - return null; - } - -} +package com.sap.sailing.server.operationaltransformation; + +import java.net.URI; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Nationality; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.RacingEventServiceOperation; +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +public class UpdateCompetitor extends AbstractRacingEventServiceOperation { + private static final long serialVersionUID = 1172181354320184263L; + private final String idAsString; + private final String newName; + private final Color newDisplayColor; + private final String newSailId; + private final String newEmail; + private final Nationality newNationality; + private final URI newTeamImageUri; + private final URI newFlagImageUri; + private final Double timeOnTimeFactor; + private final Duration timeOnDistanceAllowancePerNauticalMile; + private final String newSearchTag; + + /** + * @param idAsString + * Identified the competitor to update + * @param newNationality + * if null, the competitor obtains the "NONE" nationality, usually represented by a white + * flag + */ + public UpdateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail, + String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, + Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String newSearchTag) { + super(); + this.idAsString = idAsString; + this.newName = newName; + this.newDisplayColor = newDisplayColor; + this.newSailId = newSailId; + this.newNationality = newNationality; + this.newTeamImageUri = newTeamImageUri; + this.newEmail = newEmail; + this.newFlagImageUri = newFlagImageUri; + this.timeOnTimeFactor = timeOnTimeFactor; + this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; + this.newSearchTag = newSearchTag; + } + + /** + * {@link #internalApplyTo(RacingEventService)} already replicates the effects + */ + @Override + public boolean isRequiresExplicitTransitiveReplication() { + return false; + } + + @Override + public Competitor internalApplyTo(RacingEventService toState) throws Exception { + Competitor result = toState.getBaseDomainFactory().getCompetitorStore() + .updateCompetitor(idAsString, newName, newDisplayColor, newEmail, newSailId, newNationality, + newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, newSearchTag); + return result; + } + + @Override + public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { + // TODO Auto-generated method stub + return null; + } + + @Override + public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java b/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java index 391a42d3611..1e46db1ecf2 100755 --- a/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java +++ b/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java @@ -210,7 +210,7 @@ public class StructureImporter { BoatAndTeam boatAndTeam = getBoatAndTeam(idAsString, name, nationality, boatClass); this.baseDomainFactory.convertToCompetitorDTO(this.baseDomainFactory.getOrCreateCompetitor( UUID.fromString(idAsString), name, color, email, flagImage, boatAndTeam.getTeam(), boatAndTeam.getBoat(), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); } else { break; } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/ExpandedListEditorUi.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/ExpandedListEditorUi.java index 179728ff039..4aba7f4ce7a 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/ExpandedListEditorUi.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/ExpandedListEditorUi.java @@ -7,7 +7,6 @@ import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HTMLTable.Cell; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.PushButton; -import com.google.gwt.user.client.ui.ValueBoxBase; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sse.gwt.client.StringMessages; @@ -108,7 +107,10 @@ public abstract class ExpandedListEditorUi extends ListEditorUi valueWidget, ValueType newValue, boolean fireEvents) { + /** + * @param valueWidget a widget returned previously from {@link #createValueWidget(int, Object)} + */ + protected void setValueFromValueWidget(Widget valueWidget, ValueType newValue, boolean fireEvents) { for (int i = 0; i < expandedValuesGrid.getRowCount(); i++) { Widget gridWidget = expandedValuesGrid.getWidget(i, 0); if (gridWidget.getElement() == valueWidget.getElement()) { diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/GenericStringListEditorComposite.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/GenericStringListEditorComposite.java new file mode 100644 index 00000000000..0ce0a584fdc --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/GenericStringListEditorComposite.java @@ -0,0 +1,156 @@ +package com.sap.sse.gwt.client.controls.listedit; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.KeyUpEvent; +import com.google.gwt.event.dom.client.KeyUpHandler; +import com.google.gwt.resources.client.ImageResource; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.MultiWordSuggestOracle; +import com.google.gwt.user.client.ui.SuggestBox; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sse.common.Util; +import com.sap.sse.gwt.client.StringMessages; + +/** + * A list editor that renders values of type {@code ValueType} as {@link String}s and lets the user edit them + * as strings. For this to work, implementing subclasses need to specify the + * + * @author Lukas Niemeier + * @author Axel Uhl (d043530) + * + * @param + */ +public abstract class GenericStringListEditorComposite extends ListEditorComposite { + protected GenericStringListEditorComposite(Iterable initialValues, StringMessages stringMessages, + ImageResource removeImage, Iterable suggestValues) { + super(initialValues, new ExpandedUi(stringMessages, removeImage, suggestValues)); + } + + protected GenericStringListEditorComposite(Iterable initialValues, StringMessages stringMessages, + ImageResource removeImage, Iterable suggestValues, String placeholderTextForAddTextbox) { + super(initialValues, new ExpandedUi(stringMessages, removeImage, suggestValues, placeholderTextForAddTextbox)); + } + + protected GenericStringListEditorComposite(Iterable initialValues, ListEditorUiStrategy activeUi) { + super(initialValues, activeUi); + } + + /** + * Parses a new value provided as string {@code s} into a new object of type {@code ValueType} + */ + abstract protected ValueType parse(String s); + + /** + * Tries to update an existing value {@code valueToUpdate} from the string specification {@code s}. + * If an in-place update works, {@code valueToUpdate} is returned, otherwise a new {@code ValueType} + * object is created using {@link #parse(String)}. + */ + abstract protected ValueType parse(String s, ValueType valueToUpdate); + + /** + * Renders a {@code value} as {@link String} for representation in labels and text input fields. It + * must be symmetric with {@link #parse(String, Object)} such that if in-place updates are generally supported + * by the implementation then {@code toString(parse(s, v)).equals(s)} must be satisfied. + */ + abstract protected String toString(ValueType value); + + public abstract static class CollapsedUi extends CollapsedListEditorUi { + + public CollapsedUi(StringMessages stringMessages, String dialogTitle, ExpandedListEditorUi expandedUi) { + super(stringMessages, dialogTitle, expandedUi); + } + + @Override + protected String getCollapsedValueText(Iterable value) { + StringBuilder valuesText = new StringBuilder(); + for (int i = 0; i < Util.size(value); i++) { + if (i > 0) { + valuesText.append(','); + } + valuesText.append(Util.get(value, i)); + } + String condensedValue = valuesText.toString(); + return condensedValue; + } + } + + public static class ExpandedUi extends ExpandedListEditorUi { + + protected final MultiWordSuggestOracle inputOracle; + protected final String placeholderTextForAddTextbox; + + + public ExpandedUi(StringMessages stringMessages, ImageResource removeImage, Iterable suggestValues) { + this(stringMessages, removeImage, suggestValues, /* placeholderTextForAddTextbox */ null); + } + + public ExpandedUi(StringMessages stringMessages, ImageResource removeImage, Iterable suggestValues, String placeholderTextForAddTextbox) { + super(stringMessages, removeImage, /*canRemoveItems*/true); + this.placeholderTextForAddTextbox = placeholderTextForAddTextbox; + this.inputOracle = new MultiWordSuggestOracle(); + for (String suggestValue : suggestValues) { + inputOracle.add(suggestValue); + } + List defaultSuggestions = new ArrayList<>(); + Util.addAll(suggestValues, defaultSuggestions); + this.inputOracle.setDefaultSuggestionsFromText(defaultSuggestions); + } + + protected GenericStringListEditorComposite getContext() { + return (GenericStringListEditorComposite) context; + } + + @Override + public void setContext(ListEditorComposite context) { + super.setContext(context); + for (final ValueType value : context.getValue()) { + inputOracle.add(getContext().toString(value)); + } + } + + protected SuggestBox createSuggestBox() { + final SuggestBox result = new SuggestBox(inputOracle); + if (placeholderTextForAddTextbox != null) { + result.getElement().setAttribute("placeholder", placeholderTextForAddTextbox); + } + return result; + } + + @Override + protected Widget createAddWidget() { + final SuggestBox inputBox = createSuggestBox(); + inputBox.ensureDebugId("InputSuggestBox"); + final Button addButton = new Button(getStringMessages().add()); + addButton.ensureDebugId("AddButton"); + addButton.setEnabled(false); + addButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + addValue(getContext().parse(inputBox.getValue())); + inputBox.setText(""); + } + }); + inputBox.addKeyUpHandler(new KeyUpHandler() { + @Override + public void onKeyUp(KeyUpEvent event) { + addButton.setEnabled(!inputBox.getValue().isEmpty()); + } + }); + HorizontalPanel panel = new HorizontalPanel(); + panel.add(inputBox); + panel.add(addButton); + return panel; + } + + @Override + protected Widget createValueWidget(int rowIndex, ValueType newValue) { + return new Label(getContext().toString(newValue)); + } + } +} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/GenericStringListInlineEditorComposite.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/GenericStringListInlineEditorComposite.java new file mode 100644 index 00000000000..bc9e6cf73b9 --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/GenericStringListInlineEditorComposite.java @@ -0,0 +1,77 @@ +package com.sap.sse.gwt.client.controls.listedit; + +import java.util.List; + +import com.google.gwt.dom.client.InputElement; +import com.google.gwt.event.dom.client.KeyUpEvent; +import com.google.gwt.event.dom.client.KeyUpHandler; +import com.google.gwt.event.logical.shared.ValueChangeEvent; +import com.google.gwt.event.logical.shared.ValueChangeHandler; +import com.google.gwt.resources.client.ImageResource; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.SuggestBox; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sse.gwt.client.StringMessages; + +/** + * In its expanded view, as opposed to its superclass which renders the values only as {@link Label}, this + * class renders the values as {@link TextBox} and allows users to edit the values in place, without having + * to remove and add them. + */ +public abstract class GenericStringListInlineEditorComposite extends GenericStringListEditorComposite { + public GenericStringListInlineEditorComposite(Iterable initialValues, StringMessages stringMessages, + ImageResource removeImage, List suggestValues, int textBoxSize) { + super(initialValues, new ExpandedUi(stringMessages, removeImage, suggestValues, textBoxSize)); + } + + public GenericStringListInlineEditorComposite(Iterable initialValues, ListEditorUiStrategy activeUi) { + super(initialValues, activeUi); + } + + public static class ExpandedUi extends GenericStringListEditorComposite.ExpandedUi { + private final int textBoxSize; + + public ExpandedUi(StringMessages stringMessages, ImageResource removeImage, List suggestValues, int textBoxSize) { + this(stringMessages, removeImage, suggestValues, /* placeholderTextForAddTextbox */ null, textBoxSize); + } + + public ExpandedUi(StringMessages stringMessages, ImageResource removeImage, List suggestValues, String placeholderTextForAddTextbox, int textBoxSize) { + super(stringMessages, removeImage, suggestValues, placeholderTextForAddTextbox); + this.textBoxSize = textBoxSize; + } + + @Override + protected SuggestBox createSuggestBox() { + SuggestBox result = super.createSuggestBox(); + InputElement inputElement = result.getElement().cast(); + inputElement.setSize(textBoxSize); + return result; + } + + @Override + protected Widget createValueWidget(final int rowIndex, ValueType newValue) { + final TextBox textBox = new TextBox(); + textBox.setVisibleLength(textBoxSize); + textBox.ensureDebugId("ValueTextBox"); + textBox.setValue(getContext().toString(newValue)); + textBox.addKeyUpHandler(new KeyUpHandler() { + @Override + public void onKeyUp(KeyUpEvent event) { + textBox.setFocus(false); + // this ensures that the value is copied into the TextBox.getValue() result and a ChangeEvent is fired + textBox.setFocus(true); + } + }); + textBox.addValueChangeHandler(new ValueChangeHandler() { + @Override + public void onValueChange(ValueChangeEvent event) { + ValueType oldValue = getContext().getValue().get(rowIndex); + ValueType newValue = getContext().parse(event.getValue(), oldValue); + setValueFromValueWidget(textBox, newValue, /* fireEvents */ true); + } + }); + return textBox; + } + } +} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListEditorComposite.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListEditorComposite.java index 56a23608b20..1addb1f7b5f 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListEditorComposite.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListEditorComposite.java @@ -1,23 +1,18 @@ package com.sap.sse.gwt.client.controls.listedit; -import java.util.ArrayList; -import java.util.List; - -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.resources.client.ImageResource; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.MultiWordSuggestOracle; -import com.google.gwt.user.client.ui.SuggestBox; -import com.google.gwt.user.client.ui.Widget; import com.sap.sse.common.Util; import com.sap.sse.gwt.client.StringMessages; -public class StringListEditorComposite extends ListEditorComposite { +/** + * A simple string list editor for {@link String} values with trivial implementations for parsing and + * serializing to strings. + * + * @author Lukas Niemeier + * @author Axel Uhl (d043530) + * + */ +public class StringListEditorComposite extends GenericStringListEditorComposite { public StringListEditorComposite(Iterable initialValues, StringMessages stringMessages, String popupDialogTitle, ImageResource removeImage, Iterable suggestValues) { this(initialValues, stringMessages, popupDialogTitle, removeImage, suggestValues, /* placeholderTextForAddTextbox */ null); @@ -26,113 +21,46 @@ public class StringListEditorComposite extends ListEditorComposite { public StringListEditorComposite(Iterable initialValues, StringMessages stringMessages, String popupDialogTitle, ImageResource removeImage, Iterable suggestValues, String placeholderTextForAddTextbox) { super(initialValues, new CollapsedUi(stringMessages, popupDialogTitle, - new ExpandedUi(stringMessages, removeImage, suggestValues, placeholderTextForAddTextbox))); + new ExpandedUi(stringMessages, removeImage, suggestValues, placeholderTextForAddTextbox))); } public StringListEditorComposite(Iterable initialValues, StringMessages stringMessages, ImageResource removeImage, Iterable suggestValues) { - super(initialValues, new ExpandedUi(stringMessages, removeImage, suggestValues)); + super(initialValues, new ExpandedUi(stringMessages, removeImage, suggestValues)); } public StringListEditorComposite(Iterable initialValues, StringMessages stringMessages, ImageResource removeImage, Iterable suggestValues, String placeholderTextForAddTextbox) { - super(initialValues, new ExpandedUi(stringMessages, removeImage, suggestValues, placeholderTextForAddTextbox)); + super(initialValues, new ExpandedUi(stringMessages, removeImage, suggestValues, placeholderTextForAddTextbox)); } public StringListEditorComposite(Iterable initialValues, ListEditorUiStrategy activeUi) { super(initialValues, activeUi); } - public static class CollapsedUi extends CollapsedListEditorUi { - + public static class CollapsedUi extends GenericStringListEditorComposite.CollapsedUi { public CollapsedUi(StringMessages stringMessages, String dialogTitle, ExpandedListEditorUi expandedUi) { super(stringMessages, dialogTitle, expandedUi); } - @Override - protected String getCollapsedValueText(Iterable value) { - StringBuilder valuesText = new StringBuilder(); - for (int i = 0; i < Util.size(value); i++) { - if (i > 0) { - valuesText.append(','); - } - valuesText.append(Util.get(value, i)); - } - String condensedValue = valuesText.toString(); - return condensedValue; - } - @Override protected ListEditorComposite createExpandedUi(Iterable initialValues, ExpandedListEditorUi ui) { return new StringListEditorComposite(initialValues, ui); } } - public static class ExpandedUi extends ExpandedListEditorUi { + @Override + protected String parse(String s) { + return s; + } - protected final MultiWordSuggestOracle inputOracle; - protected final String placeholderTextForAddTextbox; + @Override + protected String parse(String s, String valueToUpdate) { + return Util.equalsWithNull(valueToUpdate, s) ? valueToUpdate : s; // try to preserve identity where possible + } - - public ExpandedUi(StringMessages stringMessages, ImageResource removeImage, Iterable suggestValues) { - this(stringMessages, removeImage, suggestValues, /* placeholderTextForAddTextbox */ null); - } - - public ExpandedUi(StringMessages stringMessages, ImageResource removeImage, Iterable suggestValues, String placeholderTextForAddTextbox) { - super(stringMessages, removeImage, /*canRemoveItems*/true); - this.placeholderTextForAddTextbox = placeholderTextForAddTextbox; - this.inputOracle = new MultiWordSuggestOracle(); - for (String suggestValue : suggestValues) { - inputOracle.add(suggestValue); - } - List defaultSuggestions = new ArrayList<>(); - Util.addAll(suggestValues, defaultSuggestions); - this.inputOracle.setDefaultSuggestionsFromText(defaultSuggestions); - } - - @Override - public void setContext(ListEditorComposite context) { - super.setContext(context); - inputOracle.addAll(context.getValue()); - } - - protected SuggestBox createSuggestBox() { - final SuggestBox result = new SuggestBox(inputOracle); - if (placeholderTextForAddTextbox != null) { - result.getElement().setAttribute("placeholder", placeholderTextForAddTextbox); - } - return result; - } - - @Override - protected Widget createAddWidget() { - final SuggestBox inputBox = createSuggestBox(); - inputBox.ensureDebugId("InputSuggestBox"); - final Button addButton = new Button(getStringMessages().add()); - addButton.ensureDebugId("AddButton"); - addButton.setEnabled(false); - addButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - addValue(inputBox.getValue()); - inputBox.setText(""); - } - }); - inputBox.addKeyUpHandler(new KeyUpHandler() { - @Override - public void onKeyUp(KeyUpEvent event) { - addButton.setEnabled(!inputBox.getValue().isEmpty()); - } - }); - HorizontalPanel panel = new HorizontalPanel(); - panel.add(inputBox); - panel.add(addButton); - return panel; - } - - @Override - protected Widget createValueWidget(int rowIndex, String newValue) { - return new Label(newValue); - } + @Override + protected String toString(String value) { + return value; } } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListInlineEditorComposite.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListInlineEditorComposite.java index e18f3f67588..4b493449286 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListInlineEditorComposite.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListInlineEditorComposite.java @@ -1,30 +1,15 @@ package com.sap.sse.gwt.client.controls.listedit; -import java.util.List; - -import com.google.gwt.dom.client.InputElement; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.google.gwt.resources.client.ImageResource; -import com.google.gwt.user.client.ui.SuggestBox; +import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; -import com.google.gwt.user.client.ui.Widget; import com.sap.sse.gwt.client.StringMessages; +/** + * In its expanded view, as opposed to its superclass which renders the values only as {@link Label}, this + * class renders the values as {@link TextBox} and allows users to edit the values in place, without having + * to remove and add them. + */ public class StringListInlineEditorComposite extends StringListEditorComposite { - public StringListInlineEditorComposite(List initialValues, StringMessages stringMessages, - String popupDialogTitle, ImageResource removeImage, List suggestValues, int textBoxSize) { - super(initialValues, new CollapsedUi(stringMessages, popupDialogTitle, - new ExpandedUi(stringMessages, removeImage, suggestValues, textBoxSize))); - } - - public StringListInlineEditorComposite(Iterable initialValues, StringMessages stringMessages, - ImageResource removeImage, List suggestValues, int textBoxSize) { - super(initialValues, new ExpandedUi(stringMessages, removeImage, suggestValues, textBoxSize)); - } - public StringListInlineEditorComposite(Iterable initialValues, ListEditorUiStrategy activeUi) { super(initialValues, activeUi); } @@ -39,51 +24,4 @@ public class StringListInlineEditorComposite extends StringListEditorComposite { return new StringListInlineEditorComposite(initialValues, ui); } } - - public static class ExpandedUi extends StringListEditorComposite.ExpandedUi { - private final int textBoxSize; - - public ExpandedUi(StringMessages stringMessages, ImageResource removeImage, List suggestValues, int textBoxSize) { - this(stringMessages, removeImage, suggestValues, /* placeholderTextForAddTextbox */ null, textBoxSize); - } - - public ExpandedUi(StringMessages stringMessages, ImageResource removeImage, List suggestValues, String placeholderTextForAddTextbox, int textBoxSize) { - super(stringMessages, removeImage, suggestValues, placeholderTextForAddTextbox); - this.textBoxSize = textBoxSize; - } - - @Override - protected SuggestBox createSuggestBox() { - SuggestBox result = super.createSuggestBox(); - InputElement inputElement = result.getElement().cast(); - inputElement.setSize(textBoxSize); - return result; - } - - @Override - protected Widget createValueWidget(final int rowIndex, String newValue) { - final TextBox textBox = new TextBox(); - textBox.setVisibleLength(textBoxSize); - textBox.ensureDebugId("ValueTextBox"); - textBox.setValue(newValue); - - textBox.addKeyUpHandler(new KeyUpHandler() { - @Override - public void onKeyUp(KeyUpEvent event) { - textBox.setFocus(false); - // this ensures that the value is copied into the TextBox.getValue() result and a ChangeEvent is fired - textBox.setFocus(true); - } - }); - - textBox.addValueChangeHandler(new ValueChangeHandler() { - @Override - public void onValueChange(ValueChangeEvent event) { - String newValue = event.getValue(); - setValueFromValueWidget(textBox, newValue, true); - } - }); - return textBox; - } - } } diff --git a/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/AbstractSecurityReplicationTest.java b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/AbstractSecurityReplicationTest.java index 97fec10c49c..a6ac180f601 100755 --- a/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/AbstractSecurityReplicationTest.java +++ b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/AbstractSecurityReplicationTest.java @@ -3,18 +3,20 @@ package com.sap.sse.security.replication.test; import java.io.IOException; import java.net.MalformedURLException; +import com.sap.sse.common.mail.MailException; import com.sap.sse.mongodb.MongoDBService; import com.sap.sse.replication.testsupport.AbstractServerReplicationTestSetUp; import com.sap.sse.replication.testsupport.AbstractServerWithSingleServiceReplicationTest; import com.sap.sse.security.SecurityService; import com.sap.sse.security.impl.SecurityServiceImpl; +import com.sap.sse.security.shared.UserManagementException; import com.sap.sse.security.userstore.mongodb.UserStoreImpl; public abstract class AbstractSecurityReplicationTest extends AbstractServerWithSingleServiceReplicationTest { public AbstractSecurityReplicationTest() { super(new SecurityServerReplicationTestSetUp()); } - + public static class SecurityServerReplicationTestSetUp extends AbstractServerReplicationTestSetUp { private MongoDBService mongoDBService; @@ -27,7 +29,8 @@ public abstract class AbstractSecurityReplicationTest extends AbstractServerWith } @Override - protected SecurityServiceImpl createNewMaster() throws MalformedURLException, IOException, InterruptedException { + protected SecurityServiceImpl createNewMaster() throws MalformedURLException, IOException, InterruptedException, + UserManagementException, MailException { SecurityServiceImpl result = new SecurityServiceImpl(new UserStoreImpl()); result.clearReplicaState(); return result; diff --git a/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SecurityServiceInitialLoadTest.java b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SecurityServiceInitialLoadTest.java new file mode 100755 index 00000000000..0f25246a1f0 --- /dev/null +++ b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SecurityServiceInitialLoadTest.java @@ -0,0 +1,50 @@ +package com.sap.sse.security.replication.test; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.net.MalformedURLException; + +import org.junit.Test; + +import com.sap.sse.common.mail.MailException; +import com.sap.sse.replication.testsupport.AbstractServerWithSingleServiceReplicationTest; +import com.sap.sse.security.SecurityService; +import com.sap.sse.security.impl.SecurityServiceImpl; +import com.sap.sse.security.shared.UserManagementException; +import com.sap.sse.security.userstore.mongodb.UserStoreImpl; + +public class SecurityServiceInitialLoadTest extends AbstractServerWithSingleServiceReplicationTest { + private final static String username = "abc"; + private final static String email = "e@mail.com"; + private final static String password = "password"; + private final static String fullName = "Full Name"; + private final static String company = "Company"; + private static String accessToken = "Company"; + + public SecurityServiceInitialLoadTest() { + super(new AbstractSecurityReplicationTest.SecurityServerReplicationTestSetUp() { + @Override + protected SecurityServiceImpl createNewMaster() + throws MalformedURLException, IOException, InterruptedException, UserManagementException, MailException { + final SecurityServiceImpl newMaster = new SecurityServiceImpl(new UserStoreImpl(null, null)); // no persistence + newMaster.clearReplicaState(); + newMaster.createSimpleUser(username, email, password, fullName, company, /* validationBaseURL */ null); + accessToken = newMaster.createAccessToken(username); + return newMaster; + } + }); + } + + @Test + public void simpleMasterTest() { + assertEquals(username, master.getUserByName(username).getName()); + assertEquals(username, master.getUserByAccessToken(accessToken).getName()); + } + + @Test + public void simpleReplicaTest() { + assertEquals(username, replica.getUserByName(username).getName()); + assertEquals(username, replica.getUserByAccessToken(accessToken).getName()); + } +} diff --git a/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SimpleSecurityReplicationTest.java b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SimpleSecurityReplicationTest.java index 97a3fdedb07..72d73daa1e8 100755 --- a/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SimpleSecurityReplicationTest.java +++ b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SimpleSecurityReplicationTest.java @@ -40,6 +40,12 @@ public class SimpleSecurityReplicationTest extends AbstractSecurityReplicationTe assertEquals(emailValidationSecret, replicatedErnie.getValidationSecret()); assertEquals(fullName, replicatedErnie.getFullName()); assertEquals(company, replicatedErnie.getCompany()); + + // check that incremental replication of access token handling works + final String accessToken = master.createAccessToken(username); + replicaReplicator.waitUntilQueueIsEmpty(); + Thread.sleep(3000); + assertEquals(username, replica.getUserByAccessToken(accessToken).getName()); } @Test diff --git a/java/com.sap.sse.security.test/src/com/sap/sse/security/test/UserStoreTest.java b/java/com.sap.sse.security.test/src/com/sap/sse/security/test/UserStoreTest.java new file mode 100644 index 00000000000..2b4c91673e4 --- /dev/null +++ b/java/com.sap.sse.security.test/src/com/sap/sse/security/test/UserStoreTest.java @@ -0,0 +1,44 @@ +package com.sap.sse.security.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sse.security.UserStore; +import com.sap.sse.security.shared.UserManagementException; +import com.sap.sse.security.userstore.mongodb.UserStoreImpl; + +public class UserStoreTest { + private final UserStore userStore = new UserStoreImpl(null, null); + private final String username = "abc"; + private final String email = "e@mail.com"; + private final String accessToken = "ak"; + private final String prefKey = "pk"; + private final String prefValue = "pv"; + + @Before + public void setUp() throws UserManagementException { + userStore.createUser(username, email); + userStore.setAccessToken(username, accessToken); + userStore.setPreference(username, prefKey, prefValue); + } + + @Test + public void testClear() throws UserManagementException { + assertEquals(prefValue, userStore.getPreference(username, prefKey)); + assertEquals(username, userStore.getUserByAccessToken(accessToken).getName()); + userStore.clear(); + assertNull(userStore.getPreference(username, prefKey)); + assertNull(userStore.getUserByAccessToken(accessToken)); + } + + @Test + public void testUpdate() throws UserManagementException { + UserStore newUserStore = new UserStoreImpl(null, null); + newUserStore.replaceContentsFrom(userStore); + assertEquals(prefValue, newUserStore.getPreference(username, prefKey)); + assertEquals(username, newUserStore.getUserByAccessToken(accessToken).getName()); + } +} diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java index 3824e7bce6b..574d38ba348 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java @@ -54,6 +54,10 @@ public class UserStoreImpl implements UserStore { private final transient MongoObjectFactory mongoObjectFactory; public UserStoreImpl() { + this(PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(), PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory()); + } + + public UserStoreImpl(final DomainObjectFactory domainObjectFactory, final MongoObjectFactory mongoObjectFactory) { users = new ConcurrentHashMap<>(); usersByEmail = new ConcurrentHashMap<>(); emailForUsername = new ConcurrentHashMap<>(); @@ -61,36 +65,37 @@ public class UserStoreImpl implements UserStore { settingTypes = new ConcurrentHashMap<>(); usersByAccessToken = new ConcurrentHashMap<>(); preferences = new ConcurrentHashMap<>(); - final DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(); - mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(); - for (Entry> e : domainObjectFactory.loadSettingTypes().entrySet()) { - settingTypes.put(e.getKey(), e.getValue()); - } - for (Entry e : domainObjectFactory.loadSettings().entrySet()) { - settings.put(e.getKey(), e.getValue()); - } - for (Entry> e : domainObjectFactory.loadPreferences().entrySet()) { - preferences.put(e.getKey(), e.getValue()); - } - boolean changed = false; - changed = changed || initSocialSettingsIfEmpty(); - if (changed) { - mongoObjectFactory.storeSettingTypes(settingTypes); - mongoObjectFactory.storeSettings(settings); - } - for (User u : domainObjectFactory.loadAllUsers()) { - users.put(u.getName(), u); - addToUsersByEmail(u); - } - for (Entry> e : preferences.entrySet()) { - if (e.getValue() != null) { - final String accessToken = e.getValue().get(ACCESS_TOKEN_KEY); - if (accessToken != null) { - final User user = users.get(e.getKey()); - if (user != null) { - usersByAccessToken.put(accessToken, user); - } else { - logger.warning("Couldn't find user \""+e.getKey()+"\" for which an access token was found in the preferences"); + this.mongoObjectFactory = mongoObjectFactory; + if (domainObjectFactory != null) { + for (Entry> e : domainObjectFactory.loadSettingTypes().entrySet()) { + settingTypes.put(e.getKey(), e.getValue()); + } + for (Entry e : domainObjectFactory.loadSettings().entrySet()) { + settings.put(e.getKey(), e.getValue()); + } + for (Entry> e : domainObjectFactory.loadPreferences().entrySet()) { + preferences.put(e.getKey(), e.getValue()); + } + boolean changed = false; + changed = changed || initSocialSettingsIfEmpty(); + if (changed) { + mongoObjectFactory.storeSettingTypes(settingTypes); + mongoObjectFactory.storeSettings(settings); + } + for (User u : domainObjectFactory.loadAllUsers()) { + users.put(u.getName(), u); + addToUsersByEmail(u); + } + for (Entry> e : preferences.entrySet()) { + if (e.getValue() != null) { + final String accessToken = e.getValue().get(ACCESS_TOKEN_KEY); + if (accessToken != null) { + final User user = users.get(e.getKey()); + if (user != null) { + usersByAccessToken.put(accessToken, user); + } else { + logger.warning("Couldn't find user \""+e.getKey()+"\" for which an access token was found in the preferences"); + } } } } @@ -105,6 +110,7 @@ public class UserStoreImpl implements UserStore { settingTypes.clear(); users.clear(); usersByEmail.clear(); + usersByAccessToken.clear(); } @Override @@ -115,6 +121,9 @@ public class UserStoreImpl implements UserStore { addToUsersByEmail(user); for (Entry userPref : newUserStore.getAllPreferences(user.getName()).entrySet()) { setPreference(user.getName(), userPref.getKey(), userPref.getValue()); + if (userPref.getKey().equals(ACCESS_TOKEN_KEY)) { + usersByAccessToken.put(userPref.getValue(), user); + } } } for (Entry setting : newUserStore.getAllSettings().entrySet()) { diff --git a/java/target/configuration/logging_debug.properties b/java/target/configuration/logging_debug.properties index e8bf8fcb010..f8c132a67e6 100644 --- a/java/target/configuration/logging_debug.properties +++ b/java/target/configuration/logging_debug.properties @@ -18,6 +18,7 @@ java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter # Overwrite the log leves for specific loggers here com.sap.sailing.level = FINE com.sap.sse.level = FINE +#com.sap.sailing.domain.markpassingcalculation.level = FINEST # log at level FINEST for TransientCompetitorStoreIMpl #com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl.level = FINEST #com.sap.sailing.domain.base.impl.SharedDomainFactoryImpl.level = FINEST diff --git a/mobile/.gitignore b/mobile/.gitignore index 5d970a030c8..eaa5cd3cc18 100644 --- a/mobile/.gitignore +++ b/mobile/.gitignore @@ -1,3 +1,3 @@ com.sap.sailing.android.tracking.app.test-test/bin/ /target -**/build.info \ No newline at end of file +build.info \ No newline at end of file diff --git a/mobile/com.sap.sailing.android.shared/res/values-de/strings.xml b/mobile/com.sap.sailing.android.shared/res/values-de/strings.xml index 3c69e24e5d0..e06c9516444 100644 --- a/mobile/com.sap.sailing.android.shared/res/values-de/strings.xml +++ b/mobile/com.sap.sailing.android.shared/res/values-de/strings.xml @@ -49,4 +49,8 @@ Warnung GPS ist nicht aktiviert. Diese App erfordert GPS Positionen. Möchten Sie GPS in den Einstellungen aktivieren? + + %1$d Events konnten noch nicht gesendet werden.\nLetzter erfolgreicher Versand fand statt %2$s + Derzeit keine unversendeten Events. + \ No newline at end of file diff --git a/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/util/JsonHelper.java b/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/util/JsonHelper.java new file mode 100644 index 00000000000..fce8071f698 --- /dev/null +++ b/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/util/JsonHelper.java @@ -0,0 +1,19 @@ +package com.sap.sailing.android.shared.util; + +import org.json.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +/** + * Helps converting JSON objects coming from the {@code org.json.JSONObject} world, as used in the Android world, + * to the {@code org.json.simple.JSONObject} world. The approach works by naively {@link String}-serializing the + * {@link org.json.JSONObject} and then parsing this {@link String} again using a {@link JSONParser} from the + * {@code org.json.simple} world. + */ +public class JsonHelper { + public static org.json.simple.JSONObject convertToSimple(JSONObject jsonObject) throws ParseException { + String jsonString = jsonObject.toString(); + JSONParser jsonParser = new JSONParser(); + return (org.json.simple.JSONObject) jsonParser.parse(jsonString); + } +} diff --git a/mobile/com.sap.sailing.android.tracking.app/res/values/strings_uss_sailing.xml b/mobile/com.sap.sailing.android.tracking.app/res/values/strings_uss_sailing.xml index 2e210229c85..819858d6e45 100644 --- a/mobile/com.sap.sailing.android.tracking.app/res/values/strings_uss_sailing.xml +++ b/mobile/com.sap.sailing.android.tracking.app/res/values/strings_uss_sailing.xml @@ -1,7 +1,7 @@ - The SAP Sail InSight app supports live tracking of race boats by leveraging mobile phone technology, allowing the ability for friends and fans to follow racing whether onsite or online through live leaderboards and 2D visualization. Following racing sailors can replay their races allowing the opportunity to review performance and optimize strategies all available at: sapsailing.com\n\nSAP supports US Sailing through the implementation of a range of innovative technology solutions, delivering analytics to help teams and sailors improve performance whilst also providing applications to help sailing operations run more efficiently.\n\nAs the national governing body for sailing, US Sailing provides leadership, integrity and growth for the sport including training and education programs for instructors and race officials alongside administration and oversight of competitive sailing across the country. - sapsailing.com + The SAP Sail InSight app supports live tracking of race boats by leveraging mobile phone technology, allowing the ability for friends and fans to follow racing whether onsite or online through live leaderboards and 2D visualization. Following racing sailors can replay their races allowing the opportunity to review performance and optimize strategies all available at: https://www.sapsailing.com\n\nSAP supports US Sailing through the implementation of a range of innovative technology solutions, delivering analytics to help teams and sailors improve performance whilst also providing applications to help sailing operations run more efficiently.\n\nAs the national governing body for sailing, US Sailing provides leadership, integrity and growth for the sport including training and education programs for instructors and race officials alongside administration and oversight of competitive sailing across the country. + https://www.sapsailing.com \ No newline at end of file diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/fragments/AboutFragment.java b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/fragments/AboutFragment.java index 46bcd166725..e4d95177fbd 100644 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/fragments/AboutFragment.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/fragments/AboutFragment.java @@ -74,7 +74,7 @@ public class AboutFragment extends com.sap.sailing.android.ui.fragments.BaseFrag ClickableSpan clickableSpan = new ClickableSpan() { @Override public void onClick(View widget) { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://" + url)); + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(browserIntent); } }; diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/adapter/MarkAdapter.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/adapter/MarkAdapter.java index a50a01839e4..721c2a3753c 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/adapter/MarkAdapter.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/adapter/MarkAdapter.java @@ -1,18 +1,19 @@ package com.sap.sailing.android.buoy.positioning.app.adapter; +import java.text.DecimalFormat; +import java.util.List; + import android.content.Context; import android.database.Cursor; import android.support.v4.widget.ResourceCursorAdapter; import android.view.View; import android.widget.TextView; + import com.sap.sailing.android.buoy.positioning.app.R; import com.sap.sailing.android.buoy.positioning.app.provider.AnalyticsContract; import com.sap.sailing.android.buoy.positioning.app.util.DatabaseHelper; import com.sap.sailing.android.buoy.positioning.app.valueobjects.MarkPingInfo; -import java.text.DecimalFormat; -import java.util.List; - public class MarkAdapter extends ResourceCursorAdapter { public MarkAdapter(Context context, int layout, Cursor cursor, int flags) { @@ -21,21 +22,19 @@ public class MarkAdapter extends ResourceCursorAdapter { @Override public void bindView(View view, Context context, Cursor cursor) { - TextView markName = (TextView) view.findViewById(R.id.mark_name); - TextView markSet = (TextView) view.findViewById(R.id.mark_set); - String name = cursor.getString(cursor.getColumnIndex(AnalyticsContract.Mark.MARK_NAME)); - String markID = cursor.getString(cursor.getColumnIndex(AnalyticsContract.Mark.MARK_ID)); - List markPings = DatabaseHelper.getInstance().getMarkPings(context, markID); - String setText = ""; + final TextView markName = (TextView) view.findViewById(R.id.mark_name); + final TextView markSet = (TextView) view.findViewById(R.id.mark_set); + final String name = cursor.getString(cursor.getColumnIndex(AnalyticsContract.Mark.MARK_NAME)); + final String markID = cursor.getString(cursor.getColumnIndex(AnalyticsContract.Mark.MARK_ID)); + final List markPings = DatabaseHelper.getInstance().getMarkPings(context, markID); + final String setText; if (markPings.isEmpty()) { setText = context.getString(R.string.not_set); } else { - DecimalFormat df = new DecimalFormat("#.##"); - setText = context.getString(R.string.set); - double accuracy = markPings.get(0).getAccuracy(); - String accuracyString = context.getString(R.string.mark_list_accuracy); - accuracyString = String.format(accuracyString, df.format(accuracy)); - setText += " " + accuracyString; + final DecimalFormat df = new DecimalFormat("#.##"); + final double accuracy = markPings.get(0).getAccuracy(); + final String accuracyString = String.format(context.getString(R.string.mark_list_accuracy), df.format(accuracy)); + setText = context.getString(R.string.set) + " " + accuracyString; } markName.setText(name); markSet.setText(setText); diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/adapter/RegattaAdapter.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/adapter/RegattaAdapter.java index d723a1d29db..14b85fcfdf8 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/adapter/RegattaAdapter.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/adapter/RegattaAdapter.java @@ -20,9 +20,6 @@ public class RegattaAdapter extends AbstractRegattaAdapter { if (name != null) { String text = cursor.getString(cursor.getColumnIndex(AnalyticsContract.Leaderboard.LEADERBOARD_NAME)); name.setText(text); - // String digestString = - // cursor.getString(cursor.getColumnIndex(AnalyticsContract.Leaderboard.LEADERBOARD_CHECKIN_DIGEST)); - // System.out.println("BENNET: " + digestString); } } } diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/ui/activities/PositioningActivity.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/ui/activities/PositioningActivity.java index 56aca3f9bc0..1fa2b99306e 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/ui/activities/PositioningActivity.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/ui/activities/PositioningActivity.java @@ -23,7 +23,7 @@ public class PositioningActivity extends BaseActivity implements pingListener { private MarkInfo markInfo; private MarkPingInfo markPing; private LeaderboardInfo leaderBoard; - private String markerID; + private String markIdAsString; private String checkinDigest; @Override @@ -31,7 +31,7 @@ public class PositioningActivity extends BaseActivity implements pingListener { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_container); Intent intent = getIntent(); - markerID = intent.getExtras().getString(getString(R.string.mark_id)); + markIdAsString = intent.getExtras().getString(getString(R.string.mark_id)); checkinDigest = intent.getExtras().getString(getString(R.string.checkin_digest)); loadDataFromDatabase(); @@ -60,13 +60,13 @@ public class PositioningActivity extends BaseActivity implements pingListener { List marks = DatabaseHelper.getInstance().getMarks(this, checkinDigest); setLeaderBoard(DatabaseHelper.getInstance().getLeaderboard(this, checkinDigest)); for (MarkInfo mark : marks) { - if (mark.getId().equals(markerID)) { + if (mark.getId().toString().equals(markIdAsString)) { setMarkInfo(mark); break; } } if (markInfo != null) { - setPingFromDatabase(markerID); + setPingFromDatabase(markIdAsString); } } @@ -139,6 +139,6 @@ public class PositioningActivity extends BaseActivity implements pingListener { @Override public void updatePing() { - setPingFromDatabase(markInfo.getId()); + setPingFromDatabase(markInfo.getId().toString()); } } diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/ui/fragments/RegattaFragment.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/ui/fragments/RegattaFragment.java index 43d8f23890c..914649f24b9 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/ui/fragments/RegattaFragment.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/ui/fragments/RegattaFragment.java @@ -111,11 +111,9 @@ public class RegattaFragment extends BaseFragment implements LoaderCallbacks parent, View view, int position, long id) { - Cursor cursor = (Cursor) adapter.getItem(position); - - String markerID = cursor.getString(cursor.getColumnIndex("mark_id")); - String checkinDigest = cursor.getString(cursor.getColumnIndex("mark_checkin_digest")); + String markerID = cursor.getString(cursor.getColumnIndex(AnalyticsContract.Mark.MARK_ID)); + String checkinDigest = cursor.getString(cursor.getColumnIndex(AnalyticsContract.Mark.MARK_CHECKIN_DIGEST)); Intent intent = new Intent(getActivity(), PositioningActivity.class); intent.putExtra(getString(R.string.mark_id), markerID); intent.putExtra(getString(R.string.checkin_digest), checkinDigest); diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/AppPreferences.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/AppPreferences.java index 4db4d5fcb77..5c8c3a953f8 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/AppPreferences.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/AppPreferences.java @@ -21,10 +21,10 @@ public class AppPreferences extends BaseAppPreferences { cleanLeaderBoardName); } - public String getServerMarkPingPath(String leaderBoardName, String markID) { + public String getServerMarkPingPath(String leaderBoardName, String markIdAsString) { String cleanLeaderBoardName = leaderBoardName.replaceAll(" ", "%20"); return context.getString(R.string.preference_server_gps_fixes_post_path) - .replace("{leaderboard_name}", cleanLeaderBoardName).replace("{mark-id}", markID); + .replace("{leaderboard_name}", cleanLeaderBoardName).replace("{mark-id}", markIdAsString); } public void setDataRefreshInterval(long interval){ diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/CheckinManager.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/CheckinManager.java index d06eeed6ee0..384470627c0 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/CheckinManager.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/CheckinManager.java @@ -13,13 +13,7 @@ import java.util.UUID; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.net.Uri; -import android.util.Log; -import android.widget.Toast; +import org.json.simple.parser.ParseException; import com.sap.sailing.android.buoy.positioning.app.R; import com.sap.sailing.android.buoy.positioning.app.valueobjects.CheckinData; @@ -29,35 +23,58 @@ import com.sap.sailing.android.shared.data.AbstractCheckinData; import com.sap.sailing.android.shared.data.http.HttpGetRequest; import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.android.shared.ui.activities.CheckinDataActivity; +import com.sap.sailing.android.shared.util.JsonHelper; import com.sap.sailing.android.shared.util.NetworkHelper; import com.sap.sailing.android.shared.util.NetworkHelper.NetworkHelperSuccessListener; import com.sap.sailing.android.shared.util.UniqueDeviceUuid; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.base.impl.SharedDomainFactoryImpl; import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; +import com.sap.sailing.domain.common.tracking.GPSFix; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; import com.sap.sailing.domain.racelogtracking.impl.SmartphoneUUIDIdentifierImpl; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.coursedata.impl.MarkDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.FlatGPSFixJsonDeserializer; +import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.FlatGPSFixJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.MarkJsonSerializerWithPosition; -public class CheckinManager { +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.net.Uri; +import android.util.Log; +import android.widget.Toast; +public class CheckinManager { private final static String TAG = CheckinManager.class.getName(); private AbstractCheckinData checkinData; - private CheckinDataActivity activity; - private Context mContext; - private AppPreferences prefs; + private final CheckinDataActivity activity; + private final Context mContext; + private final AppPreferences prefs; private String url; private DataChangedListner dataChangedListner; + private final SharedDomainFactory sharedDomainFactory; - public CheckinManager(String url, Context context){ + public CheckinManager(String url, Context context) { + this(url, context, /* context is not necessarily a CheckinDataActivity */ null); + } + + private CheckinManager(String url, Context context, CheckinDataActivity activity) { + sharedDomainFactory = new SharedDomainFactoryImpl(/* race log resolver not needed in this app */ null); this.url = url; mContext = context; prefs = new AppPreferences(context); + this.activity = activity; } public CheckinManager(String url, CheckinDataActivity activity) { - this.activity = activity; - this.url = url; - mContext = activity; - prefs = new AppPreferences(mContext); + this(url, activity, activity); + } + + public SharedDomainFactory getSharedDomainFactory() { + return sharedDomainFactory; } public void callServerAndGenerateCheckinData() { @@ -156,36 +173,33 @@ public class CheckinManager { public void performAction(JSONObject response) { try { JSONArray markArray = response.getJSONArray("marks"); - String checkinDigest = generateCheckindigest(urlData.uriStr); - List marks = new ArrayList(); - List pings = new ArrayList(); + String checkinDigest = generateCheckinDigest(urlData.uriStr); + List marks = new ArrayList<>(); + List pings = new ArrayList<>(); for (int i = 0; i < markArray.length(); i++) { JSONObject jsonMark = (JSONObject) markArray.get(i); - MarkInfo mark = new MarkInfo(); - mark.setCheckinDigest(checkinDigest); - mark.setClassName(jsonMark.getString("@class")); - mark.setName(jsonMark.getString("name")); - mark.setId(jsonMark.getString("id")); - if (jsonMark.has("position")) { - if (!jsonMark.get("position").equals(null)) { + org.json.simple.JSONObject simpleMark; + simpleMark = JsonHelper.convertToSimple(jsonMark); + MarkDeserializer markDeserializer = new MarkDeserializer(getSharedDomainFactory()); + MarkInfo mark = MarkInfo.create(markDeserializer.deserialize(simpleMark), jsonMark.getString(MarkJsonSerializer.FIELD_CLASS), checkinDigest); + if (jsonMark.has(MarkJsonSerializerWithPosition.FIELD_POSITION)) { + if (!jsonMark.get(MarkJsonSerializerWithPosition.FIELD_POSITION).equals(null)) { JSONObject positionJson = jsonMark.getJSONObject(MarkJsonSerializerWithPosition.FIELD_POSITION); - MarkPingInfo ping = new MarkPingInfo(); - ping.setLatitude(positionJson.getString("latitude")); - ping.setLongitude(positionJson.getString("longitude")); - ping.setTimestamp(positionJson.getInt("timestamp")); - ping.setAccuracy(positionJson.getDouble("accuracy")); - ping.setMarkId(mark.getId()); + FlatGPSFixJsonDeserializer deserializer = new FlatGPSFixJsonDeserializer(); + org.json.simple.JSONObject simplePosition; + simplePosition = JsonHelper.convertToSimple(positionJson); + GPSFix gpsFix = deserializer.deserialize(simplePosition); + MarkPingInfo ping = new MarkPingInfo(mark.getId(), gpsFix, positionJson.getDouble(FlatGPSFixJsonSerializer.FIELD_ACCURACY)); pings.add(ping); } } - mark.setType(jsonMark.getString("type")); marks.add(mark); } urlData.marks = marks; urlData.pings = pings; saveCheckinDataAndNotifyListeners(urlData, leaderboardName); - } catch (JSONException e) { + } catch (JSONException | ParseException | JsonDeserializationException e) { ExLog.e(mContext, TAG, "Error getting data from call on URL: " + urlData.getMarkUrl + ", Error: " + e.getMessage()); if (activity != null) { @@ -282,7 +296,7 @@ public class CheckinManager { setCheckinData(null); } - private String generateCheckindigest(String url) { + private String generateCheckinDigest(String url) { String checkinDigest = ""; try { MessageDigest md = MessageDigest.getInstance("SHA-256"); diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/DatabaseHelper.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/DatabaseHelper.java index aacfe28f050..f65208dada6 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/DatabaseHelper.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/DatabaseHelper.java @@ -1,19 +1,9 @@ package com.sap.sailing.android.buoy.positioning.app.util; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import android.content.ContentProviderOperation; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.content.OperationApplicationException; -import android.database.Cursor; -import android.os.RemoteException; -import android.provider.BaseColumns; -import android.support.v4.content.LocalBroadcastManager; - import com.sap.sailing.android.buoy.positioning.app.BuildConfig; import com.sap.sailing.android.buoy.positioning.app.R; import com.sap.sailing.android.buoy.positioning.app.provider.AnalyticsContract; @@ -26,6 +16,19 @@ import com.sap.sailing.android.buoy.positioning.app.valueobjects.MarkPingInfo; import com.sap.sailing.android.shared.data.CheckinUrlInfo; import com.sap.sailing.android.shared.data.LeaderboardInfo; import com.sap.sailing.android.shared.logging.ExLog; +import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl; +import com.sap.sailing.server.gateway.deserialization.impl.Helpers; + +import android.content.ContentProviderOperation; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.content.OperationApplicationException; +import android.database.Cursor; +import android.os.RemoteException; +import android.provider.BaseColumns; +import android.support.v4.content.LocalBroadcastManager; public class DatabaseHelper { @@ -85,12 +88,12 @@ public class DatabaseHelper { if (mc != null) { mc.moveToFirst(); while (!mc.isAfterLast()) { - MarkInfo markInfo = new MarkInfo(); - markInfo.setCheckinDigest(mc.getString((mc.getColumnIndex(Mark.MARK_CHECKIN_DIGEST)))); - markInfo.setId(mc.getString((mc.getColumnIndex(Mark.MARK_ID)))); - markInfo.setName(mc.getString((mc.getColumnIndex(Mark.MARK_NAME)))); - markInfo.setType(mc.getString((mc.getColumnIndex(Mark.MARK_TYPE)))); - markInfo.setClassName(mc.getString((mc.getColumnIndex(Mark.MARK_CLASS_NAME)))); + final String markName = mc.getString((mc.getColumnIndex(Mark.MARK_NAME))); + final String markIdAsString = mc.getString(mc.getColumnIndex(Mark.MARK_ID)); + final Serializable markId = Helpers.tryUuidConversion(markIdAsString); + MarkInfo markInfo = new MarkInfo(markId, markName, + mc.getString((mc.getColumnIndex(Mark.MARK_CLASS_NAME))), + checkinDigest); marks.add(markInfo); mc.moveToNext(); } @@ -106,12 +109,11 @@ public class DatabaseHelper { if (mpc != null) { mpc.moveToFirst(); while (!mpc.isAfterLast()) { - MarkPingInfo markPingInfo = new MarkPingInfo(); - markPingInfo.setMarkId(markID); - markPingInfo.setTimestamp(mpc.getInt((mpc.getColumnIndex(MarkPing.MARK_PING_TIMESTAMP)))); - markPingInfo.setLongitude(mpc.getString((mpc.getColumnIndex(MarkPing.MARK_PING_LONGITUDE)))); - markPingInfo.setLatitude(mpc.getString((mpc.getColumnIndex(MarkPing.MARK_PING_LATITUDE)))); - markPingInfo.setAccuracy(mpc.getDouble((mpc.getColumnIndex(MarkPing.MARK_PING_ACCURACY)))); + long timeStamp = Long.parseLong(mpc.getString((mpc.getColumnIndex(MarkPing.MARK_PING_TIMESTAMP)))); + double longitude = Double.parseDouble(mpc.getString((mpc.getColumnIndex(MarkPing.MARK_PING_LONGITUDE)))); + double latitude = Double.parseDouble(mpc.getString((mpc.getColumnIndex(MarkPing.MARK_PING_LATITUDE)))); + MarkPingInfo markPingInfo = new MarkPingInfo(markID, GPSFixImpl.create(longitude, latitude, timeStamp), + mpc.getDouble((mpc.getColumnIndex(MarkPing.MARK_PING_ACCURACY)))); marks.add(markPingInfo); mpc.moveToNext(); } @@ -120,12 +122,12 @@ public class DatabaseHelper { return marks; } - public void deletePingsFromDataBase(Context context, String markID) { + public void deletePingsFromDataBase(Context context, String markIdAsString) { ContentResolver cr = context.getContentResolver(); - int d1 = cr.delete(MarkPing.CONTENT_URI, MarkPing.MARK_ID + " = ?", new String[] { markID }); + int d1 = cr.delete(MarkPing.CONTENT_URI, MarkPing.MARK_ID + " = ?", new String[] { markIdAsString }); if (BuildConfig.DEBUG) { - ExLog.i(context, TAG, "Checkout, number of markpings for mark: " + markID + " deleted: " + d1); + ExLog.i(context, TAG, "Checkout, number of markpings for mark: " + markIdAsString + " deleted: " + d1); } } @@ -135,7 +137,7 @@ public class DatabaseHelper { List marks = getMarks(context, checkinDigest); for (MarkInfo mark : marks) { - deletePingsFromDataBase(context, mark.getId()); + deletePingsFromDataBase(context, mark.getId().toString()); } int d2 = cr.delete(Leaderboard.CONTENT_URI, Leaderboard.LEADERBOARD_CHECKIN_DIGEST + " = ?", new String[] { checkinDigest }); @@ -184,9 +186,9 @@ public class DatabaseHelper { for (MarkInfo mark : markList) { ContentValues cmv = new ContentValues(); cmv.put(Mark.MARK_CHECKIN_DIGEST, mark.getCheckinDigest()); - cmv.put(Mark.MARK_ID, mark.getId()); + cmv.put(Mark.MARK_ID, mark.getId().toString()); cmv.put(Mark.MARK_NAME, mark.getName()); - cmv.put(Mark.MARK_TYPE, mark.getType()); + cmv.put(Mark.MARK_TYPE, mark.getType().toString()); cmv.put(Mark.MARK_CLASS_NAME, mark.getClassName()); opList.add(ContentProviderOperation.newInsert(Mark.CONTENT_URI).withValues(cmv).build()); @@ -219,7 +221,7 @@ public class DatabaseHelper { private void deleteMark(Context context, MarkInfo markInfo) { ContentResolver cr = context.getContentResolver(); - cr.delete(Mark.CONTENT_URI, Mark.MARK_ID + " = ?", new String[] { markInfo.getId() }); + cr.delete(Mark.CONTENT_URI, Mark.MARK_ID + " = ?", new String[] { markInfo.getId().toString() }); if (BuildConfig.DEBUG) { ExLog.i(context, TAG, "Deleted mark with id: " + markInfo.getId()); @@ -246,14 +248,14 @@ public class DatabaseHelper { for (MarkInfo mark : markList) { ContentValues cmv = new ContentValues(); cmv.put(Mark.MARK_CHECKIN_DIGEST, mark.getCheckinDigest()); - cmv.put(Mark.MARK_ID, mark.getId()); + cmv.put(Mark.MARK_ID, mark.getId().toString()); cmv.put(Mark.MARK_NAME, mark.getName()); - cmv.put(Mark.MARK_TYPE, mark.getType()); + cmv.put(Mark.MARK_TYPE, mark.getType().toString()); cmv.put(Mark.MARK_CLASS_NAME, mark.getClassName()); if (!dataBaseContainsMark(context, mark)) { cr.insert(Mark.CONTENT_URI, cmv); } else { - cr.update(Mark.CONTENT_URI, cmv, Mark.MARK_ID + " = ?", new String[] { mark.getId() }); + cr.update(Mark.CONTENT_URI, cmv, Mark.MARK_ID + " = ?", new String[] { mark.getId().toString() }); } } LocalBroadcastManager.getInstance(context.getApplicationContext()).sendBroadcast(new Intent(context.getString(R.string.database_changed))); @@ -261,7 +263,7 @@ public class DatabaseHelper { private boolean dataBaseContainsMark(Context context, MarkInfo mark) { Cursor contentResolver = context.getContentResolver().query(Mark.CONTENT_URI, null, Mark.MARK_CHECKIN_DIGEST + " = ?" + - " AND " + Mark.MARK_ID + " = ? ", new String[] { mark.getCheckinDigest(), mark.getId() }, ""); + " AND " + Mark.MARK_ID + " = ? ", new String[] { mark.getCheckinDigest(), mark.getId().toString() }, ""); int count = 0; if (contentResolver != null) { count = contentResolver.getCount(); @@ -273,10 +275,10 @@ public class DatabaseHelper { public void storeMarkPing(Context context, MarkPingInfo markPing) throws GeneralDatabaseHelperException { ContentResolver cr = context.getContentResolver(); - deletePingsFromDataBase(context, markPing.getMarkId()); + deletePingsFromDataBase(context, markPing.getMarkId().toString()); ArrayList opList = new ArrayList<>(); ContentValues mpcv = new ContentValues(); - mpcv.put(MarkPing.MARK_ID, markPing.getMarkId()); + mpcv.put(MarkPing.MARK_ID, markPing.getMarkId().toString()); mpcv.put(MarkPing.MARK_PING_LATITUDE, markPing.getLatitude()); mpcv.put(MarkPing.MARK_PING_LONGITUDE, markPing.getLongitude()); mpcv.put(MarkPing.MARK_PING_ACCURACY, markPing.getAccuracy()); diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/PingHelper.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/PingHelper.java index 69a5510a3d2..b5b28827ddb 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/PingHelper.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/PingHelper.java @@ -1,14 +1,10 @@ package com.sap.sailing.android.buoy.positioning.app.util; -import java.util.Date; import java.util.UUID; import org.json.JSONException; import org.json.JSONObject; -import android.content.Context; -import android.location.Location; - import com.sap.sailing.android.buoy.positioning.app.util.DatabaseHelper.GeneralDatabaseHelperException; import com.sap.sailing.android.buoy.positioning.app.valueobjects.MarkInfo; import com.sap.sailing.android.buoy.positioning.app.valueobjects.MarkPingInfo; @@ -17,6 +13,10 @@ import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.android.shared.services.sending.MessageSendingService; import com.sap.sailing.android.shared.services.sending.ServerReplyCallback; import com.sap.sailing.domain.common.tracking.impl.FlatSmartphoneUuidAndGPSFixMovingJsonSerializer; +import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl; + +import android.content.Context; +import android.location.Location; public class PingHelper { private static String TAG = PingHelper.class.getName(); @@ -25,13 +25,10 @@ public class PingHelper { AppPreferences prefs = new AppPreferences(context); try { JSONObject fixJson = new JSONObject(); - - fixJson.put(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.TIME_MILLIS, new Date().getTime()); + fixJson.put(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.TIME_MILLIS, location.getTime()); fixJson.put(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.LON_DEG, location.getLongitude()); fixJson.put(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.LAT_DEG, location.getLatitude()); - - String postUrlStr = leaderBoard.serverUrl + prefs.getServerMarkPingPath(leaderBoard.name, mark.getId()); - + String postUrlStr = leaderBoard.serverUrl + prefs.getServerMarkPingPath(leaderBoard.name, mark.getId().toString()); context.startService(MessageSendingService.createMessageIntent(context, postUrlStr, null, UUID.randomUUID(), fixJson.toString(), callback)); @@ -41,12 +38,8 @@ public class PingHelper { } public Boolean storePingInDatabase(Context context, Location location, MarkInfo mark) { - MarkPingInfo pingInfo = new MarkPingInfo(); - pingInfo.setMarkId(mark.getId()); - pingInfo.setLatitude("" + location.getLatitude()); - pingInfo.setLongitude("" + location.getLongitude()); - pingInfo.setAccuracy(location.getAccuracy()); - pingInfo.setTimestamp((int) location.getTime()); + MarkPingInfo pingInfo = new MarkPingInfo(mark.getId(), + GPSFixImpl.create(location.getLongitude(), location.getLatitude(), location.getTime()), location.getAccuracy()); try { DatabaseHelper.getInstance().storeMarkPing(context, pingInfo); } catch (GeneralDatabaseHelperException e) { diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkInfo.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkInfo.java index f3ddd04971b..ccf866f4007 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkInfo.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkInfo.java @@ -1,53 +1,47 @@ package com.sap.sailing.android.buoy.positioning.app.valueobjects; -public class MarkInfo { +import java.io.Serializable; - private String markId; - private String name; - private String type; - private String className; - private String checkinDigest; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.impl.MarkImpl; +import com.sap.sailing.domain.common.MarkType; - public String getId() { - return markId; +public class MarkInfo extends MarkImpl { + private static final long serialVersionUID = 6139266956501048794L; + + private final String className; + private final String checkinDigest; + + public static MarkInfo create(Mark mark, String classname, String checkinDigest) { + return new MarkInfo(mark.getId(), mark.getName(), mark.getType(), mark.getColor(), mark.getShape(), mark.getPattern(), classname, checkinDigest); } - public void setId(String id) { - this.markId = id; + public MarkInfo(String name) { + super(name); + className = null; + checkinDigest = null; } - public String getName() { - return name; + public MarkInfo(Serializable id, String name, String classname, String checkinDigest) { + super(id, name); + this.className = classname; + this.checkinDigest = checkinDigest; } - public void setName(String name) { - this.name = name; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; + public MarkInfo(Serializable id, String name, MarkType type, String color, String shape, String pattern, String classname, String checkinDigest) { + super(id, name, type, color, shape, pattern); + this.className = classname; + this.checkinDigest = checkinDigest; } public String getClassName() { return className; } - public void setClassName(String className) { - this.className = className; - } - public String getCheckinDigest() { return checkinDigest; } - public void setCheckinDigest(String checkinDigest) { - this.checkinDigest = checkinDigest; - } - @Override public boolean equals(Object o) { if (this == o) @@ -55,27 +49,23 @@ public class MarkInfo { if (o == null || getClass() != o.getClass()) return false; - MarkInfo info = (MarkInfo) o; + MarkInfo markInfo = (MarkInfo) o; - if (markId != null ? !markId.equals(info.markId) : info.markId != null) + if(!super.equals(markInfo)) { return false; - if (name != null ? !name.equals(info.name) : info.name != null) + } + + if (!className.equals(markInfo.className)) return false; - if (type != null ? !type.equals(info.type) : info.type != null) - return false; - if (className != null ? !className.equals(info.className) : info.className != null) - return false; - return !(checkinDigest != null ? !checkinDigest.equals(info.checkinDigest) : info.checkinDigest != null); + return checkinDigest.equals(markInfo.checkinDigest); } @Override public int hashCode() { - int result = markId != null ? markId.hashCode() : 0; - result = 31 * result + (name != null ? name.hashCode() : 0); - result = 31 * result + (type != null ? type.hashCode() : 0); - result = 31 * result + (className != null ? className.hashCode() : 0); - result = 31 * result + (checkinDigest != null ? checkinDigest.hashCode() : 0); + int result = super.hashCode(); + result = 31 * result + className.hashCode(); + result = 31 * result + checkinDigest.hashCode(); return result; } } diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkPingInfo.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkPingInfo.java index 2d8118bb388..dcdc8286672 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkPingInfo.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkPingInfo.java @@ -1,49 +1,38 @@ package com.sap.sailing.android.buoy.positioning.app.valueobjects; -public class MarkPingInfo { - private String markId; - private String longitude; - private String latitude; - private double accuracy; - private int timestamp; +import java.io.Serializable; - public String getMarkId() { +import com.sap.sailing.domain.common.tracking.GPSFix; + +public class MarkPingInfo { + private final Serializable markId; + private final GPSFix gpsFix; + private final double accuracy; + + public MarkPingInfo(Serializable markId, GPSFix gpsFix, double accuracy) { + super(); + this.markId = markId; + this.gpsFix = gpsFix; + this.accuracy = accuracy; + } + + public Serializable getMarkId() { return markId; } - public void setMarkId(String markId) { - this.markId = markId; - } - public String getLongitude() { - return longitude; - } - - public void setLongitude(String longitude) { - this.longitude = longitude; + return "" + gpsFix.getPosition().getLngDeg(); } public String getLatitude() { - return latitude; - } - - public void setLatitude(String latitude) { - this.latitude = latitude; + return "" + gpsFix.getPosition().getLatDeg(); } public double getAccuracy() { return accuracy; } - public void setAccuracy(double accuracy) { - this.accuracy = accuracy; - } - - public int getTimestamp() { - return timestamp; - } - - public void setTimestamp(int timestamp) { - this.timestamp = timestamp; + public long getTimestamp() { + return gpsFix.getTimePoint().asMillis(); } } diff --git a/mobile/com.sap.sailing.buoy.positioning/tests-jvm/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkInfoTest.java b/mobile/com.sap.sailing.buoy.positioning/tests-jvm/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkInfoTest.java index e4dcaba5adc..39cf20026b2 100644 --- a/mobile/com.sap.sailing.buoy.positioning/tests-jvm/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkInfoTest.java +++ b/mobile/com.sap.sailing.buoy.positioning/tests-jvm/src/com/sap/sailing/android/buoy/positioning/app/valueobjects/MarkInfoTest.java @@ -1,16 +1,15 @@ package com.sap.sailing.android.buoy.positioning.app.valueobjects; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; + public class MarkInfoTest { @Test public void testMarkInfoName() { - MarkInfo markInfo = new MarkInfo(); String name = "test"; - markInfo.setName(name); + MarkInfo markInfo = new MarkInfo(name); assertEquals(markInfo.getName(), name); } } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java index 93e1ae7ec11..f5bf0fb8920 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java @@ -1,257 +1,257 @@ -package com.sap.sailing.racecommittee.app.data; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.Callable; - -import android.app.LoaderManager.LoaderCallbacks; -import android.content.Context; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; -import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.CourseBase; -import com.sap.sailing.domain.base.EventBase; -import com.sap.sailing.domain.base.LeaderboardGroupBase; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.SharedDomainFactory; -import com.sap.sailing.domain.base.configuration.ConfigurationLoader; -import com.sap.sailing.domain.base.configuration.DeviceConfiguration; -import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier; -import com.sap.sailing.domain.base.configuration.RegattaConfiguration; -import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CourseAreaImpl; -import com.sap.sailing.domain.base.impl.FleetImpl; -import com.sap.sailing.domain.base.impl.MarkImpl; -import com.sap.sailing.domain.base.impl.StrippedEventImpl; -import com.sap.sailing.domain.base.racegroup.RaceGroup; -import com.sap.sailing.domain.base.racegroup.SeriesWithRows; -import com.sap.sailing.domain.base.racegroup.impl.RaceGroupImpl; -import com.sap.sailing.domain.base.racegroup.impl.SeriesWithRowsImpl; -import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; -import com.sap.sailing.racecommittee.app.AppPreferences; -import com.sap.sailing.racecommittee.app.data.clients.LoadClient; -import com.sap.sailing.racecommittee.app.data.loaders.DataLoaderResult; -import com.sap.sailing.racecommittee.app.data.loaders.ImmediateDataLoaderCallbacks; -import com.sap.sailing.racecommittee.app.domain.CoursePosition; -import com.sap.sailing.racecommittee.app.domain.ManagedRace; -import com.sap.sailing.racecommittee.app.domain.configuration.impl.PreferencesRegattaConfigurationLoader; -import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceIdentifierImpl; -import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceImpl; -import com.sap.sailing.racecommittee.app.ui.fragments.lists.PositionListFragment; -import com.sap.sse.common.Color; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class OfflineDataManager extends DataManager { - - private static boolean isInitialized = false; - private final Context context; - - protected OfflineDataManager(Context context, DataStore dataStore, SharedDomainFactory domainFactory) { - super(context, dataStore, domainFactory); - this.context = context; - if (!isInitialized) { - isInitialized = true; - fillDataStore(dataStore); - } - } - - private void fillDataStore(DataStore dataStore) { - Calendar cal = Calendar.getInstance(); - cal.set(2012, 12, 1); - final TimePoint startDate = new MillisecondsTimePoint(cal.getTimeInMillis()); - cal.set(2012, 12, 5); - final TimePoint endDate = new MillisecondsTimePoint(cal.getTimeInMillis()); - - dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Cardiff)", startDate, endDate, "Cardiff", true, UUID.randomUUID(), Collections. emptySet())); - dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Nice)", startDate, endDate, "Nice", true, UUID.randomUUID(), Collections. emptySet())); - dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Rio)", startDate, endDate, "Rio", true, UUID.randomUUID(), Collections. emptySet())); - EventBase newEvent = new StrippedEventImpl("Extreme Sailing Series 2013 (Muscat)", startDate, endDate, "Muscat", true, UUID.randomUUID(), Collections. emptySet()); - newEvent.getVenue().addCourseArea(new CourseAreaImpl("Offshore", UUID.randomUUID())); - newEvent.getVenue().addCourseArea(new CourseAreaImpl("Stadium", UUID.randomUUID())); - dataStore.addEvent(newEvent); - - SeriesWithRows qualifying = new SeriesWithRowsImpl("Qualifying", false, null); - SeriesWithRows medal = new SeriesWithRowsImpl("Medal", true, null); - RaceGroup raceGroup = new RaceGroupImpl("ESS", /* displayName */ null, new BoatClassImpl("X40", false), null, Arrays.asList(qualifying, - medal), new EmptyRegattaConfiguration()); - - List competitors = new ArrayList(); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.BLUE, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", Color.LIGHT_GRAY, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", Color.GREEN, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", Color.BLACK, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); - - RaceLog log = new RaceLogImpl(UUID.randomUUID()); - final AbstractLogEventAuthor author = AppPreferences.on(context).getAuthor(); - ConfigurationLoader configuration = PreferencesRegattaConfigurationLoader - .loadFromPreferences(preferences); - - log.add(new RaceLogStartTimeEventImpl(new MillisecondsTimePoint(new Date().getTime() - 2000), author, 1, - new MillisecondsTimePoint(new Date().getTime() - 1000))); - - log.add(new RaceLogRaceStatusEventImpl(new MillisecondsTimePoint(new Date().getTime()), - AppPreferences.on(context).getAuthor(), 1, RaceLogRaceStatus.FINISHING)); - - ManagedRace q1 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("A.B", new FleetImpl("A"), qualifying, raceGroup), - RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration)); - - log = new RaceLogImpl(UUID.randomUUID()); - /* - * log.add(factory.createStartTimeEvent( new MillisecondsTimePoint(new Date()), 1, RaceLogRaceStatus.SCHEDULED, - * new MillisecondsTimePoint(new Date().getTime() + 100000))); - */ - - ManagedRace q2 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("B", new FleetImpl("A.A"), qualifying, raceGroup), - RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration)); - - log = new RaceLogImpl(UUID.randomUUID()); - /* - * log.add(factory.createRaceStatusEvent( new MillisecondsTimePoint(new Date()), 5, - * RaceLogRaceStatus.FINISHED)); - */ - ManagedRace q3 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("Q3", new FleetImpl("Default"), qualifying, raceGroup), - RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration)); - /* - * ManagedRace m1 = new ManagedRaceImpl( new ManagedRaceIdentifierImpl( "M1", new FleetImpl("Default"), medal, - * raceGroup), null); - */ - dataStore.addRace(q1); - dataStore.addRace(q2); - dataStore.addRace(q3); - // dataStore.addRace(m1); - - Mark m1 = new MarkImpl("Red"); - Mark m2 = new MarkImpl("Green"); - Mark m3 = new MarkImpl("White"); - - dataStore.addMark(m1); - dataStore.addMark(m2); - dataStore.addMark(m3); - } - - @Override - public LoaderCallbacks>> createEventsLoader( - LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getEvents(); - } - }); - } - - @Override - public LoaderCallbacks>> createCourseAreasLoader( - final Serializable parentEventId, LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getCourseAreas(dataStore.getEvent(parentEventId)); - } - }); - } - - @Override - public LoaderCallbacks>> createCourseAreasLoader( - final EventBase parentEvent, LoadClient> callback) { - // TODO Auto-generated method stub - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getCourseAreas(parentEvent); - } - }); - } - - @Override - public LoaderCallbacks>> createRacesLoader(Serializable courseAreaId, - LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getRaces(); - } - }); - } - - @Override - public LoaderCallbacks>> createMarksLoader(ManagedRace managedRace, - LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getMarks(); - } - }); - } - - @Override - public LoaderCallbacks> createCourseLoader(final ManagedRace managedRace, - LoadClient callback) { - return new ImmediateDataLoaderCallbacks(context, callback, new Callable() { - @Override - public CourseBase call() throws Exception { - return managedRace.getCourseOnServer(); - } - }); - } - - @Override - public LoaderCallbacks>> createCompetitorsLoader( - final ManagedRace managedRace, LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return managedRace.getCompetitors(); - } - }); - } - - @Override - public LoaderCallbacks> createConfigurationLoader( - DeviceConfigurationIdentifier identifier, LoadClient callback) { - return new ImmediateDataLoaderCallbacks(context, callback, - new Callable() { - @Override - public DeviceConfiguration call() throws Exception { - throw new IllegalStateException("No remote configuration in offline mode."); - } - }); - } - - @Override - public String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts, boolean showStreamlets, boolean showSimulation, - boolean showMapControls) { - throw new IllegalStateException("No wind map in offline mode."); - } - - @Override - public LoaderCallbacks>> createPositionLoader( - PositionListFragment positionListFragment) { - // TODO Auto-generated method stub - return null; - } - -} +package com.sap.sailing.racecommittee.app.data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.Callable; + +import android.app.LoaderManager.LoaderCallbacks; +import android.content.Context; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.CourseBase; +import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.domain.base.LeaderboardGroupBase; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.base.configuration.ConfigurationLoader; +import com.sap.sailing.domain.base.configuration.DeviceConfiguration; +import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier; +import com.sap.sailing.domain.base.configuration.RegattaConfiguration; +import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CourseAreaImpl; +import com.sap.sailing.domain.base.impl.FleetImpl; +import com.sap.sailing.domain.base.impl.MarkImpl; +import com.sap.sailing.domain.base.impl.StrippedEventImpl; +import com.sap.sailing.domain.base.racegroup.RaceGroup; +import com.sap.sailing.domain.base.racegroup.SeriesWithRows; +import com.sap.sailing.domain.base.racegroup.impl.RaceGroupImpl; +import com.sap.sailing.domain.base.racegroup.impl.SeriesWithRowsImpl; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.racecommittee.app.AppPreferences; +import com.sap.sailing.racecommittee.app.data.clients.LoadClient; +import com.sap.sailing.racecommittee.app.data.loaders.DataLoaderResult; +import com.sap.sailing.racecommittee.app.data.loaders.ImmediateDataLoaderCallbacks; +import com.sap.sailing.racecommittee.app.domain.CoursePosition; +import com.sap.sailing.racecommittee.app.domain.ManagedRace; +import com.sap.sailing.racecommittee.app.domain.configuration.impl.PreferencesRegattaConfigurationLoader; +import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceIdentifierImpl; +import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceImpl; +import com.sap.sailing.racecommittee.app.ui.fragments.lists.PositionListFragment; +import com.sap.sse.common.Color; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class OfflineDataManager extends DataManager { + + private static boolean isInitialized = false; + private final Context context; + + protected OfflineDataManager(Context context, DataStore dataStore, SharedDomainFactory domainFactory) { + super(context, dataStore, domainFactory); + this.context = context; + if (!isInitialized) { + isInitialized = true; + fillDataStore(dataStore); + } + } + + private void fillDataStore(DataStore dataStore) { + Calendar cal = Calendar.getInstance(); + cal.set(2012, 12, 1); + final TimePoint startDate = new MillisecondsTimePoint(cal.getTimeInMillis()); + cal.set(2012, 12, 5); + final TimePoint endDate = new MillisecondsTimePoint(cal.getTimeInMillis()); + + dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Cardiff)", startDate, endDate, "Cardiff", true, UUID.randomUUID(), Collections. emptySet())); + dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Nice)", startDate, endDate, "Nice", true, UUID.randomUUID(), Collections. emptySet())); + dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Rio)", startDate, endDate, "Rio", true, UUID.randomUUID(), Collections. emptySet())); + EventBase newEvent = new StrippedEventImpl("Extreme Sailing Series 2013 (Muscat)", startDate, endDate, "Muscat", true, UUID.randomUUID(), Collections. emptySet()); + newEvent.getVenue().addCourseArea(new CourseAreaImpl("Offshore", UUID.randomUUID())); + newEvent.getVenue().addCourseArea(new CourseAreaImpl("Stadium", UUID.randomUUID())); + dataStore.addEvent(newEvent); + + SeriesWithRows qualifying = new SeriesWithRowsImpl("Qualifying", false, null); + SeriesWithRows medal = new SeriesWithRowsImpl("Medal", true, null); + RaceGroup raceGroup = new RaceGroupImpl("ESS", /* displayName */ null, new BoatClassImpl("X40", false), null, Arrays.asList(qualifying, + medal), new EmptyRegattaConfiguration()); + + List competitors = new ArrayList(); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.BLUE, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", Color.LIGHT_GRAY, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", Color.GREEN, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", Color.BLACK, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + + RaceLog log = new RaceLogImpl(UUID.randomUUID()); + final AbstractLogEventAuthor author = AppPreferences.on(context).getAuthor(); + ConfigurationLoader configuration = PreferencesRegattaConfigurationLoader + .loadFromPreferences(preferences); + + log.add(new RaceLogStartTimeEventImpl(new MillisecondsTimePoint(new Date().getTime() - 2000), author, 1, + new MillisecondsTimePoint(new Date().getTime() - 1000))); + + log.add(new RaceLogRaceStatusEventImpl(new MillisecondsTimePoint(new Date().getTime()), + AppPreferences.on(context).getAuthor(), 1, RaceLogRaceStatus.FINISHING)); + + ManagedRace q1 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("A.B", new FleetImpl("A"), qualifying, raceGroup), + RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration)); + + log = new RaceLogImpl(UUID.randomUUID()); + /* + * log.add(factory.createStartTimeEvent( new MillisecondsTimePoint(new Date()), 1, RaceLogRaceStatus.SCHEDULED, + * new MillisecondsTimePoint(new Date().getTime() + 100000))); + */ + + ManagedRace q2 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("B", new FleetImpl("A.A"), qualifying, raceGroup), + RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration)); + + log = new RaceLogImpl(UUID.randomUUID()); + /* + * log.add(factory.createRaceStatusEvent( new MillisecondsTimePoint(new Date()), 5, + * RaceLogRaceStatus.FINISHED)); + */ + ManagedRace q3 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("Q3", new FleetImpl("Default"), qualifying, raceGroup), + RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration)); + /* + * ManagedRace m1 = new ManagedRaceImpl( new ManagedRaceIdentifierImpl( "M1", new FleetImpl("Default"), medal, + * raceGroup), null); + */ + dataStore.addRace(q1); + dataStore.addRace(q2); + dataStore.addRace(q3); + // dataStore.addRace(m1); + + Mark m1 = new MarkImpl("Red"); + Mark m2 = new MarkImpl("Green"); + Mark m3 = new MarkImpl("White"); + + dataStore.addMark(m1); + dataStore.addMark(m2); + dataStore.addMark(m3); + } + + @Override + public LoaderCallbacks>> createEventsLoader( + LoadClient> callback) { + return new ImmediateDataLoaderCallbacks>(context, callback, + new Callable>() { + @Override + public Collection call() throws Exception { + return dataStore.getEvents(); + } + }); + } + + @Override + public LoaderCallbacks>> createCourseAreasLoader( + final Serializable parentEventId, LoadClient> callback) { + return new ImmediateDataLoaderCallbacks>(context, callback, + new Callable>() { + @Override + public Collection call() throws Exception { + return dataStore.getCourseAreas(dataStore.getEvent(parentEventId)); + } + }); + } + + @Override + public LoaderCallbacks>> createCourseAreasLoader( + final EventBase parentEvent, LoadClient> callback) { + // TODO Auto-generated method stub + return new ImmediateDataLoaderCallbacks>(context, callback, + new Callable>() { + @Override + public Collection call() throws Exception { + return dataStore.getCourseAreas(parentEvent); + } + }); + } + + @Override + public LoaderCallbacks>> createRacesLoader(Serializable courseAreaId, + LoadClient> callback) { + return new ImmediateDataLoaderCallbacks>(context, callback, + new Callable>() { + @Override + public Collection call() throws Exception { + return dataStore.getRaces(); + } + }); + } + + @Override + public LoaderCallbacks>> createMarksLoader(ManagedRace managedRace, + LoadClient> callback) { + return new ImmediateDataLoaderCallbacks>(context, callback, new Callable>() { + @Override + public Collection call() throws Exception { + return dataStore.getMarks(); + } + }); + } + + @Override + public LoaderCallbacks> createCourseLoader(final ManagedRace managedRace, + LoadClient callback) { + return new ImmediateDataLoaderCallbacks(context, callback, new Callable() { + @Override + public CourseBase call() throws Exception { + return managedRace.getCourseOnServer(); + } + }); + } + + @Override + public LoaderCallbacks>> createCompetitorsLoader( + final ManagedRace managedRace, LoadClient> callback) { + return new ImmediateDataLoaderCallbacks>(context, callback, + new Callable>() { + @Override + public Collection call() throws Exception { + return managedRace.getCompetitors(); + } + }); + } + + @Override + public LoaderCallbacks> createConfigurationLoader( + DeviceConfigurationIdentifier identifier, LoadClient callback) { + return new ImmediateDataLoaderCallbacks(context, callback, + new Callable() { + @Override + public DeviceConfiguration call() throws Exception { + throw new IllegalStateException("No remote configuration in offline mode."); + } + }); + } + + @Override + public String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts, boolean showStreamlets, boolean showSimulation, + boolean showMapControls) { + throw new IllegalStateException("No wind map in offline mode."); + } + + @Override + public LoaderCallbacks>> createPositionLoader( + PositionListFragment positionListFragment) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java index f353db21782..c63c8ed1635 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java @@ -72,6 +72,8 @@ public class LoginActivity extends BaseActivity private final static String CourseAreaListFragmentTag = "CourseAreaListFragmentTag"; private final static String AreaPositionListFragmentTag = "AreaPositionListFragmentTag"; + private boolean wakeUp; + private final static String TAG = LoginActivity.class.getName(); private final PositionListFragment positionFragment; @@ -385,6 +387,7 @@ public class LoginActivity extends BaseActivity @Override public void onPause() { super.onPause(); + wakeUp = true; LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver); } @@ -537,11 +540,12 @@ public class LoginActivity extends BaseActivity public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (AppConstants.INTENT_ACTION_RESET.equals(action)) { + if (AppConstants.INTENT_ACTION_RESET.equals(action) && !wakeUp) { resetData(); - } else if (AppConstants.INTENT_ACTION_VALID_DATA.equals(action)) { + } else if (AppConstants.INTENT_ACTION_VALID_DATA.equals(action) && !wakeUp) { resetData(); } + wakeUp = false; } } @@ -567,7 +571,7 @@ public class LoginActivity extends BaseActivity @Override public void onAnimationCancel(Animator animation) { - + // no op } @Override diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/RacingActivity.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/RacingActivity.java index e09c8dba858..aaa4d68f19a 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/RacingActivity.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/RacingActivity.java @@ -6,7 +6,38 @@ import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; +import android.annotation.TargetApi; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.IdRes; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.content.LocalBroadcastManager; +import android.support.v4.view.ViewCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.AlertDialog; +import android.support.v7.internal.widget.TintImageView; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.Window; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.Toast; + import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.android.shared.util.AppUtils; import com.sap.sailing.android.shared.util.BitmapHelper; @@ -47,36 +78,6 @@ import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; -import android.annotation.TargetApi; -import android.app.Fragment; -import android.app.FragmentTransaction; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.os.Build; -import android.os.Bundle; -import android.support.annotation.IdRes; -import android.support.annotation.NonNull; -import android.support.v4.content.LocalBroadcastManager; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.AlertDialog; -import android.support.v7.internal.widget.TintImageView; -import android.support.v7.widget.Toolbar; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.Window; -import android.widget.ImageView; -import android.widget.ProgressBar; -import android.widget.Toast; - public class RacingActivity extends SessionActivity implements RaceListCallbacks { private static final String TAG = RacingActivity.class.getName(); private static final String WIND = "wind"; @@ -517,8 +518,8 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks overflow.setMinimumWidth(getResources().getDimensionPixelSize(R.dimen.bigger_over_flow_width)); overflow.setMinimumHeight(getResources().getDimensionPixelSize(R.dimen.bigger_over_flow_height)); Bitmap bitmap = BitmapHelper - .decodeSampledBitmapFromResource(getResources(), R.drawable.ic_more_vert_white_48dp, overflow.getMinimumWidth(), overflow - .getMinimumHeight()); + .decodeSampledBitmapFromResource(getResources(), R.drawable.ic_more_vert_white_48dp, + ViewCompat.getMinimumWidth(overflow), ViewCompat.getMinimumHeight(overflow)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { overflow.setScaleType(ImageView.ScaleType.FIT_END); } @@ -540,71 +541,82 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks } } - public void processIntent(Intent intent) { - Fragment content; - Fragment extra = null; - Bundle args = new Bundle(); - View view; - - String action = intent.getAction(); + public void processIntent(final Intent intent) { + final Bundle args = new Bundle(); if (mSelectedRace != null) { args.putSerializable(AppConstants.RACE_ID_KEY, mSelectedRace.getId()); } - FragmentTransaction transaction = getFragmentManager().beginTransaction(); + // artificial delay (to prevent "java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState") + new Thread(new Runnable() { + @Override + public void run() { + runOnUiThread(new Runnable() { + @Override + public void run() { + Fragment content; + Fragment extra = null; + View view; + String action = intent.getAction(); - if (AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT.equals(action)) { - view = findViewById(R.id.race_edit); - if (view != null) { - ViewHelper.setSiblingsVisibility(view, View.VISIBLE); - extra = getFragmentManager().findFragmentById(R.id.race_edit); - if (extra != null) { - transaction.remove(extra); - } - } - if (findViewById(R.id.race_content) != null) { - if (mSelectedRace.getStatus() != RaceLogRaceStatus.FINISHING) { - content = RaceFlagViewerFragment.newInstance(); - } else { - if (preferences.getRacingProcedureIsResultEntryEnabled(mSelectedRace.getState(). - getRacingProcedure().getType())) { - content = TrackingListFragment.newInstance(args, 1); - } else { - content = RaceFinishingFragment.newInstance(); + FragmentTransaction transaction = getFragmentManager().beginTransaction(); + + if (AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT.equals(action)) { + view = findViewById(R.id.race_edit); + if (view != null) { + ViewHelper.setSiblingsVisibility(view, View.VISIBLE); + extra = getFragmentManager().findFragmentById(R.id.race_edit); + if (extra != null) { + transaction.remove(extra); + } + } + if (findViewById(R.id.race_content) != null) { + if (mSelectedRace.getStatus() != RaceLogRaceStatus.FINISHING) { + content = RaceFlagViewerFragment.newInstance(); + } else { + if (preferences.getRacingProcedureIsResultEntryEnabled(mSelectedRace.getState(). + getRacingProcedure().getType())) { + content = TrackingListFragment.newInstance(args, 1); + } else { + content = RaceFinishingFragment.newInstance(); + } + } + content.setArguments(args); + transaction.replace(R.id.race_content, content); + } + } + + if (AppConstants.INTENT_ACTION_SHOW_SUMMARY_CONTENT.equals(action)) { + view = findViewById(R.id.finished_edit); + if (view != null) { + ViewHelper.setSiblingsVisibility(view, View.VISIBLE); + extra = getFragmentManager().findFragmentById(R.id.finished_edit); + if (extra != null) { + transaction.remove(extra); + } + } + if (extra == null && findViewById(R.id.finished_content) != null) { + content = RaceSummaryFragment.newInstance(args); + transaction.replace(R.id.finished_content, content); + } + } + + if (AppConstants.INTENT_ACTION_REMOVE_PROTEST.equals(action)) { + view = findViewById(R.id.protest_time_fragment); + if (view != null) { + ViewHelper.setSiblingsVisibility(view, View.VISIBLE); + extra = getFragmentManager().findFragmentById(R.id.protest_time_fragment); + if (extra != null) { + transaction.remove(extra); + } + } + } + + transaction.commit(); } - } - content.setArguments(args); - transaction.replace(R.id.race_content, content); + }); } - } - - if (AppConstants.INTENT_ACTION_SHOW_SUMMARY_CONTENT.equals(action)) { - view = findViewById(R.id.finished_edit); - if (view != null) { - ViewHelper.setSiblingsVisibility(view, View.VISIBLE); - extra = getFragmentManager().findFragmentById(R.id.finished_edit); - if (extra != null) { - transaction.remove(extra); - } - } - if (extra == null && findViewById(R.id.finished_content) != null) { - content = RaceSummaryFragment.newInstance(args); - transaction.replace(R.id.finished_content, content); - } - } - - if (AppConstants.INTENT_ACTION_REMOVE_PROTEST.equals(action)) { - view = findViewById(R.id.protest_time_fragment); - if (view != null) { - ViewHelper.setSiblingsVisibility(view, View.VISIBLE); - extra = getFragmentManager().findFragmentById(R.id.protest_time_fragment); - if (extra != null) { - transaction.remove(extra); - } - } - } - - transaction.commit(); + }).start(); } private class RaceLoadClient implements LoadClient> { diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/LoginListViews.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/LoginListViews.java index 666b0c181a1..b03d1a6d4f0 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/LoginListViews.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/LoginListViews.java @@ -102,6 +102,7 @@ public class LoginListViews extends LoggableDialogFragment implements View.OnCli IntentFilter filter = new IntentFilter(); filter.addAction(AppConstants.INTENT_ACTION_TOGGLE); + filter.addAction(AppConstants.INTENT_ACTION_RESET); LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mListener, filter); } @@ -252,6 +253,10 @@ public class LoginListViews extends LoggableDialogFragment implements View.OnCli } break; + case AppConstants.INTENT_ACTION_RESET: + mSignUp.setEnabled(false); + break; + default: break; } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/BaseRaceInfoRaceFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/BaseRaceInfoRaceFragment.java index a1cc9e00bb2..65f36e64dfd 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/BaseRaceInfoRaceFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/BaseRaceInfoRaceFragment.java @@ -81,7 +81,7 @@ public abstract class BaseRaceInfoRaceFragment all this shall be included to a next HVM version \ No newline at end of file