Merge branch 'gpsfixstore-independent-of-race' into ftes-gpximport

Conflicts:
	java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/SailingDomain.gwt.xml
	java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java
	java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
	java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java
	java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java
	java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java
	java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java
	java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java
This commit is contained in:
Fredrik Teschke committed 2014-05-01 23:05:08 +02:00
commit fb0f187d55
368 files changed
+23334 -11328

No files matched your search

@@ -14,6 +14,7 @@ Export-Package: com.sap.sailing.domain.common,
com.sap.sailing.domain.common.quadtree,
com.sap.sailing.domain.common.quadtree.impl;x-friends:="com.sap.sailing.domain.test",
com.sap.sailing.domain.common.racelog,
com.sap.sailing.domain.common.racelog.tracking,
com.sap.sailing.domain.common.racelog.utils,
com.sap.sailing.domain.common.scalablevalue,
com.sap.sailing.domain.common.scalablevalue.impl,
@@ -7,5 +7,6 @@
<source path='common/filter'/>
<source path='common/media'/>
<source path='common/scalablevalue'/>
<source path='common/racelog/tracking'/>
<source path='common/scalablevalue/impl'/>
</module>
@@ -12,6 +12,7 @@ import com.sap.sailing.domain.common.impl.MillisecondsDurationImpl;
*/
public interface Duration extends Serializable, Comparable<Duration> {
static final Duration NULL = new MillisecondsDurationImpl(0);
static final Duration ONE_SECOND = new MillisecondsDurationImpl(1000);
static final Duration ONE_MINUTE = ONE_SECOND.times(60);
static final Duration ONE_HOUR = ONE_MINUTE.times(60);
@@ -12,13 +12,13 @@ package com.sap.sailing.domain.common;
*/
public enum PassingInstruction {
None,
Port,
Starboard,
Gate,
Line,
Offset,
FixedBearing;
None(1, 2),
Port(1),
Starboard(1),
Gate(2),
Line(2),
Offset(2),
FixedBearing(1);
public static PassingInstruction[] relevantValues() {
PassingInstruction[] uiValues = new PassingInstruction[PassingInstruction.values().length - 1];
@@ -40,4 +40,15 @@ public enum PassingInstruction {
return null;
}
/**
* Denotes for which types of {@code ControlPoints} (defined by the number of marks they are made up of)
* this passing instruction is applicable.<p>
* E.g. {@code [1,2]} denotes that the passing instruction is applicable for {@code ControlPoints} with either one
* or two marks.
*/
public final int[] applicability;
private PassingInstruction(int... applicability) {
this.applicability = applicability;
}
}
@@ -0,0 +1,67 @@
package com.sap.sailing.domain.common;
import java.io.Serializable;
public interface TimeRange extends Comparable<TimeRange>, Serializable {
/**
* @return {@code null}, if the timepoint is at the beginning of time
*/
TimePoint from();
/**
* @return {@code null}, if the timepoint is at the beginning of time
*/
TimePoint to();
/**
* Also returns true if (either or both) the from or to timepoints are equal.
* E.g. 10-100 lies within 10-00, and 10-50 lies within 10-100.
* @param other
* @return
*/
boolean liesWithin(TimeRange other);
/**
* Reverse operation of {@link #liesWithin(TimeRange)}.
* x.includes(y) = y.liesWithin(x)
* @param other
* @return
*/
boolean includes(TimeRange other);
boolean includes(TimePoint timePoint);
boolean intersects(TimeRange other);
boolean startsBefore(TimeRange other);
boolean endsAfter(TimeRange other);
/**
* Is the time range open ended towards older timepoints?
*/
boolean openBeginning();
/**
* Is the time range open ended towards newer timepoints?
*/
boolean openEnd();
/**
* Get time-difference between the timepoint and this timerange.
* It will be 0 if the timepoint lies within the timerange, otherwise the time-difference
* to either the start or end of the timerange, depending on which is closer. The
* time difference is a duration that is guaranteed to be positive.
*/
Duration timeDifference(TimePoint timePoint);
/**
* Merges the two ranges, only possible if {@code other} {@link #intersects()} this range.
*/
TimeRange union(TimeRange other);
/**
* Intersection of the two ranges, only possible if {@code other} {@link #intersects()} this range.
*/
TimeRange intersection(TimeRange other);
}
@@ -30,7 +30,7 @@ public abstract class AbstractLeaderboardDTO implements Serializable {
public UUID defaultCourseAreaId;
public String defaultCourseAreaName;
public ScoringSchemeType scoringScheme;
public LeaderboardType type;
public LeaderboardType type;
private Long delayToLiveInMillisForLatestRace;
@@ -23,7 +23,7 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial
private String idAsString;
private BoatClassDTO boatClass;
CompetitorDTOImpl() {}
public CompetitorDTOImpl() {}
public CompetitorDTOImpl(String name, Color color, String twoLetterIsoCountryCode, String threeLetterIocCountryCode,
String countryName, String sailID, String idAsString, BoatClassDTO boatClass) {
@@ -22,6 +22,8 @@ public class RaceColumnDTO extends NamedDTO implements Serializable {
private Boolean isValidInTotalScore;
private Double explicitFactor;
private double effectiveFactor;
private final Map<FleetDTO, RaceLogTrackingInfoDTO> raceLogTrackingInfos = new HashMap<FleetDTO, RaceLogTrackingInfoDTO>();
RaceColumnDTO() {} // for GWT serialization
@@ -283,4 +285,12 @@ public class RaceColumnDTO extends NamedDTO implements Serializable {
public double getEffectiveFactor() {
return effectiveFactor;
}
public RaceLogTrackingInfoDTO getRaceLogTrackingInfo(FleetDTO fleet) {
return raceLogTrackingInfos.get(fleet);
}
public void setRaceLogTrackingInfo(FleetDTO fleet, RaceLogTrackingInfoDTO info) {
raceLogTrackingInfos.put(fleet, info);
}
}
@@ -0,0 +1,16 @@
package com.sap.sailing.domain.common.dto;
import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState;
public class RaceLogTrackingInfoDTO {
public boolean raceLogTrackerExists;
public boolean competitorRegistrationsExists;
public RaceLogTrackingState raceLogTrackingState;
public RaceLogTrackingInfoDTO(boolean raceLogTrackerExists, boolean competitorRegistrationsExists,
RaceLogTrackingState raceLogTrackingState) {
this.raceLogTrackerExists = raceLogTrackerExists;
this.competitorRegistrationsExists = competitorRegistrationsExists;
this.raceLogTrackingState = raceLogTrackingState;
}
}
@@ -1,112 +1,113 @@
package com.sap.sailing.domain.common.impl;
import java.util.Comparator;
import java.util.Date;
import com.sap.sailing.domain.common.Duration;
import com.sap.sailing.domain.common.TimePoint;
public abstract class AbstractTimePoint implements TimePoint {
private static final long serialVersionUID = 8825508619301420378L;
public static Comparator<TimePoint> TIMEPOINT_COMPARATOR = new SerializableComparator<TimePoint>() {
private static final long serialVersionUID = 7644726881387366025L;
@Override
public int compare(TimePoint o1, TimePoint o2) {
long milliDiff = o1.asMillis() - o2.asMillis();
return milliDiff<0 ? -1 : milliDiff == 0 ? 0 : 1;
}
};
@Override
public int compareTo(TimePoint o) {
return TIMEPOINT_COMPARATOR.compare(this, o);
}
@Override
public Date asDate() {
Date result = getDateFromCache();
if (result == null) {
result = new Date(asMillis());
cacheDate(result);
}
return result;
}
@Override
public TimePoint plus(Duration duration) {
final TimePoint result;
if (duration != null) {
result = plus(duration.asMillis());
} else {
result = this;
}
return result;
}
@Override
public TimePoint minus(Duration duration) {
final TimePoint result;
if (duration != null) {
result = minus(duration.asMillis());
} else {
result = this;
}
return result;
}
@Override
public Duration until(TimePoint later) {
return new MillisecondsDurationImpl(later.asMillis()-asMillis());
}
@Override
public TimePoint plus(long milliseconds) {
return new MillisecondsTimePoint(asMillis()+milliseconds);
}
@Override
public TimePoint minus(long milliseconds) {
return plus(-milliseconds);
}
@Override
public boolean after(TimePoint other) {
return this.compareTo(other) > 0;
}
@Override
public boolean before(TimePoint other) {
return this.compareTo(other) < 0;
}
@Override
public int hashCode() {
return (int) (asMillis() & Integer.MAX_VALUE);
}
@Override
public boolean equals(Object obj) {
return compareTo((TimePoint) obj) == 0;
}
@Override
public String toString() {
return asDate().toString();
}
/**
* A subclass may implement a cache for the {@link Date} representation by overriding this method as well
* as {@link #cacheDate(Date)}.
*/
protected Date getDateFromCache() {
return null;
}
/**
* A subclass may implement a cache for the {@link Date} representation by overriding this method as well
* as {@link #getDate()}.
*/
protected void cacheDate(Date date) {}
}
package com.sap.sailing.domain.common.impl;
import java.util.Comparator;
import java.util.Date;
import com.sap.sailing.domain.common.Duration;
import com.sap.sailing.domain.common.TimePoint;
public abstract class AbstractTimePoint implements TimePoint {
private static final long serialVersionUID = 8825508619301420378L;
public static Comparator<TimePoint> TIMEPOINT_COMPARATOR = new SerializableComparator<TimePoint>() {
private static final long serialVersionUID = 7644726881387366025L;
@Override
public int compare(TimePoint o1, TimePoint o2) {
long o1Millis = o1.asMillis();
long o2Millis = o2.asMillis();
return o1Millis<o2Millis?-1:o1Millis==o2Millis?0:1;
}
};
@Override
public int compareTo(TimePoint o) {
return TIMEPOINT_COMPARATOR.compare(this, o);
}
@Override
public Date asDate() {
Date result = getDateFromCache();
if (result == null) {
result = new Date(asMillis());
cacheDate(result);
}
return result;
}
@Override
public TimePoint plus(Duration duration) {
final TimePoint result;
if (duration != null) {
result = plus(duration.asMillis());
} else {
result = this;
}
return result;
}
@Override
public TimePoint minus(Duration duration) {
final TimePoint result;
if (duration != null) {
result = minus(duration.asMillis());
} else {
result = this;
}
return result;
}
@Override
public Duration until(TimePoint later) {
return new MillisecondsDurationImpl(later.asMillis()-asMillis());
}
@Override
public TimePoint plus(long milliseconds) {
return new MillisecondsTimePoint(asMillis()+milliseconds);
}
@Override
public TimePoint minus(long milliseconds) {
return plus(-milliseconds);
}
@Override
public boolean after(TimePoint other) {
return this.compareTo(other) > 0;
}
@Override
public boolean before(TimePoint other) {
return this.compareTo(other) < 0;
}
@Override
public int hashCode() {
return (int) (asMillis() & Integer.MAX_VALUE);
}
@Override
public boolean equals(Object obj) {
return compareTo((TimePoint) obj) == 0;
}
@Override
public String toString() {
return asDate().toString();
}
/**
* A subclass may implement a cache for the {@link Date} representation by overriding this method as well
* as {@link #cacheDate(Date)}.
*/
protected Date getDateFromCache() {
return null;
}
/**
* A subclass may implement a cache for the {@link Date} representation by overriding this method as well
* as {@link #getDate()}.
*/
protected void cacheDate(Date date) {}
}
@@ -0,0 +1,112 @@
package com.sap.sailing.domain.common.impl;
import com.sap.sailing.domain.common.Duration;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.TimeRange;
import com.sap.sailing.domain.common.impl.Util.Pair;
public class TimeRangeImpl extends Pair<TimePoint, TimePoint> implements TimeRange {
public static final TimePoint BeginningOfTime = new MillisecondsTimePoint(Long.MIN_VALUE);
public static final TimePoint EndOfTime = new MillisecondsTimePoint(Long.MAX_VALUE);
private static final long serialVersionUID = 8710198176227507300L;
public TimeRangeImpl(TimePoint from, TimePoint to) {
super(from == null ? BeginningOfTime : from, to == null ? EndOfTime : to);
if (from().after(to())) throw new IllegalArgumentException(String.format("from (%s) must lie before to (%s) in a TimeRange", from(), to()));
}
@Override
public int compareTo(TimeRange other) {
if (other.from().equals(from()) && other.to().equals(to())) return 0;
return startsBefore(other) ? -1 : 1;
}
@Override
public TimePoint from() {
return getA();
}
@Override
public TimePoint to() {
return getB();
}
@Override
public boolean liesWithin(TimeRange other) {
return from().compareTo(other.from()) >= 0 && to().compareTo(other.to()) <= 0;
}
@Override
public boolean includes(TimeRange other) {
return other.liesWithin(this);
}
@Override
public boolean intersects(TimeRange other) {
return includes(other.from()) || includes(other.to()) || liesWithin(other);
}
@Override
public boolean includes(TimePoint timePoint) {
return from().compareTo(timePoint) <= 0 && to().compareTo(timePoint) >= 0;
}
@Override
public boolean startsBefore(TimeRange other) {
return from().before(other.from());
}
@Override
public boolean endsAfter(TimeRange other) {
return to().after(other.to());
}
@Override
public Duration timeDifference(TimePoint timePoint) {
final Duration result;
if (includes(timePoint)) {
result = Duration.NULL;
} else if (timePoint.before(from())) {
result = timePoint.until(from());
} else {
result = to().until(timePoint);
}
return result;
}
@Override
public TimeRange union(TimeRange other) {
if (! intersects(other)) return null;
TimePoint newFrom = startsBefore(other) ? from() : other.from();
TimePoint newTo = endsAfter(other) ? to() : other.to();
return new TimeRangeImpl(newFrom, newTo);
}
@Override
public boolean openBeginning() {
return from().equals(BeginningOfTime);
}
@Override
public boolean openEnd() {
return to().equals(EndOfTime);
}
@Override
public TimeRange intersection(TimeRange other) {
if (! intersects(other)) return null;
TimePoint newFrom = startsBefore(other) ? other.from() : from();
TimePoint newTo = endsAfter(other) ? other.to() : to();
return new TimeRangeImpl(newFrom, newTo);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj instanceof TimeRange) {
TimeRange other = (TimeRange) obj;
return from().equals(other.from()) && to().equals(other.to());
}
return super.equals(obj);
}
}
@@ -0,0 +1,24 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class NoCorrespondingServiceRegisteredException extends RuntimeException {
public String type;
public String serviceInterface;
private static final long serialVersionUID = -358955216089477585L;
protected NoCorrespondingServiceRegisteredException() {}
public NoCorrespondingServiceRegisteredException(String message, String type, String serviceInterface) {
super(message);
this.type = type;
this.serviceInterface = serviceInterface;
}
public String getDeviceType() {
return type;
}
@Override
public String toString() {
return super.toString() + " (Service: " + serviceInterface + ", Type: " + type + ")";
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class NotDenotableForRaceLogTrackingException extends Exception {
private static final long serialVersionUID = 6721038282862173471L;
public NotDenotableForRaceLogTrackingException() {
super();
}
public NotDenotableForRaceLogTrackingException(String msg) {
super(msg);
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class NotDenotedForRaceLogTrackingException extends Exception {
private static final long serialVersionUID = 6721038282862173471L;
public NotDenotedForRaceLogTrackingException() {
super();
}
public NotDenotedForRaceLogTrackingException(String msg) {
super(msg);
}
}
@@ -0,0 +1,13 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class NotRevokableException extends Exception {
private static final long serialVersionUID = 6825451915706047105L;
public NotRevokableException() {
super();
}
public NotRevokableException(String msg) {
super(msg);
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class RaceLogRaceTrackerExistsException extends RuntimeException {
private static final long serialVersionUID = 6721038282862173471L;
public RaceLogRaceTrackerExistsException() {
super();
}
public RaceLogRaceTrackerExistsException(String raceLogName) {
super("Tracker for racelog " + raceLogName + " already exists");
}
}
@@ -0,0 +1,30 @@
package com.sap.sailing.domain.common.racelog.tracking;
/**
* The state of the race tracked via the racelog. This can be determined by inspecting the corresponding events
* in the racelog with the {@link RaceLogTrackingStateAnalyzer}.
* @author Fredrik Teschke
*
*/
public enum RaceLogTrackingState {
//can't determine whether tracking has ended from race log, therefore omitting TRACKING_ENDED state for now
/**
* no {@link DenoteForTrackingEvent} is present
*/
NOT_A_RACELOG_TRACKED_RACE,
/**
* a {@link DenoteForTrackingEvent} is present, but no {@link StartTrackingEvent} yet.
*/
AWAITING_RACE_DEFINITION,
/**
* a {@link StartTrackingEvent} is present
*/
TRACKING;
public boolean isForTracking() {
return this != NOT_A_RACELOG_TRACKED_RACE;
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class RaceNotCreatedException extends RuntimeException {
private static final long serialVersionUID = 6721038282862173471L;
public RaceNotCreatedException() {
super();
}
public RaceNotCreatedException(String msg) {
super(msg);
}
}
@@ -0,0 +1,37 @@
package com.sap.sailing.domain.common.racelog.tracking;
/**
* Only can provide the service for a single {@code type}, e.g. on smartphones with no OSGi context.
* Optionally, a {@link #setFallbackService(Object) fallback} can be set.
* @author Fredrik Teschke
*/
public class SingleTypeBasedServiceFinderImpl<ServiceType> implements
TypeBasedServiceFinder<ServiceType> {
private final ServiceType service;
private final String type;
private ServiceType fallback;
public SingleTypeBasedServiceFinderImpl(ServiceType service, ServiceType fallback, String type) {
this.service = service;
this.type = type;
this.fallback = fallback;
}
public SingleTypeBasedServiceFinderImpl(ServiceType service, String type) {
this(service, null, type);
}
@Override
public ServiceType findService(String type)
throws NoCorrespondingServiceRegisteredException {
if (type.equals(this.type)) return service;
if (fallback != null) return fallback;
throw new NoCorrespondingServiceRegisteredException("Only one service registered", type, service.getClass().getSimpleName());
}
@Override
public void setFallbackService(ServiceType fallback) {
this.fallback = fallback;
}
}
@@ -0,0 +1,30 @@
package com.sap.sailing.domain.common.racelog.tracking;
import java.io.IOException;
public class TransformationException extends IOException {
private static final long serialVersionUID = -7795777645371428971L;
public TransformationException() {
}
public TransformationException(Class<?> from, Class<?> to, String at, Throwable e) {
super("Couldn't transform "+from.getName()+" into "+to.getName()+" at "+at, e);
}
public TransformationException(Class<?> from, Class<?> to, String at) {
this(from, to, at, null);
}
public TransformationException(String message, Throwable e) {
super(message, e);
}
public TransformationException(Throwable e) {
super(e);
}
public TransformationException(String message) {
super(message);
}
}
@@ -0,0 +1,13 @@
package com.sap.sailing.domain.common.racelog.tracking;
/**
* Handle transformation between two types. Most likely use-case is serialization,
* e.g. for JSON documents or database persistence.
*
* @author Fredrik Teschke
*
*/
public interface TransformationHandler<T1, T2> {
T1 transformBack(T2 object) throws TransformationException;
T2 transformForth(T1 object) throws TransformationException;
}
@@ -0,0 +1,29 @@
package com.sap.sailing.domain.common.racelog.tracking;
/**
* @author Fredrik Teschke
*
* @param <ServiceType> Specifies desired the service interface
*/
public interface TypeBasedServiceFinder<ServiceType> {
public static final String TYPE = "type";
/**
* Find a service that implements the <ServiceType> interface for the specified {@code type}
* of object (e.g. type of a {@link GPSFix}).
* @param type A {@link String} that specifies for which type the service should be registered
* @throws NoCorrespondingServiceRegisteredException Thrown, if no service is registered for this type.
*/
ServiceType findService(String type) throws NoCorrespondingServiceRegisteredException;
/**
* Sets a fallback service (optional), that is used if no service is registered for a {@code type}.
* This should be a generic service, that can deal with any {@code type}, and provides a
* "better-than-nothing" implementation, which will be returned instead of throwing a
* {@link NoCorrespondingServiceRegisteredException}.
* <p>
* This method does not need to be implemented, but can remain a stub, if no fallback behaviour
* is desired.
*/
void setFallbackService(ServiceType fallback);
}
@@ -0,0 +1,18 @@
package com.sap.sailing.domain.common.racelog.tracking;
/**
* A factory for creating {@link TypeBasedServiceFinder}s, for a specific type of service.
* The desired service type is specified by the {@link Class} object passed to the
* {@link #createServiceFinder(Class)} method.
*
* The created {@link TypeBasedServiceFinder} can then be used to find the desired
* service for a specific type. E.g., there may be a persistence service interface for
* {@link GPSFix}es, and there are several different service registered, depending on the type
* of {@link GPSFix}. The service finder then can find the appropriate service for each fix.
* @author Fredrik Teschke
*
*/
public interface TypeBasedServiceFinderFactory {
<ServiceT> TypeBasedServiceFinder<ServiceT> createServiceFinder(Class<ServiceT> clazz);
}