mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-09 20:41:10 +00:00
Merge branch 'master' into bug4514
Change-Id: Id1ca0e271319ee209a1a3d7dc486ed1c7a6a25a6
This commit is contained in:
commit
452b5ff205
89 files changed
+1321
-505
No files matched your search
+15
@@ -0,0 +1,15 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class ServiceException extends Exception implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1690510580423647161L;
|
||||
|
||||
public ServiceException() {
|
||||
}
|
||||
|
||||
public ServiceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.sap.sailing.domain.common.dto;
|
||||
|
||||
public final class ExpeditionAllInOneConstants {
|
||||
public static final String REQUEST_PARAMETER_IMPORT_MODE = "importMode";
|
||||
public static final String REQUEST_PARAMETER_BOAT_CLASS = "boatClass";
|
||||
public static final String REQUEST_PARAMETER_REGATTA_NAME = "regattaName";
|
||||
public static final String REQUEST_PARAMETER_LOCALE = "locale";
|
||||
public enum ImportMode{
|
||||
NEW_COMPETITOR, NEW_EVENT, NEW_RACE;
|
||||
}
|
||||
|
||||
private ExpeditionAllInOneConstants() {
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -483,7 +483,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoFixImpl.java
Regular → Executable
+2
-1
@@ -58,7 +58,8 @@ public class BravoFixImpl extends SensorFixImpl implements BravoFix {
|
||||
|
||||
@Override
|
||||
public boolean isFoiling(Distance minimumRideHeight) {
|
||||
return getRideHeight() == null ? false : getRideHeight().compareTo(minimumRideHeight) >= 0;
|
||||
final Distance rideHeight = getRideHeight();
|
||||
return rideHeight != null && rideHeight.compareTo(minimumRideHeight) >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+6
-6
@@ -263,6 +263,7 @@ import com.sap.sse.shared.media.VideoDescriptor;
|
||||
import com.sap.sse.shared.media.impl.ImageDescriptorImpl;
|
||||
import com.sap.sse.shared.media.impl.VideoDescriptorImpl;
|
||||
import com.sap.sse.util.ThreadPoolUtil;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName());
|
||||
@@ -1626,7 +1627,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
private RaceLogEvent loadRaceLogRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author,
|
||||
TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors,
|
||||
DBObject dbObject) {
|
||||
Serializable revokedEventId = Helpers
|
||||
Serializable revokedEventId = UUIDHelper
|
||||
.tryUuidConversion((Serializable) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_ID.name()));
|
||||
String revokedEventType = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_TYPE.name());
|
||||
String revokedEventShortInfo = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_SHORT_INFO.name());
|
||||
@@ -1651,9 +1652,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
result = null; // the competitor wasn't found
|
||||
dbObjectForUpdate = Optional.empty();
|
||||
} else if (boatId == null) {
|
||||
final Boat boat;
|
||||
if (competitor.hasBoat() && (boat=((CompetitorWithBoat) competitor).getBoat()) != null) {
|
||||
result = new RaceLogRegisterCompetitorEventImpl(createdAt, logicalTimePoint, author, id, passId, competitor, boat);
|
||||
if (competitor.hasBoat()) {
|
||||
result = new RaceLogRegisterCompetitorEventImpl(createdAt, logicalTimePoint, author, id, passId, competitor, ((CompetitorWithBoat) competitor).getBoat());
|
||||
} else {
|
||||
logger.warning("Bug2822: Competitor with ID "+competitorId+" already seems to have been migrated to one without boat."+
|
||||
" But the RaceLogRegisterCompetitorEventImpl event loaded does not specify one either. We'll try to find a boat...");
|
||||
@@ -2044,7 +2044,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
|
||||
private RegattaLogRevokeEvent loadRegattaLogRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author,
|
||||
TimePoint logicalTimePoint, Serializable id, DBObject dbObject) {
|
||||
Serializable revokedEventId = Helpers
|
||||
Serializable revokedEventId = UUIDHelper
|
||||
.tryUuidConversion((Serializable) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_ID.name()));
|
||||
String revokedEventType = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_TYPE.name());
|
||||
String revokedEventShortInfo = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_SHORT_INFO.name());
|
||||
@@ -2092,7 +2092,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
private RegattaLogCloseOpenEndedDeviceMappingEvent loadRegattaLogCloseOpenEndedDeviceMappingEvent(
|
||||
TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id,
|
||||
DBObject dbObject) {
|
||||
Serializable deviceMappingEventId = Helpers
|
||||
Serializable deviceMappingEventId = UUIDHelper
|
||||
.tryUuidConversion((Serializable) dbObject.get(FieldNames.REGATTA_LOG_DEVICE_MAPPING_EVENT_ID.name()));
|
||||
TimePoint closingTimePointInclusive = loadTimePoint(dbObject, FieldNames.REGATTA_LOG_CLOSING_TIMEPOINT);
|
||||
return new RegattaLogCloseOpenEndedDeviceMappingEventImpl(createdAt, author, logicalTimePoint, id,
|
||||
|
||||
+2
@@ -113,4 +113,6 @@ public interface SharedDomainFactory extends CompetitorFactory, BoatFactory {
|
||||
RaceLogResolver getRaceLogResolver();
|
||||
|
||||
Mark getOrCreateMark(String name, MarkType markType);
|
||||
|
||||
Mark getOrCreateMark(Serializable id, String name, MarkType markType);
|
||||
}
|
||||
+2
-1
@@ -161,7 +161,8 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory {
|
||||
return getOrCreateMark(name, name, markType);
|
||||
}
|
||||
|
||||
private Mark getOrCreateMark(Serializable id, String name, MarkType markType) {
|
||||
@Override
|
||||
public Mark getOrCreateMark(Serializable id, String name, MarkType markType) {
|
||||
return getOrCreateMark(id, name, markType, /* color */ null, /* shape */ null, /* pattern */ null);
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -44,7 +44,7 @@ public class SwissTimingConnectivityParamsHandler extends AbstractRaceTrackingCo
|
||||
private static final String COMPETITOR_THREE_LETTER_IOC_CODE = "competitorThreeLetterIocCode";
|
||||
private static final String COMPETITOR_NAME = "competitorName";
|
||||
private static final String COMPETITOR_BOAT_ID = "competitorBoatId";
|
||||
private static final String COMPETITOR_ID = "competitorId";
|
||||
private static final String COMPETITOR_ID_AS_STRING = "competitorId"; // the competitor ID as String
|
||||
private static final String USE_INTERNAL_MARK_PASSING_ALGORITHM = "useInternalMarkPassingAlgorithm";
|
||||
private static final String DELAY_TO_LIVE_IN_MILLIS = "delayToLiveInMillis";
|
||||
private static final String START_LIST = "startList";
|
||||
@@ -107,7 +107,7 @@ public class SwissTimingConnectivityParamsHandler extends AbstractRaceTrackingCo
|
||||
|
||||
private DBObject createCompetitorDBObject(Competitor competitor) {
|
||||
final DBObject result = new BasicDBObject();
|
||||
result.put(COMPETITOR_ID, competitor.getID());
|
||||
result.put(COMPETITOR_ID_AS_STRING, competitor.getIdAsString());
|
||||
result.put(COMPETITOR_BOAT_ID, competitor.getBoatID());
|
||||
result.put(COMPETITOR_NAME, competitor.getName());
|
||||
result.put(COMPETITOR_THREE_LETTER_IOC_CODE, competitor.getThreeLetterIOCCode());
|
||||
@@ -150,15 +150,15 @@ public class SwissTimingConnectivityParamsHandler extends AbstractRaceTrackingCo
|
||||
|
||||
private Competitor createCompetitorFromDBObject(DBObject competitorDBObject) {
|
||||
final Competitor result;
|
||||
final String competitorId = (String) competitorDBObject.get(COMPETITOR_ID);
|
||||
final String competitorIdAsString = (String) competitorDBObject.get(COMPETITOR_ID_AS_STRING);
|
||||
final String boatID = (String) competitorDBObject.get(COMPETITOR_BOAT_ID);
|
||||
final String threeLetterIOCCode = (String) competitorDBObject.get(COMPETITOR_THREE_LETTER_IOC_CODE);
|
||||
final String name = (String) competitorDBObject.get(COMPETITOR_NAME);
|
||||
final BasicDBList crewDBObject = (BasicDBList) competitorDBObject.get(COMPETITOR_CREW);
|
||||
if (competitorId == null) {
|
||||
if (competitorIdAsString == null) {
|
||||
result = new CompetitorWithoutID(boatID, threeLetterIOCCode, name);
|
||||
} else {
|
||||
result = new CompetitorWithID(competitorId, boatID, threeLetterIOCCode, name, createCrewFromDBObject(crewDBObject));
|
||||
result = new CompetitorWithID(competitorIdAsString, boatID, threeLetterIOCCode, name, createCrewFromDBObject(crewDBObject));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+2
-7
@@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.swisstimingadapter.Mark;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class CCGMessage {
|
||||
private String raceId;
|
||||
@@ -37,17 +38,11 @@ public class CCGMessage {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
String s = "";
|
||||
for (Mark m : markList) {
|
||||
s = s + "|" + m.getIndex() + ";" + m.getDescription() + ";";
|
||||
for (String str : m.getDevices()) {
|
||||
s = s + str + ";";
|
||||
}
|
||||
s = s.substring(0, s.length() - 1);
|
||||
s += Util.join(";", m.getDeviceIds());
|
||||
}
|
||||
return "CCG|" +raceId + "|" + markList.size() + s;
|
||||
}
|
||||
|
||||
}
|
||||
+5
-3
@@ -6,6 +6,7 @@ import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -13,6 +14,8 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
@@ -205,9 +208,8 @@ public class MessageFileServiceImpl implements MessageFileService {
|
||||
} else {
|
||||
devicesNamesStartIndex = 2;
|
||||
}
|
||||
marks.add(new MarkImpl(markDetails[1], Integer.valueOf(markDetails[0]),
|
||||
Arrays.asList(markDetails).subList(devicesNamesStartIndex, markDetails.length),
|
||||
markType));
|
||||
List<Serializable> markIds = Arrays.asList(markDetails).subList(devicesNamesStartIndex, markDetails.length).stream().map(idAsString->UUID.fromString(idAsString)).collect(Collectors.toList());
|
||||
marks.add(new MarkImpl(markDetails[1], Integer.valueOf(markDetails[0]), markIds, markType));
|
||||
}
|
||||
return new CCGMessage(raceId, marks);
|
||||
}
|
||||
|
||||
+5
-5
@@ -239,11 +239,11 @@ public class SailMasterConnectivityTest {
|
||||
Iterator<Mark> mi = course1.getMarks().iterator();
|
||||
Mark m11 = mi.next();
|
||||
assertEquals("Lee Gate", m11.getDescription());
|
||||
assertEquals(Arrays.asList(new String[] { "LG1", "LG2" }), m11.getDevices());
|
||||
assertEquals(Arrays.asList(new String[] { "LG1", "LG2" }), m11.getDeviceIds());
|
||||
assertEquals(1, m11.getIndex());
|
||||
Mark m12 = mi.next();
|
||||
assertEquals("Windward", m12.getDescription());
|
||||
assertEquals(Arrays.asList(new String[] { "WW1" }), m12.getDevices());
|
||||
assertEquals(Arrays.asList(new String[] { "WW1" }), m12.getDeviceIds());
|
||||
assertEquals(2, m12.getIndex());
|
||||
|
||||
Race r2 = connector4712.getRace();
|
||||
@@ -253,15 +253,15 @@ public class SailMasterConnectivityTest {
|
||||
mi = course2.getMarks().iterator();
|
||||
Mark m21 = mi.next();
|
||||
assertEquals("Lee Gate", m21.getDescription());
|
||||
assertEquals(Arrays.asList(new String[] { "LG1", "LG2" }), m21.getDevices());
|
||||
assertEquals(Arrays.asList(new String[] { "LG1", "LG2" }), m21.getDeviceIds());
|
||||
assertEquals(1, m21.getIndex());
|
||||
Mark m22 = mi.next();
|
||||
assertEquals("Windward", m22.getDescription());
|
||||
assertEquals(Arrays.asList(new String[] { "WW1" }), m22.getDevices());
|
||||
assertEquals(Arrays.asList(new String[] { "WW1" }), m22.getDeviceIds());
|
||||
assertEquals(2, m22.getIndex());
|
||||
Mark m23 = mi.next();
|
||||
assertEquals("Offset", m23.getDescription());
|
||||
assertEquals(Arrays.asList(new String[] { "OS1" }), m23.getDevices());
|
||||
assertEquals(Arrays.asList(new String[] { "OS1" }), m23.getDeviceIds());
|
||||
assertEquals(3, m23.getIndex());
|
||||
}
|
||||
|
||||
|
||||
+10
-8
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
package com.sap.sailing.domain.swisstimingadapter.test.ui;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -248,11 +249,12 @@ public class EditCCG extends javax.swing.JDialog {
|
||||
|
||||
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
|
||||
// TODO add your handling code here:
|
||||
List<String> devices = new ArrayList<String>();
|
||||
devices.add(jSailNumber1.getText());
|
||||
if (jRadioButton2.isSelected())
|
||||
devices.add(jSailNumber2.getText());
|
||||
marks.add(new MarkWithDesc(jMarkDescription.getText(), Integer.parseInt(jMarkIndex.getText()),devices));
|
||||
List<Serializable> deviceIds = new ArrayList<>();
|
||||
deviceIds.add(jSailNumber1.getText());
|
||||
if (jRadioButton2.isSelected()) {
|
||||
deviceIds.add(jSailNumber2.getText());
|
||||
}
|
||||
marks.add(new MarkWithDesc(jMarkDescription.getText(), Integer.parseInt(jMarkIndex.getText()), deviceIds));
|
||||
jMarkList.setListData(marks.toArray(new CCGMessage[0]));
|
||||
}//GEN-LAST:event_jButton2ActionPerformed
|
||||
|
||||
@@ -272,13 +274,13 @@ public class EditCCG extends javax.swing.JDialog {
|
||||
|
||||
private class MarkWithDesc extends MarkImpl {
|
||||
|
||||
public MarkWithDesc(String description, int index, Iterable<String> devices) {
|
||||
super(description, index, devices, /* markType */ null);
|
||||
public MarkWithDesc(String description, int index, Iterable<Serializable> deviceIds) {
|
||||
super(description, index, deviceIds, /* markType */ null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "Mark " + getIndex() + ": " + getDescription() + getDevices();
|
||||
return "Mark " + getIndex() + ": " + getDescription() + getDeviceIds();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -11,5 +11,5 @@ public interface Competitor {
|
||||
|
||||
String getName();
|
||||
|
||||
String getID();
|
||||
String getIdAsString();
|
||||
}
|
||||
+4
-3
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -46,7 +47,7 @@ public interface DomainFactory {
|
||||
|
||||
Pair<Competitor, Boat> createCompetitorWithID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, BoatClass boatClass);
|
||||
|
||||
Pair<Competitor, Boat> createCompetitorWithoutID(String boatID, String threeLetterIOCCode, String name, String raceId, BoatClass boatClass);
|
||||
Pair<Competitor, Boat> createCompetitorWithoutID(String competitorId, String threeLetterIOCCode, String name, String raceId, BoatClass boatClass);
|
||||
|
||||
String getCompetitorID(String boatID, RaceType raceType);
|
||||
|
||||
@@ -54,7 +55,7 @@ public interface DomainFactory {
|
||||
|
||||
RaceDefinition createRaceDefinition(Regatta regatta, Race race, StartList startList, com.sap.sailing.domain.swisstimingadapter.Course course);
|
||||
|
||||
com.sap.sailing.domain.base.Mark getOrCreateMark(String trackerID);
|
||||
com.sap.sailing.domain.base.Mark getOrCreateMark(Serializable trackerID, String description);
|
||||
|
||||
GPSFixMoving createGPSFix(TimePoint timePointOfTransmission, Fix fix);
|
||||
|
||||
@@ -71,7 +72,7 @@ public interface DomainFactory {
|
||||
long delayToLiveInMillis, SwissTimingFactory swissTimingFactory, DomainFactory domainFactory,
|
||||
RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, boolean useInternalMarkPassingAlgorithm, boolean trackWind, boolean correctWindDirectionByMagneticDeclination);
|
||||
|
||||
ControlPoint getOrCreateControlPoint(Iterable<String> devices, MarkType markType);
|
||||
ControlPoint getOrCreateControlPoint(String description, Iterable<Serializable> deviceIds, MarkType markType);
|
||||
|
||||
RaceDefinition createRaceDefinition(Regatta regatta, String swissTimingRaceID, Map<Competitor, Boat> competitorsAndBoats,
|
||||
List<ControlPoint> courseDefinition, String raceName, String raceIdForRaceDefinition);
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
@@ -13,7 +15,7 @@ import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
*
|
||||
*/
|
||||
public interface Fix {
|
||||
String getBoatID();
|
||||
Serializable getTrackedObjectId();
|
||||
|
||||
TrackerType getTrackerType();
|
||||
|
||||
|
||||
+3
-1
@@ -1,11 +1,13 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface Mark extends WithDescription {
|
||||
public enum MarkType { MANUAL, LINE_CROSSING, BUOY_ROUNDING };
|
||||
|
||||
int getIndex();
|
||||
|
||||
Iterable<String> getDevices();
|
||||
Iterable<Serializable> getDeviceIds();
|
||||
|
||||
MarkType getMarkType();
|
||||
}
|
||||
-4
@@ -1,7 +1,5 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.tracking.RaceTracker;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
@@ -10,6 +8,4 @@ public interface SwissTimingRaceTracker extends RaceTracker {
|
||||
* The key for a SwissTiming race tracker is the triple of raceID, host name and port number.
|
||||
*/
|
||||
Util.Triple<String, String, Integer> getID();
|
||||
|
||||
Competitor getCompetitorByBoatIDAndRaceIDOrBoatClass(String boatID, String raceID, BoatClass boatClass);
|
||||
}
|
||||
+1
-1
@@ -29,7 +29,7 @@ public abstract class AbstractCompetitor implements Competitor {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
public String getIdAsString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -5,17 +5,17 @@ import java.util.List;
|
||||
import com.sap.sailing.domain.swisstimingadapter.CrewMember;
|
||||
|
||||
public class CompetitorWithID extends AbstractCompetitor {
|
||||
private final String id;
|
||||
private final String idAsString;
|
||||
private List<CrewMember> crew;
|
||||
|
||||
public CompetitorWithID(String id, String boatID, String threeLetterIOCCode, String name, List<CrewMember> crew) {
|
||||
public CompetitorWithID(String idAsString, String boatID, String threeLetterIOCCode, String name, List<CrewMember> crew) {
|
||||
super(boatID, threeLetterIOCCode, name);
|
||||
this.id = id;
|
||||
this.idAsString = idAsString;
|
||||
this.crew = crew;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return id;
|
||||
public String getIdAsString() {
|
||||
return idAsString;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -28,7 +28,7 @@ public class CompetitorWithID extends AbstractCompetitor {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + ((crew == null) ? 0 : crew.hashCode());
|
||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||
result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -46,10 +46,10 @@ public class CompetitorWithID extends AbstractCompetitor {
|
||||
return false;
|
||||
} else if (!crew.equals(other.crew))
|
||||
return false;
|
||||
if (id == null) {
|
||||
if (other.id != null)
|
||||
if (idAsString == null) {
|
||||
if (other.idAsString != null)
|
||||
return false;
|
||||
} else if (!id.equals(other.id))
|
||||
} else if (!idAsString.equals(other.idAsString))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -57,6 +57,6 @@ public class CompetitorWithID extends AbstractCompetitor {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CompetitorWithID [boatID=" + getBoatID() + ", threeLetterIOCCode=" + getThreeLetterIOCCode() + ", name=" + getName()
|
||||
+ ", id=" + id + ", crew=" + getCrew() + "]";
|
||||
+ ", id=" + idAsString + ", crew=" + getCrew() + "]";
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,7 +10,7 @@ public class CompetitorWithoutID extends AbstractCompetitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
public String getIdAsString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+27
-24
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
@@ -58,6 +59,7 @@ import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.WithID;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
import difflib.PatchFailedException;
|
||||
|
||||
@@ -72,7 +74,7 @@ import difflib.PatchFailedException;
|
||||
public class DomainFactoryImpl implements DomainFactory {
|
||||
private final static Logger logger = Logger.getLogger(DomainFactoryImpl.class.getName());
|
||||
private final Map<String, Regatta> raceIDToRegattaCache;
|
||||
private final Map<Iterable<String>, ControlPoint> controlPointCache;
|
||||
private final Map<Iterable<Serializable>, ControlPoint> controlPointCache;
|
||||
private final Map<String, RaceType> raceTypeByID;
|
||||
private final RaceType unknownRaceType;
|
||||
private final com.sap.sailing.domain.base.DomainFactory baseDomainFactory;
|
||||
@@ -80,7 +82,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
public DomainFactoryImpl(com.sap.sailing.domain.base.DomainFactory baseDomainFactory) {
|
||||
this.baseDomainFactory = baseDomainFactory;
|
||||
raceIDToRegattaCache = new HashMap<String, Regatta>();
|
||||
controlPointCache = new HashMap<Iterable<String>, ControlPoint>();
|
||||
controlPointCache = new HashMap<>();
|
||||
raceTypeByID = new HashMap<String, RaceType>();
|
||||
|
||||
for (OlympicRaceCode olympicRaceCode : OlympicRaceCode.values()) {
|
||||
@@ -121,7 +123,8 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
@Override
|
||||
public Pair<Competitor, Boat> createCompetitorWithID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, BoatClass boatClass) {
|
||||
CompetitorAndBoatStore competitorAndBoatStore = baseDomainFactory.getCompetitorAndBoatStore();
|
||||
CompetitorWithBoat domainCompetitor = competitorAndBoatStore.getExistingCompetitorWithBoatByIdAsString(competitor.getID());
|
||||
final Serializable competitorId = UUIDHelper.tryUuidConversion(competitor.getIdAsString());
|
||||
CompetitorWithBoat domainCompetitor = competitorAndBoatStore.getExistingCompetitorWithBoatById(competitorId);
|
||||
if (domainCompetitor == null || competitorAndBoatStore.isCompetitorToUpdateDuringGetOrCreate(domainCompetitor)) {
|
||||
List<DynamicPerson> teamMembers = new ArrayList<DynamicPerson>();
|
||||
for (CrewMember crewMember: competitor.getCrew()) {
|
||||
@@ -130,8 +133,8 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
teamMembers.add(person);
|
||||
}
|
||||
DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null);
|
||||
DynamicBoat domainBoat = new BoatImpl(competitor.getID(), null, boatClass, competitor.getBoatID(), null);
|
||||
domainCompetitor = competitorAndBoatStore.getOrCreateCompetitorWithBoat(competitor.getID(), competitor.getName(), null /* shortName */, null /*displayColor*/, null /*email*/, null, team,
|
||||
DynamicBoat domainBoat = new BoatImpl(competitorId, null, boatClass, competitor.getBoatID(), null);
|
||||
domainCompetitor = competitorAndBoatStore.getOrCreateCompetitorWithBoat(competitorId, competitor.getName(), null /* shortName */, null /*displayColor*/, null /*email*/, null, team,
|
||||
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null, domainBoat);
|
||||
}
|
||||
return new Pair<Competitor, Boat>(domainCompetitor, domainCompetitor.getBoat());
|
||||
@@ -266,8 +269,8 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
private Map<Competitor,Boat> createCompetitorsAndBoats(StartList startList, String raceId, BoatClass boatClass) {
|
||||
Map<Competitor, Boat> result = new LinkedHashMap<>();
|
||||
for (com.sap.sailing.domain.swisstimingadapter.Competitor swissTimingCompetitor : startList.getCompetitors()) {
|
||||
Pair<Competitor,Boat> domainCompetitorAndBoat;
|
||||
if (swissTimingCompetitor.getID() != null) {
|
||||
Pair<Competitor, Boat> domainCompetitorAndBoat;
|
||||
if (swissTimingCompetitor.getIdAsString() != null) {
|
||||
domainCompetitorAndBoat = createCompetitorWithID(swissTimingCompetitor, boatClass);
|
||||
} else {
|
||||
domainCompetitorAndBoat = createCompetitorWithoutID(swissTimingCompetitor, raceId, boatClass);
|
||||
@@ -280,7 +283,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
private com.sap.sailing.domain.base.Course createCourse(String courseName, Course course) {
|
||||
List<Waypoint> waypoints = new ArrayList<Waypoint>();
|
||||
for (Mark mark : course.getMarks()) {
|
||||
ControlPoint controlPoint = getOrCreateControlPoint(mark.getDevices(), getMarkType(mark.getMarkType()));
|
||||
ControlPoint controlPoint = getOrCreateControlPoint(mark.getDescription(), mark.getDeviceIds(), getMarkType(mark.getMarkType()));
|
||||
Waypoint waypoint = baseDomainFactory.createWaypoint(controlPoint, /* passingInstruction */ PassingInstruction.None);
|
||||
waypoints.add(waypoint);
|
||||
}
|
||||
@@ -302,44 +305,44 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControlPoint getOrCreateControlPoint(Iterable<String> devices, MarkType markType) {
|
||||
public ControlPoint getOrCreateControlPoint(String description, Iterable<Serializable> deviceIds, MarkType markType) {
|
||||
ControlPoint result;
|
||||
synchronized (controlPointCache) {
|
||||
result = controlPointCache.get(devices);
|
||||
result = controlPointCache.get(deviceIds);
|
||||
if (result == null) {
|
||||
switch (Util.size(devices)) {
|
||||
switch (Util.size(deviceIds)) {
|
||||
case 1:
|
||||
result = getOrCreateMark(devices.iterator().next(), markType);
|
||||
result = getOrCreateMark(description, deviceIds.iterator().next(), markType);
|
||||
break;
|
||||
case 2:
|
||||
Iterator<String> markNameIter = devices.iterator();
|
||||
String left = markNameIter.next();
|
||||
String right = markNameIter.next();
|
||||
result = baseDomainFactory.createControlPointWithTwoMarks(getOrCreateMark(left), getOrCreateMark(right), left + "/" + right);
|
||||
Iterator<Serializable> markNameIter = deviceIds.iterator();
|
||||
final Serializable idLeft = markNameIter.next();
|
||||
final Serializable idRight = markNameIter.next();
|
||||
result = baseDomainFactory.createControlPointWithTwoMarks(getOrCreateMark(idLeft, description), getOrCreateMark(idRight, description), description);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException(
|
||||
"Don't know how to handle control points with number of devices neither 1 nor 2. Was "
|
||||
+ Util.size(devices));
|
||||
+ Util.size(deviceIds));
|
||||
}
|
||||
controlPointCache.put(devices, result);
|
||||
controlPointCache.put(deviceIds, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private ControlPoint getOrCreateMark(String name, MarkType markType) {
|
||||
return baseDomainFactory.getOrCreateMark(name, markType);
|
||||
private ControlPoint getOrCreateMark(String description, Serializable id, MarkType markType) {
|
||||
return baseDomainFactory.getOrCreateMark(id, description, markType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param trackerID
|
||||
* @param trackerId
|
||||
* the "device name" and the "sail number" in case of an {@link MessageType#RPD RPD} message, used as the mark's
|
||||
* {@link Named#getName() name} and {@link WithID#getId() ID}.
|
||||
*/
|
||||
@Override
|
||||
public com.sap.sailing.domain.base.Mark getOrCreateMark(String trackerID) {
|
||||
return baseDomainFactory.getOrCreateMark(trackerID);
|
||||
public com.sap.sailing.domain.base.Mark getOrCreateMark(Serializable trackerId, String description) {
|
||||
return baseDomainFactory.getOrCreateMark(trackerId, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -354,7 +357,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
List<com.sap.sse.common.Util.Pair<com.sap.sailing.domain.base.ControlPoint, PassingInstruction>> newDomainControlPoints = new ArrayList<com.sap.sse.common.Util.Pair<com.sap.sailing.domain.base.ControlPoint, PassingInstruction>>();
|
||||
for (Mark mark : marks) {
|
||||
// TODO bug 1043: propagate the mark names to the waypoint names
|
||||
com.sap.sailing.domain.base.ControlPoint domainControlPoint = getOrCreateControlPoint(mark.getDevices(), getMarkType(mark.getMarkType()));
|
||||
com.sap.sailing.domain.base.ControlPoint domainControlPoint = getOrCreateControlPoint(mark.getDescription(), mark.getDeviceIds(), getMarkType(mark.getMarkType()));
|
||||
newDomainControlPoints.add(new com.sap.sse.common.Util.Pair<>(domainControlPoint, PassingInstruction.None));
|
||||
}
|
||||
courseToUpdate.update(newDomainControlPoints, baseDomainFactory);
|
||||
|
||||
+7
-5
@@ -1,5 +1,7 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
@@ -8,7 +10,7 @@ import com.sap.sailing.domain.swisstimingadapter.Fix;
|
||||
import com.sap.sailing.domain.swisstimingadapter.TrackerType;
|
||||
|
||||
public class FixImpl implements Fix {
|
||||
private final String boatID;
|
||||
private final Serializable trackedObjectId;
|
||||
private final TrackerType trackerType;
|
||||
private final Long ageOfDataInMilliseconds;
|
||||
private final Position position;
|
||||
@@ -25,11 +27,11 @@ public class FixImpl implements Fix {
|
||||
*/
|
||||
private final String boatIRM;
|
||||
|
||||
public FixImpl(String boatID, TrackerType trackerType, Long ageOfDataInMilliseconds, Position position,
|
||||
public FixImpl(Serializable trackedObjectId, TrackerType trackerType, Long ageOfDataInMilliseconds, Position position,
|
||||
SpeedWithBearing speed, Integer nextMarkIndex, Integer rank, Speed averageSpeedOverGroundPerLeg,
|
||||
Speed velocityMadeGood, Distance distanceToLeader, Distance distanceToNextMark, String boatIRM) {
|
||||
super();
|
||||
this.boatID = boatID;
|
||||
this.trackedObjectId = trackedObjectId;
|
||||
this.trackerType = trackerType;
|
||||
this.ageOfDataInMilliseconds = ageOfDataInMilliseconds;
|
||||
this.position = position;
|
||||
@@ -49,8 +51,8 @@ public class FixImpl implements Fix {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBoatID() {
|
||||
return boatID;
|
||||
public Serializable getTrackedObjectId() {
|
||||
return trackedObjectId;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+11
-12
@@ -1,25 +1,28 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.swisstimingadapter.Mark;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class MarkImpl implements Mark {
|
||||
private final String description;
|
||||
private final int index;
|
||||
private final Iterable<String> devices;
|
||||
private final Iterable<Serializable> deviceIds;
|
||||
private final MarkType markType;
|
||||
|
||||
public MarkImpl(String description, int index, Iterable<String> devices, MarkType markType) {
|
||||
public MarkImpl(String description, int index, Iterable<Serializable> devices, MarkType markType) {
|
||||
super();
|
||||
this.description = description;
|
||||
this.index = index;
|
||||
this.markType = markType;
|
||||
ArrayList<String> l = new ArrayList<String>();
|
||||
for (String device : devices) {
|
||||
List<Serializable> l = new ArrayList<>();
|
||||
for (Serializable device : devices) {
|
||||
l.add(device);
|
||||
}
|
||||
this.devices = l;
|
||||
this.deviceIds = l;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -38,8 +41,8 @@ public class MarkImpl implements Mark {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> getDevices() {
|
||||
return devices;
|
||||
public Iterable<Serializable> getDeviceIds() {
|
||||
return deviceIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,11 +52,7 @@ public class MarkImpl implements Mark {
|
||||
result.append(": ");
|
||||
result.append(getDescription());
|
||||
result.append(" [");
|
||||
for (String device : getDevices()) {
|
||||
result.append(device);
|
||||
result.append(", ");
|
||||
}
|
||||
result.delete(result.length()-2, result.length());
|
||||
result.append(Util.join(", ", getDeviceIds()));
|
||||
result.append("]");
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
+48
-44
@@ -25,6 +25,7 @@ import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.common.AbstractBearing;
|
||||
@@ -55,6 +56,7 @@ import com.sap.sailing.domain.swisstimingadapter.TrackerType;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
/**
|
||||
* Implements the connector to the SwissTiming Sail Master system. It uses a host name and port number to establish the
|
||||
@@ -283,7 +285,7 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
|
||||
private void notifyListenersTMD(SailMasterMessage message) {
|
||||
// example message: TMD|W4702|NZL 75|1|4;;00:49:43
|
||||
String raceID = message.getSections()[1];
|
||||
String boatID = message.getSections()[2];
|
||||
String competitorIdAsString = message.getSections()[2];
|
||||
int count = Integer.valueOf(message.getSections()[3]);
|
||||
List<Util.Triple<Integer, Integer, Long>> markIndicesRanksAndTimesSinceStartInMilliseconds = new ArrayList<Util.Triple<Integer,Integer,Long>>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -296,7 +298,7 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
|
||||
}
|
||||
for (SailMasterListener listener : getListeners()) {
|
||||
try {
|
||||
listener.receivedTimingData(raceID, boatID, markIndicesRanksAndTimesSinceStartInMilliseconds);
|
||||
listener.receivedTimingData(raceID, competitorIdAsString, markIndicesRanksAndTimesSinceStartInMilliseconds);
|
||||
} catch (Exception e) {
|
||||
logger.info("Exception occurred trying to notify listener "+listener+" about "+message+": "+e.getMessage());
|
||||
logger.throwing(SailMasterConnectorImpl.class.getName(), "notifyListenersTMD", e);
|
||||
@@ -359,12 +361,12 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
|
||||
String raceID = sections[1];
|
||||
final RaceStatus raceStatus;
|
||||
final RacingStatus racingStatus;
|
||||
if (sections[2].contains(",")) {
|
||||
final String[] raceStatusIntAndRacingStatusInt = sections[2].split(",");
|
||||
final String[] raceStatusIntAndRacingStatusInt = sections[2].split(",");
|
||||
if (raceStatusIntAndRacingStatusInt.length > 1) {
|
||||
raceStatus = RaceStatus.values()[Integer.valueOf(raceStatusIntAndRacingStatusInt[0])];
|
||||
racingStatus = RacingStatus.values()[Integer.valueOf(raceStatusIntAndRacingStatusInt[1])];
|
||||
} else {
|
||||
raceStatus = RaceStatus.values()[Integer.valueOf(sections[2])];
|
||||
raceStatus = RaceStatus.values()[Integer.valueOf(raceStatusIntAndRacingStatusInt[0])];
|
||||
racingStatus = null;
|
||||
}
|
||||
TimePoint timePoint = new MillisecondsTimePoint(parseTimeAndDateISO(sections[3], raceID));
|
||||
@@ -386,45 +388,47 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
|
||||
final String[] fixSections = sections[9+i].split(";");
|
||||
final boolean postVersion1_0 = sections[9+i].split(";", -1).length >= 14;
|
||||
if (fixSections.length > 2) {
|
||||
final String boatID = fixSections[fixDetailIndex++];
|
||||
final TrackerType trackerType = TrackerType.values()[Integer.valueOf(fixSections[fixDetailIndex++])];
|
||||
final Long ageOfDataInMilliseconds = 1000l * Long.valueOf(fixSections[fixDetailIndex++]);
|
||||
final Position position = new DegreePosition(Double.valueOf(fixSections[fixDetailIndex++]),
|
||||
Double.valueOf(fixSections[fixDetailIndex++]));
|
||||
final Double speedOverGroundInKnots = Double.valueOf(fixSections[fixDetailIndex++]);
|
||||
final int alsIndex = postVersion1_0 ? fixDetailIndex+1 : fixDetailIndex;
|
||||
final int vmgIndex = postVersion1_0 ? fixDetailIndex : fixDetailIndex+1;
|
||||
final Speed averageSpeedOverGround = fixSections[alsIndex].trim().length() == 0 ? null
|
||||
: new KnotSpeedImpl(Double.valueOf(fixSections[alsIndex]));
|
||||
final Speed velocityMadeGood = fixSections[vmgIndex].trim().length() == 0 ? null : new KnotSpeedImpl(
|
||||
Double.valueOf(fixSections[vmgIndex]));
|
||||
fixDetailIndex += 2;
|
||||
final AbstractBearing cog = new DegreeBearingImpl(
|
||||
Double.valueOf(fixSections[fixDetailIndex++]));
|
||||
final SpeedWithBearing speed = new KnotSpeedWithBearingImpl(speedOverGroundInKnots, cog);
|
||||
final Integer nextMarkIndex = fixSections.length <= fixDetailIndex
|
||||
|| fixSections[fixDetailIndex].trim().length() == 0 ? null : Integer
|
||||
.valueOf(fixSections[fixDetailIndex]);
|
||||
fixDetailIndex++;
|
||||
final Integer rank = fixSections.length <= fixDetailIndex || fixSections[fixDetailIndex].trim().length() == 0 ? null
|
||||
: Integer.valueOf(fixSections[fixDetailIndex]);
|
||||
fixDetailIndex++;
|
||||
final Distance distanceToLeader = fixSections.length <= fixDetailIndex
|
||||
|| fixSections[fixDetailIndex].trim().length() == 0 ? null : new MeterDistance(
|
||||
Double.valueOf(fixSections[fixDetailIndex]));
|
||||
fixDetailIndex++;
|
||||
final Distance distanceToNextMark = fixSections.length <= fixDetailIndex
|
||||
|| fixSections[fixDetailIndex].trim().length() == 0 ? null : new MeterDistance(
|
||||
Double.valueOf(fixSections[fixDetailIndex]));
|
||||
fixDetailIndex++;
|
||||
final String boatIRM; // the "disqualification" or "MaxPointReason"
|
||||
if (postVersion1_0 && fixSections.length > fixDetailIndex) {
|
||||
boatIRM = fixSections[fixDetailIndex++];
|
||||
} else {
|
||||
boatIRM = null;
|
||||
final String trackedObjectIdAsString = fixSections[fixDetailIndex++].trim();
|
||||
if (trackedObjectIdAsString != null && !trackedObjectIdAsString.isEmpty()) {
|
||||
final TrackerType trackerType = TrackerType.values()[Integer.valueOf(fixSections[fixDetailIndex++])];
|
||||
final Long ageOfDataInMilliseconds = 1000l * Long.valueOf(fixSections[fixDetailIndex++]);
|
||||
final Position position = new DegreePosition(Double.valueOf(fixSections[fixDetailIndex++]),
|
||||
Double.valueOf(fixSections[fixDetailIndex++]));
|
||||
final Double speedOverGroundInKnots = Double.valueOf(fixSections[fixDetailIndex++]);
|
||||
final int alsIndex = postVersion1_0 ? fixDetailIndex+1 : fixDetailIndex;
|
||||
final int vmgIndex = postVersion1_0 ? fixDetailIndex : fixDetailIndex+1;
|
||||
final Speed averageSpeedOverGround = fixSections[alsIndex].trim().length() == 0 ? null
|
||||
: new KnotSpeedImpl(Double.valueOf(fixSections[alsIndex]));
|
||||
final Speed velocityMadeGood = fixSections[vmgIndex].trim().length() == 0 ? null : new KnotSpeedImpl(
|
||||
Double.valueOf(fixSections[vmgIndex]));
|
||||
fixDetailIndex += 2;
|
||||
final AbstractBearing cog = new DegreeBearingImpl(
|
||||
Double.valueOf(fixSections[fixDetailIndex++]));
|
||||
final SpeedWithBearing speed = new KnotSpeedWithBearingImpl(speedOverGroundInKnots, cog);
|
||||
final Integer nextMarkIndex = fixSections.length <= fixDetailIndex
|
||||
|| fixSections[fixDetailIndex].trim().length() == 0 ? null : Integer
|
||||
.valueOf(fixSections[fixDetailIndex]);
|
||||
fixDetailIndex++;
|
||||
final Integer rank = fixSections.length <= fixDetailIndex || fixSections[fixDetailIndex].trim().length() == 0 ? null
|
||||
: Integer.valueOf(fixSections[fixDetailIndex]);
|
||||
fixDetailIndex++;
|
||||
final Distance distanceToLeader = fixSections.length <= fixDetailIndex
|
||||
|| fixSections[fixDetailIndex].trim().length() == 0 ? null : new MeterDistance(
|
||||
Double.valueOf(fixSections[fixDetailIndex]));
|
||||
fixDetailIndex++;
|
||||
final Distance distanceToNextMark = fixSections.length <= fixDetailIndex
|
||||
|| fixSections[fixDetailIndex].trim().length() == 0 ? null : new MeterDistance(
|
||||
Double.valueOf(fixSections[fixDetailIndex]));
|
||||
fixDetailIndex++;
|
||||
final String boatIRM; // the "disqualification" or "MaxPointReason"
|
||||
if (postVersion1_0 && fixSections.length > fixDetailIndex) {
|
||||
boatIRM = fixSections[fixDetailIndex++];
|
||||
} else {
|
||||
boatIRM = null;
|
||||
}
|
||||
fixes.add(new FixImpl(UUIDHelper.tryUuidConversion(trackedObjectIdAsString), trackerType, ageOfDataInMilliseconds, position, speed, nextMarkIndex,
|
||||
rank, averageSpeedOverGround, velocityMadeGood, distanceToLeader, distanceToNextMark, boatIRM));
|
||||
}
|
||||
fixes.add(new FixImpl(boatID, trackerType, ageOfDataInMilliseconds, position, speed, nextMarkIndex,
|
||||
rank, averageSpeedOverGround, velocityMadeGood, distanceToLeader, distanceToNextMark, boatIRM));
|
||||
}
|
||||
}
|
||||
Set<SailMasterListener> allListeners = getListeners();
|
||||
@@ -625,7 +629,7 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
|
||||
devicesNamesStartIndex = 2;
|
||||
}
|
||||
marks.add(new MarkImpl(markDetails[1], Integer.valueOf(markDetails[0]),
|
||||
Arrays.asList(markDetails).subList(devicesNamesStartIndex, markDetails.length),
|
||||
Arrays.asList(markDetails).subList(devicesNamesStartIndex, markDetails.length).stream().map(idAsString->UUIDHelper.tryUuidConversion(idAsString)).collect(Collectors.toList()),
|
||||
markType));
|
||||
}
|
||||
return new CourseImpl(courseConfigurationMessage.getSections()[1], marks);
|
||||
|
||||
-1
@@ -99,7 +99,6 @@ public class SwissTimingAdapterImpl implements SwissTimingAdapter {
|
||||
teams.put(t.getTeamID(), t);
|
||||
}
|
||||
}
|
||||
|
||||
for (Object o : regattaResults.getPersonOrBoatOrTeam()) {
|
||||
if (o instanceof Event) {
|
||||
Event event = (Event) o;
|
||||
|
||||
+13
-39
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.ParseException;
|
||||
@@ -12,6 +13,7 @@ import java.util.Map;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -42,7 +44,6 @@ import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.swisstimingadapter.Fix;
|
||||
import com.sap.sailing.domain.swisstimingadapter.Race;
|
||||
import com.sap.sailing.domain.swisstimingadapter.RaceStatus;
|
||||
import com.sap.sailing.domain.swisstimingadapter.RaceType;
|
||||
import com.sap.sailing.domain.swisstimingadapter.RacingStatus;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterListener;
|
||||
@@ -276,13 +277,13 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
case JURY:
|
||||
case TIMINGSCORING:
|
||||
case UNIDENTIFIED:
|
||||
String trackerID = fix.getBoatID();
|
||||
Mark mark = domainFactory.getOrCreateMark(trackerID);
|
||||
Serializable trackerID = fix.getTrackedObjectId();
|
||||
Mark mark = domainFactory.getOrCreateMark(trackerID, /* description */ null);
|
||||
trackedRace.recordFix(mark, gpsFix);
|
||||
break;
|
||||
case COMPETITOR:
|
||||
String boatID = fix.getBoatID();
|
||||
Competitor competitor = getCompetitorByBoatIDAndRaceIDOrBoatClass(boatID, raceID, boatClass);
|
||||
Serializable competitorId = fix.getTrackedObjectId();
|
||||
Competitor competitor = getDomainFactory().getBaseDomainFactory().getExistingCompetitorById(competitorId);
|
||||
if (competitor == null) {
|
||||
// TODO: read startlist again from Manage2Sail
|
||||
// use competitorStore.isCompetitorToUpdateDuringGetOrCreate(result)
|
||||
@@ -291,7 +292,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
DynamicGPSFixTrack<Competitor, GPSFixMoving> competitorTrack = trackedRace.getTrack(competitor);
|
||||
competitorTrack.addGPSFix(gpsFix);
|
||||
} else {
|
||||
logger.info("Unknown competitor " + boatID + " found for race with id " + raceID);
|
||||
logger.info("Unknown competitor " + competitorId + " found for race with id " + raceID);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -310,41 +311,15 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
|
||||
}
|
||||
|
||||
private Competitor getCompetitorByBoatIDAndRaceType(String boatID, RaceType raceType) {
|
||||
return domainFactory.getBaseDomainFactory().getExistingCompetitorById(domainFactory.getCompetitorID(boatID, raceType));
|
||||
}
|
||||
|
||||
private Competitor getCompetitorByBoatIDAndBoatClass(String boatID, BoatClass boatClass) {
|
||||
return domainFactory.getBaseDomainFactory().getExistingCompetitorById(domainFactory.getCompetitorID(boatID, boatClass));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Competitor getCompetitorByBoatIDAndRaceIDOrBoatClass(String boatID, String raceID, BoatClass boatClass) {
|
||||
Competitor result = null;
|
||||
// first look into the temp cache
|
||||
result = competitorsByBoatId.get(boatID);
|
||||
if (result == null) {
|
||||
if (boatClass != null) {
|
||||
result = getCompetitorByBoatIDAndBoatClass(boatID, boatClass);
|
||||
} else {
|
||||
RaceType raceType = domainFactory.getRaceTypeFromRaceID(raceID);
|
||||
if (raceType != null) {
|
||||
result = getCompetitorByBoatIDAndRaceType(boatID, raceType);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receivedTimingData(String raceID, String boatID,
|
||||
public void receivedTimingData(String raceID, String competitorIdAsString,
|
||||
List<com.sap.sse.common.Util.Triple<Integer, Integer, Long>> markIndicesRanksAndTimesSinceStartInMilliseconds) {
|
||||
assert this.raceID.equals(raceID);
|
||||
if (!useInternalMarkPassingAlgorithm) {
|
||||
if (isTrackedRaceStillReachable()) {
|
||||
Competitor competitor = getCompetitorByBoatIDAndRaceIDOrBoatClass(boatID, raceID, boatClass);
|
||||
final Competitor competitor = domainFactory.getBaseDomainFactory().getExistingCompetitorById(UUID.fromString(competitorIdAsString));
|
||||
if (competitor == null) {
|
||||
logger.info("Received timing data for boat ID " + boatID + " in race " + raceID
|
||||
logger.info("Received timing data for boat ID " + competitorIdAsString + " in race " + raceID
|
||||
+ " but couldn't find a competitor with that boat ID in this race. Ignoring.");
|
||||
} else {
|
||||
// the list of mark indices and time stamps is partial and usually only shows the last mark passing;
|
||||
@@ -378,8 +353,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
final TimePoint startTime = trackedRace.getStartOfRace();
|
||||
MillisecondsTimePoint timePoint = new MillisecondsTimePoint(startTime.asMillis()
|
||||
+ markIndexRankAndTimeSinceStartInMilliseconds.getC());
|
||||
MarkPassing markPassing = domainFactory.createMarkPassing(timePoint, waypoint,
|
||||
getCompetitorByBoatIDAndRaceIDOrBoatClass(boatID, raceID, boatClass));
|
||||
MarkPassing markPassing = domainFactory.createMarkPassing(timePoint, waypoint, competitor);
|
||||
markPassingsByMarkIndex.put(markIndexRankAndTimeSinceStartInMilliseconds.getA(),
|
||||
markPassing);
|
||||
} else {
|
||||
@@ -387,7 +361,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
+ trackedRace.getRace().getName()
|
||||
+ " before having received a race start time."
|
||||
+ " Queueing message for re-application when a start time has been received.");
|
||||
tmdMessageQueue.enqueue(raceID, boatID,
|
||||
tmdMessageQueue.enqueue(raceID, competitorIdAsString,
|
||||
markIndicesRanksAndTimesSinceStartInMilliseconds);
|
||||
}
|
||||
}
|
||||
@@ -474,7 +448,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
// temp
|
||||
CompetitorAndBoatStore competitorStore = domainFactory.getBaseDomainFactory().getCompetitorAndBoatStore();
|
||||
for (com.sap.sailing.domain.swisstimingadapter.Competitor c : startList.getCompetitors()) {
|
||||
Competitor existingCompetitor = competitorStore.getExistingCompetitorByIdAsString(c.getID());
|
||||
Competitor existingCompetitor = competitorStore.getExistingCompetitorByIdAsString(c.getIdAsString());
|
||||
if (existingCompetitor != null) {
|
||||
competitorsByBoatId.put(c.getBoatID(), existingCompetitor);
|
||||
}
|
||||
|
||||
+12
-12
@@ -8,6 +8,7 @@ import java.util.Map;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
@@ -30,14 +31,14 @@ public class TMDMessageQueue {
|
||||
|
||||
private static class TMDMessageContents {
|
||||
private final String raceID;
|
||||
private final String boatID;
|
||||
private final String competitorIdAsString;
|
||||
private final List<Util.Triple<Integer, Integer, Long>> markIndicesRanksAndTimesSinceStartInMilliseconds;
|
||||
|
||||
public TMDMessageContents(String raceID, String boatID,
|
||||
public TMDMessageContents(String raceID, String competitorIdAsString,
|
||||
List<Util.Triple<Integer, Integer, Long>> markIndicesRanksAndTimesSinceStartInMilliseconds) {
|
||||
super();
|
||||
this.raceID = raceID;
|
||||
this.boatID = boatID;
|
||||
this.competitorIdAsString = competitorIdAsString;
|
||||
this.markIndicesRanksAndTimesSinceStartInMilliseconds = markIndicesRanksAndTimesSinceStartInMilliseconds;
|
||||
}
|
||||
|
||||
@@ -45,8 +46,8 @@ public class TMDMessageQueue {
|
||||
return raceID;
|
||||
}
|
||||
|
||||
public String getBoatID() {
|
||||
return boatID;
|
||||
public String getCompetitorIdAsString() {
|
||||
return competitorIdAsString;
|
||||
}
|
||||
|
||||
public List<Util.Triple<Integer, Integer, Long>> getMarkIndicesRanksAndTimesSinceStartInMilliseconds() {
|
||||
@@ -55,7 +56,7 @@ public class TMDMessageQueue {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder("TMD|"+getRaceID()+"|"+getBoatID()+"|");
|
||||
StringBuilder result = new StringBuilder("TMD|"+getRaceID()+"|"+getCompetitorIdAsString()+"|");
|
||||
result.append(getMarkIndicesRanksAndTimesSinceStartInMilliseconds().size());
|
||||
result.append('|');
|
||||
for (Util.Triple<Integer, Integer, Long> markIndexRankAndTimeSinceStartInMilliseconds : getMarkIndicesRanksAndTimesSinceStartInMilliseconds()) {
|
||||
@@ -82,8 +83,8 @@ public class TMDMessageQueue {
|
||||
queuedMessages = new HashSet<>();
|
||||
}
|
||||
|
||||
public synchronized void enqueue(String raceID, String boatID, List<Util.Triple<Integer, Integer, Long>> markIndicesRanksAndTimesSinceStartInMilliseconds) {
|
||||
final TMDMessageContents message = new TMDMessageContents(raceID, boatID, markIndicesRanksAndTimesSinceStartInMilliseconds);
|
||||
public synchronized void enqueue(String raceID, String competitorIdAsString, List<Util.Triple<Integer, Integer, Long>> markIndicesRanksAndTimesSinceStartInMilliseconds) {
|
||||
final TMDMessageContents message = new TMDMessageContents(raceID, competitorIdAsString, markIndicesRanksAndTimesSinceStartInMilliseconds);
|
||||
queuedMessages.add(message);
|
||||
logger.info("Queued TMD message "+message+" for replay when start time has been received");
|
||||
}
|
||||
@@ -101,10 +102,9 @@ public class TMDMessageQueue {
|
||||
// otherwise, this could lead to the "guessed time" to
|
||||
while (i.hasNext()) {
|
||||
TMDMessageContents messageContents = i.next();
|
||||
Competitor competitor = raceTracker.getCompetitorByBoatIDAndRaceIDOrBoatClass(messageContents.getBoatID(),
|
||||
messageContents.getRaceID(), raceTracker.getBoatClass());
|
||||
Competitor competitor = raceTracker.getDomainFactory().getBaseDomainFactory().getExistingCompetitorById(UUID.fromString(messageContents.getCompetitorIdAsString()));
|
||||
if (competitor == null) {
|
||||
logger.info("Received timing data for boat ID " + messageContents.getBoatID() + " in race " + messageContents.getRaceID()
|
||||
logger.info("Received timing data for boat ID " + messageContents.getCompetitorIdAsString() + " in race " + messageContents.getRaceID()
|
||||
+ " but couldn't find a competitor with that boat ID in this race. Ignoring.");
|
||||
} else {
|
||||
NavigableSet<MarkPassing> oldMarkPassings = trackedRace.getMarkPassings(competitor);
|
||||
@@ -156,7 +156,7 @@ public class TMDMessageQueue {
|
||||
while (i.hasNext()) {
|
||||
TMDMessageContents messageContents = i.next();
|
||||
logger.info("Re-Playing TMD message "+messageContents+" with new race start time "+trackedRace.getStartOfRace());
|
||||
raceTracker.receivedTimingData(messageContents.getRaceID(), messageContents.getBoatID(),
|
||||
raceTracker.receivedTimingData(messageContents.getRaceID(), messageContents.getCompetitorIdAsString(),
|
||||
messageContents.getMarkIndicesRanksAndTimesSinceStartInMilliseconds());
|
||||
i.remove();
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.swisstimingreplayadapter.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
@@ -308,7 +309,7 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter i
|
||||
competitorByHashValue.put(hashValue, competitorAndBoat.getA());
|
||||
} else {
|
||||
// consider it a mark
|
||||
Mark mark = domainFactory.getOrCreateMark(sailNumberOrTrackerID.trim());
|
||||
Mark mark = domainFactory.getOrCreateMark(sailNumberOrTrackerID.trim(), name);
|
||||
Map<String, Mark> marksOfCurrentRace = marksPerRaceIDPerMarkID.get(currentRaceID);
|
||||
if (marksOfCurrentRace == null) {
|
||||
marksOfCurrentRace = new HashMap<>();
|
||||
@@ -323,12 +324,12 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter i
|
||||
@Override
|
||||
public void mark(MarkType markType, String name, byte index, String id1, String id2, short windSpeedInKnots,
|
||||
short trueWindDirectionInDegrees) {
|
||||
final List<String> markNames = new ArrayList<>();
|
||||
markNames.add(id1.trim());
|
||||
final List<Serializable> markNamesAsIds = new ArrayList<>();
|
||||
markNamesAsIds.add(id1.trim());
|
||||
if (id2 != null && !id2.trim().isEmpty()) {
|
||||
markNames.add(id2.trim());
|
||||
markNamesAsIds.add(id2.trim());
|
||||
}
|
||||
final ControlPoint controlPoint = domainFactory.getOrCreateControlPoint(markNames, getMarkType(markType));
|
||||
final ControlPoint controlPoint = domainFactory.getOrCreateControlPoint(name, markNamesAsIds, getMarkType(markType));
|
||||
if (index == 0) {
|
||||
currentCourseDefinition = new ArrayList<>();
|
||||
}
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.sap.sailing.gwt.common.client.suggestion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.RegattasDisplayer;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.util.NaturalComparator;
|
||||
|
||||
public class RegattaSuggestOracle extends AbstractListSuggestOracle<RegattaDTO> implements RegattasDisplayer {
|
||||
public RegattaSuggestOracle() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String createSuggestionKeyString(RegattaDTO value) {
|
||||
return value.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String createSuggestionAdditionalDisplayString(RegattaDTO value) {
|
||||
return value.boatClass.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<String> getMatchingStrings(RegattaDTO value) {
|
||||
return Arrays.asList(value.getName(), value.boatClass.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRegattas(Iterable<RegattaDTO> result) {
|
||||
final List<RegattaDTO> sorted = new ArrayList<>();
|
||||
final NaturalComparator nameComparator = new NaturalComparator(/* case sensitive */ false);
|
||||
Util.addAll(result, sorted);
|
||||
Collections.sort(sorted, (r1, r2)->nameComparator.compare(r1.getName(), r2.getName()));
|
||||
setSelectableValues(sorted);
|
||||
}
|
||||
}
|
||||
+6
@@ -146,6 +146,7 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl
|
||||
true, /* enablePager */true, /* filterCompetitorWithBoat */ canBoatsOfCompetitorsChangePerRace, /* filterCompetitorsWithoutBoat */ !canBoatsOfCompetitorsChangePerRace);
|
||||
registeredCompetitorsTable = new CompetitorTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */
|
||||
true, /* enablePager */false, /* filterCompetitorWithBoat */ false, /* filterCompetitorsWithoutBoat */ false);
|
||||
registeredCompetitorsTable.getSelectionModel().addSelectionChangeHandler(event -> validateAndUpdate());
|
||||
allCompetitorsPanel.add(allCompetitorsTable);
|
||||
registeredCompetitorsPanel.add(registeredCompetitorsTable);
|
||||
VerticalPanel movePanel = new VerticalPanel();
|
||||
@@ -229,6 +230,7 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl
|
||||
protected void addImportedCompetitorsToRegisteredCompetitorsTableAndRemoveFromAllCompetitorsTable(Iterable<CompetitorWithBoatDTO> competitorsImported) {
|
||||
allCompetitorsTable.getFilterField().removeAll(competitorsImported);
|
||||
registeredCompetitorsTable.getFilterField().addAll(competitorsImported);
|
||||
validateAndUpdate();
|
||||
}
|
||||
|
||||
private void moveSelected(CompetitorTableWrapper<RefreshableMultiSelectionModel<CompetitorWithBoatDTO>> from,
|
||||
@@ -319,4 +321,8 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl
|
||||
public void moveFromPoolToRegistered(Collection<CompetitorWithBoatDTO> registeredCompetitors) {
|
||||
move(allCompetitorsTable, registeredCompetitorsTable, registeredCompetitors);
|
||||
}
|
||||
|
||||
public Set<CompetitorWithBoatDTO> getSelectedRegisteredCompetitors() {
|
||||
return registeredCompetitorsTable.getSelectionModel().getSelectedSet();
|
||||
}
|
||||
}
|
||||
Regular → Executable
+99
-36
@@ -20,39 +20,49 @@ import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.Validator;
|
||||
|
||||
/**
|
||||
* This is the UI wizard to be executed after
|
||||
* {@link com.sap.sailing.server.gateway.trackfiles.impl.ExpeditionAllInOneImporter ExpeditionAllInOneImporter}
|
||||
* succeeded running. This provides the functionality to add new {@link com.sap.sailing.domain.base.Competitor
|
||||
* Competitors} to the {@link com.sap.sailing.domain.base.Regatta Regatta} and automatically maps the imported GPS and
|
||||
* Bravo tracks to a selected {@link com.sap.sailing.domain.base.Competitor Competitor}. In addition, the
|
||||
* {@link com.sap.sailing.domain.tracking.TrackedRace TrackedRace} is retracked after the process to ensure that newly
|
||||
* added competitors are correctly visible afterwards. After the import finished successfully, a dialog is provided to
|
||||
* the user that shows links to the event page and race board.
|
||||
*/
|
||||
public class ExpeditionAllInOneAfterImportHandler {
|
||||
|
||||
private final SailingServiceAsync sailingService;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final StringMessages stringMessages;
|
||||
private final RegattaNameAndRaceName regattaAndRaceIdentifier;
|
||||
private final String leaderboardGroupName;
|
||||
private final String raceColumnName;
|
||||
private final String fleetName;
|
||||
protected EventDTO event;
|
||||
private RegattaDTO regatta;
|
||||
private StrippedLeaderboardDTO leaderboard;
|
||||
private List<TrackFileImportDeviceIdentifierDTO> gpsFixesDeviceIDs;
|
||||
private List<TrackFileImportDeviceIdentifierDTO> sensorFixesDeviceIDs;
|
||||
private final String sensorImporterType;
|
||||
private List<Triple<String, String, String>> raceEntries;
|
||||
private String regattaName;
|
||||
|
||||
public ExpeditionAllInOneAfterImportHandler(UUID eventId, String regattaName, String leaderboardName,
|
||||
String leaderboardGroupName, String raceName, String raceColumnName, String fleetName,
|
||||
String leaderboardGroupName, List<Triple<String, String, String>> raceEntries,
|
||||
List<String> gpsDeviceIds, List<String> sensorDeviceIds, String sensorImporterType,
|
||||
final SailingServiceAsync sailingService, final ErrorReporter errorReporter,
|
||||
final StringMessages stringMessages) {
|
||||
this.leaderboardGroupName = leaderboardGroupName;
|
||||
this.raceColumnName = raceColumnName;
|
||||
this.fleetName = fleetName;
|
||||
this.sensorImporterType = sensorImporterType;
|
||||
this.sailingService = sailingService;
|
||||
this.errorReporter = errorReporter;
|
||||
this.stringMessages = stringMessages;
|
||||
this.regattaAndRaceIdentifier = new RegattaNameAndRaceName(regattaName, raceName);
|
||||
this.raceEntries = raceEntries;
|
||||
this.regattaName = regattaName;
|
||||
|
||||
sailingService.getEventById(eventId, false, new DataLoadingCallback<EventDTO>() {
|
||||
@Override
|
||||
@@ -89,32 +99,77 @@ public class ExpeditionAllInOneAfterImportHandler {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class RegattaLogCompetitorRegistrationAndSelectionDialog extends RegattaLogCompetitorRegistrationDialog {
|
||||
public RegattaLogCompetitorRegistrationAndSelectionDialog(String boatClass, SailingServiceAsync sailingService,
|
||||
StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName,
|
||||
boolean canBoatsOfCompetitorsChangePerRace) {
|
||||
this(boatClass, sailingService, stringMessages, errorReporter, editable, leaderboardName,
|
||||
canBoatsOfCompetitorsChangePerRace, new ValidatorForCompetitorRegistrationDialog(stringMessages),
|
||||
new CallbackForCompetitorRegistrationDialog());
|
||||
}
|
||||
|
||||
public RegattaLogCompetitorRegistrationAndSelectionDialog(String boatClass, SailingServiceAsync sailingService,
|
||||
StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName,
|
||||
boolean canBoatsOfCompetitorsChangePerRace, ValidatorForCompetitorRegistrationDialog validator,
|
||||
CallbackForCompetitorRegistrationDialog callback) {
|
||||
super(boatClass, sailingService, stringMessages, errorReporter, editable, leaderboardName,
|
||||
canBoatsOfCompetitorsChangePerRace, validator, callback);
|
||||
validator.setCompetitorRegistrationsPanel(competitorRegistrationsPanel);
|
||||
callback.setCompetitorRegistrationsPanel(competitorRegistrationsPanel);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ValidatorForCompetitorRegistrationDialog implements Validator<Set<CompetitorWithBoatDTO>> {
|
||||
private CompetitorRegistrationsPanel competitorRegistrationsPanel;
|
||||
private StringMessages stringMessages;
|
||||
public ValidatorForCompetitorRegistrationDialog(StringMessages stringMessages) {
|
||||
this.stringMessages = stringMessages;
|
||||
}
|
||||
@Override
|
||||
public String getErrorMessage(Set<CompetitorWithBoatDTO> valueToValidate) {
|
||||
if (competitorRegistrationsPanel == null || competitorRegistrationsPanel.getSelectedRegisteredCompetitors().size() != 1) {
|
||||
return stringMessages.selectOneCompetitorToMapTheImportedData();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public void setCompetitorRegistrationsPanel(CompetitorRegistrationsPanel competitorRegistrationsPanel) {
|
||||
this.competitorRegistrationsPanel = competitorRegistrationsPanel;
|
||||
}
|
||||
}
|
||||
|
||||
private class CallbackForCompetitorRegistrationDialog extends CancelImportDialogCallback<Set<CompetitorWithBoatDTO>> {
|
||||
private CompetitorRegistrationsPanel competitorRegistrationsPanel;
|
||||
|
||||
@Override
|
||||
public void ok(Set<CompetitorWithBoatDTO> competitors) {
|
||||
if (competitors.isEmpty()) {
|
||||
Window.alert(stringMessages.importCanceledNoCompetitorAdded());
|
||||
} else {
|
||||
sailingService.setCompetitorRegistrationsInRegattaLog(leaderboard.getName(),
|
||||
competitors, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
mapCompetitorsToGPSFixDeviceIds(competitorRegistrationsPanel == null ? competitors
|
||||
: competitorRegistrationsPanel.getSelectedRegisteredCompetitors());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Failed to register competitors!");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
public void setCompetitorRegistrationsPanel(CompetitorRegistrationsPanel competitorRegistrationsPanel) {
|
||||
this.competitorRegistrationsPanel = competitorRegistrationsPanel;
|
||||
}
|
||||
}
|
||||
|
||||
private void showCompetitorRegistration() {
|
||||
new RegattaLogCompetitorRegistrationDialog(regatta.boatClass == null ? null : regatta.boatClass.getName(),
|
||||
new RegattaLogCompetitorRegistrationAndSelectionDialog(regatta.boatClass == null ? null : regatta.boatClass.getName(),
|
||||
sailingService, stringMessages, errorReporter, true, leaderboard.getName(),
|
||||
leaderboard.canBoatsOfCompetitorsChangePerRace,
|
||||
new CancelImportDialogCallback<Set<CompetitorWithBoatDTO>>() {
|
||||
@Override
|
||||
public void ok(final Set<CompetitorWithBoatDTO> competitors) {
|
||||
if (competitors.isEmpty()) {
|
||||
Window.alert(stringMessages.importCanceledNoCompetitorAdded());
|
||||
} else {
|
||||
sailingService.setCompetitorRegistrationsInRegattaLog(leaderboard.getName(),
|
||||
competitors, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
mapCompetitorsToGPSFixDeviceIds(competitors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Failed to register competitors!");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}).show();
|
||||
leaderboard.canBoatsOfCompetitorsChangePerRace).show();
|
||||
}
|
||||
|
||||
private void mapCompetitorsToGPSFixDeviceIds(final Set<CompetitorWithBoatDTO> mappedCompetitors) {
|
||||
@@ -172,7 +227,17 @@ public class ExpeditionAllInOneAfterImportHandler {
|
||||
|
||||
private final void continueWithMappedDevices() {
|
||||
List<RegattaNameAndRaceName> racesToStopAndStartTrackingFor = new ArrayList<>();
|
||||
racesToStopAndStartTrackingFor.add(regattaAndRaceIdentifier);
|
||||
final List<Triple<String, String, String>> leaderboardRaceColumnFleetNames = new ArrayList<>();
|
||||
final List<Pair<String, String>> raceNames = new ArrayList<>();
|
||||
for(Triple<String, String, String> race:raceEntries) {
|
||||
String raceName = race.getA();
|
||||
String raceColumnName = race.getB();
|
||||
String fleetName= race.getC();
|
||||
racesToStopAndStartTrackingFor.add(new RegattaNameAndRaceName(regattaName, raceName));
|
||||
leaderboardRaceColumnFleetNames.add(new Triple<>(leaderboard.name, raceColumnName, fleetName));
|
||||
raceNames.add(new Pair<String, String>(raceName, raceColumnName));
|
||||
}
|
||||
|
||||
sailingService.removeAndUntrackRaces(racesToStopAndStartTrackingFor, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
@@ -181,14 +246,12 @@ public class ExpeditionAllInOneAfterImportHandler {
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
final List<Triple<String, String, String>> leaderboardRaceColumnFleetNames = new ArrayList<>();
|
||||
leaderboardRaceColumnFleetNames.add(new Triple<>(leaderboard.name, raceColumnName, fleetName));
|
||||
sailingService.startRaceLogTracking(leaderboardRaceColumnFleetNames, /* trackWind */ true,
|
||||
/* TODO correctWindByDeclination */ true, new AsyncCallback<Void>() {
|
||||
sailingService.startRaceLogTracking(leaderboardRaceColumnFleetNames, /* trackWind */ false,
|
||||
/* correctWindByDeclination */ true, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
new ExpeditionAllInOneImportResultDialog(event.id, regatta.getName(),
|
||||
regattaAndRaceIdentifier.getRaceName(), leaderboard.getName(),
|
||||
raceNames, leaderboard.getName(),
|
||||
leaderboardGroupName).show();
|
||||
}
|
||||
|
||||
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.logical.shared.SelectionEvent;
|
||||
import com.google.gwt.event.logical.shared.SelectionHandler;
|
||||
import com.google.gwt.i18n.client.LocaleInfo;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FileUpload;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.FormPanel;
|
||||
import com.google.gwt.user.client.ui.HasVerticalAlignment;
|
||||
import com.google.gwt.user.client.ui.Hidden;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.RadioButton;
|
||||
import com.google.gwt.user.client.ui.SuggestBox;
|
||||
import com.google.gwt.user.client.ui.SuggestOracle;
|
||||
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.sap.sailing.domain.common.dto.ExpeditionAllInOneConstants;
|
||||
import com.sap.sailing.gwt.common.client.suggestion.BoatClassMasterdataSuggestOracle;
|
||||
import com.sap.sailing.gwt.common.client.suggestion.RegattaSuggestOracle;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.resulthandling.ExpeditionDataImportResponse;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.resulthandling.ExpeditionDataImportResultsDialog;
|
||||
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
|
||||
import com.sap.sailing.gwt.ui.client.RegattasDisplayer;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicator;
|
||||
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
|
||||
|
||||
/**
|
||||
* The UI form to upload data for expedition all in one import.
|
||||
*/
|
||||
public class ExpeditionAllInOneImportPanel extends Composite implements RegattasDisplayer {
|
||||
private static final String URL_SAILINGSERVER_EXPEDITION_FULL_IMPORT = "/../../sailingserver/expedition/import";
|
||||
|
||||
private final RegattaSuggestOracle regattaOracle;
|
||||
|
||||
public ExpeditionAllInOneImportPanel(final StringMessages stringMessages, final SailingServiceAsync sailingService,
|
||||
final ErrorReporter errorReporter, final RegattaRefresher regattaRefresher) {
|
||||
final FormPanel formPanel = new FormPanel();
|
||||
final BusyIndicator busyIndicator = new SimpleBusyIndicator();
|
||||
final Button uploadButton = new Button(stringMessages.upload());
|
||||
formPanel.getElement().setAttribute("autocomplete", "off");
|
||||
uploadButton.addClickHandler(event -> {
|
||||
uploadButton.setEnabled(false);
|
||||
busyIndicator.setBusy(true);
|
||||
formPanel.submit();
|
||||
});
|
||||
formPanel.setMethod(FormPanel.METHOD_POST);
|
||||
formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
|
||||
formPanel.setAction(GWT.getHostPageBaseURL() + URL_SAILINGSERVER_EXPEDITION_FULL_IMPORT);
|
||||
final VerticalPanel contentPanel = new VerticalPanel();
|
||||
formPanel.add(contentPanel);
|
||||
final Hidden localeField = new Hidden(ExpeditionAllInOneConstants.REQUEST_PARAMETER_LOCALE, LocaleInfo.getCurrentLocale().getLocaleName());
|
||||
contentPanel.add(localeField);
|
||||
final FileUpload fileUpload = new FileUpload();
|
||||
fileUpload.setName("upload");
|
||||
contentPanel.add(fileUpload);
|
||||
|
||||
final FlowPanel importModePanel = new FlowPanel();
|
||||
contentPanel.add(importModePanel);
|
||||
final HorizontalPanel regattaNamePanel = new HorizontalPanel();
|
||||
regattaNamePanel.setVisible(false);
|
||||
final HorizontalPanel boatClassPanel = new HorizontalPanel();
|
||||
contentPanel.add(regattaNamePanel);
|
||||
final RadioButton newEventImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE,
|
||||
stringMessages.createNewEvent());
|
||||
newEventImport.setFormValue(ExpeditionAllInOneConstants.ImportMode.NEW_EVENT.name());
|
||||
newEventImport.setValue(true);
|
||||
importModePanel.add(newEventImport);
|
||||
newEventImport.addClickHandler(event -> {
|
||||
regattaNamePanel.setVisible(false);
|
||||
boatClassPanel.setVisible(true);
|
||||
});
|
||||
final RadioButton newCompetitorImport = new RadioButton(
|
||||
ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.newExpeditionCompetitor());
|
||||
newCompetitorImport.setFormValue(ExpeditionAllInOneConstants.ImportMode.NEW_COMPETITOR.name());
|
||||
importModePanel.add(newCompetitorImport);
|
||||
newCompetitorImport.addClickHandler(event -> {
|
||||
regattaNamePanel.setVisible(true);
|
||||
boatClassPanel.setVisible(false);
|
||||
});
|
||||
final RadioButton newRaceImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE,
|
||||
stringMessages.newExpeditionRace());
|
||||
newRaceImport.setFormValue(ExpeditionAllInOneConstants.ImportMode.NEW_RACE.name());
|
||||
importModePanel.add(newRaceImport);
|
||||
newRaceImport.addClickHandler(event -> {
|
||||
regattaNamePanel.setVisible(true);
|
||||
boatClassPanel.setVisible(false);
|
||||
});
|
||||
|
||||
regattaNamePanel.setSpacing(5);
|
||||
final Label regattaNameLabel = new Label(stringMessages.regattaName() + ":");
|
||||
regattaNamePanel.add(regattaNameLabel);
|
||||
regattaNamePanel.setCellVerticalAlignment(regattaNameLabel, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
final TextBox regattaName = new TextBox();
|
||||
regattaName.setName(ExpeditionAllInOneConstants.REQUEST_PARAMETER_REGATTA_NAME);
|
||||
|
||||
regattaOracle = new RegattaSuggestOracle();
|
||||
final SuggestBox regattaSuggestBox = new SuggestBox(regattaOracle, regattaName);
|
||||
regattaSuggestBox.getValueBox().getElement().getStyle().setProperty("minWidth", 30, Unit.EM);
|
||||
regattaSuggestBox.getValueBox().getElement().setAttribute("placeholder", stringMessages.startTypingForSuggestions());
|
||||
regattaNamePanel.add(regattaSuggestBox);
|
||||
regattaNamePanel.setCellVerticalAlignment(regattaSuggestBox, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
boatClassPanel.setSpacing(5);
|
||||
contentPanel.add(boatClassPanel);
|
||||
final Label boatClassLabel = new Label(stringMessages.boatClass() + ":");
|
||||
boatClassPanel.add(boatClassLabel);
|
||||
boatClassPanel.setCellVerticalAlignment(boatClassLabel, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
final SuggestBox boatClassInput = new SuggestBox(new BoatClassMasterdataSuggestOracle());
|
||||
boatClassInput.getValueBox().getElement().getStyle().setProperty("minWidth", 30, Unit.EM);
|
||||
boatClassInput.getValueBox().getElement().setAttribute("placeholder", stringMessages.startTypingForSuggestions());
|
||||
boatClassInput.getValueBox().setName(ExpeditionAllInOneConstants.REQUEST_PARAMETER_BOAT_CLASS);
|
||||
boatClassPanel.add(boatClassInput);
|
||||
boatClassPanel.setCellVerticalAlignment(boatClassInput, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
final HorizontalPanel controlPanel = new HorizontalPanel();
|
||||
controlPanel.setSpacing(5);
|
||||
controlPanel.add(uploadButton);
|
||||
controlPanel.add(busyIndicator);
|
||||
contentPanel.add(controlPanel);
|
||||
final Runnable validation = () -> {
|
||||
final String filename = fileUpload.getFilename(), boatClass = boatClassInput.getValue();
|
||||
final String regattaNameValue = regattaSuggestBox.getValue();
|
||||
final boolean fileValid = filename != null && !filename.trim().isEmpty();
|
||||
final boolean isNewEventImport = Boolean.TRUE.equals(newEventImport.getValue());
|
||||
final boolean boatClassValid = boatClass != null && !boatClass.trim().isEmpty();
|
||||
final boolean regattaNameValid = regattaNameValue != null && !regattaNameValue.trim().isEmpty();
|
||||
uploadButton.setEnabled(fileValid && (isNewEventImport ? boatClassValid : regattaNameValid));
|
||||
};
|
||||
fileUpload.addChangeHandler(new ChangeHandler() {
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
validation.run();
|
||||
}
|
||||
});
|
||||
formPanel.addSubmitCompleteHandler(event -> {
|
||||
validation.run();
|
||||
busyIndicator.setBusy(false);
|
||||
final ExpeditionDataImportResponse response = ExpeditionDataImportResponse.parse(event.getResults());
|
||||
if (response == null) {
|
||||
Window.alert(StringMessages.INSTANCE.unexpectedErrorDuringFileImport());
|
||||
} else if (response.hasEventId()) {
|
||||
|
||||
new ExpeditionAllInOneAfterImportHandler(response.getEventId(), response.getRegattaName(),
|
||||
response.getLeaderboardName(), response.getLeaderboardGroupName(), response.getRaceEntries(), response.getGpsDeviceIds(),
|
||||
response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService,
|
||||
errorReporter, stringMessages);
|
||||
regattaRefresher.fillRegattas();
|
||||
} else {
|
||||
ExpeditionDataImportResultsDialog.showResults(response);
|
||||
}
|
||||
});
|
||||
regattaSuggestBox.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {
|
||||
@Override
|
||||
public void onSelection(SelectionEvent<Suggestion> event) {
|
||||
final String selected = event.getSelectedItem().getReplacementString();
|
||||
if (selected != null) {
|
||||
sailingService.getRegattaByName(selected, new AsyncCallback<RegattaDTO>() {
|
||||
@Override
|
||||
public void onSuccess(RegattaDTO result) {
|
||||
validation.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Could not determine Regatta " + selected);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
regattaSuggestBox.addKeyUpHandler(event -> validation.run());
|
||||
fileUpload.addChangeHandler(event -> validation.run());
|
||||
boatClassInput.addSelectionHandler(event -> validation.run());
|
||||
boatClassInput.addKeyUpHandler(event -> validation.run());
|
||||
validation.run();
|
||||
initWidget(formPanel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRegattas(Iterable<RegattaDTO> regattas) {
|
||||
regattaOracle.fillRegattas(regattas);
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -1,15 +1,17 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.shared.race.TrackedRaceCreationResultDialog;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
|
||||
public class ExpeditionAllInOneImportResultDialog extends TrackedRaceCreationResultDialog {
|
||||
|
||||
public ExpeditionAllInOneImportResultDialog(UUID eventId, String regattaName, String raceName,
|
||||
public ExpeditionAllInOneImportResultDialog(UUID eventId, String regattaName, List<Pair<String, String>> raceEntries,
|
||||
String leaderboardName, String leaderboardGroupName) {
|
||||
super(StringMessages.INSTANCE.importFinished(), StringMessages.INSTANCE.importFinishedMessage(), eventId,
|
||||
regattaName, raceName, leaderboardName, leaderboardGroupName);
|
||||
regattaName, raceEntries, leaderboardName, leaderboardGroupName);
|
||||
}
|
||||
}
|
||||
Regular → Executable
+10
-1
@@ -16,7 +16,16 @@ public class RegattaLogCompetitorRegistrationDialog extends AbstractCompetitorRe
|
||||
public RegattaLogCompetitorRegistrationDialog(String boatClass, SailingServiceAsync sailingService,
|
||||
StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace,
|
||||
com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback<Set<CompetitorWithBoatDTO>> callback) {
|
||||
super(sailingService, stringMessages, errorReporter, editable, callback, leaderboardName, canBoatsOfCompetitorsChangePerRace, boatClass, stringMessages.save(), /* validator */ null);
|
||||
this(boatClass, sailingService, stringMessages, errorReporter, editable, leaderboardName,
|
||||
canBoatsOfCompetitorsChangePerRace, /* validator */ null, callback);
|
||||
}
|
||||
|
||||
public RegattaLogCompetitorRegistrationDialog(String boatClass, SailingServiceAsync sailingService,
|
||||
StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName,
|
||||
boolean canBoatsOfCompetitorsChangePerRace, Validator<Set<CompetitorWithBoatDTO>> validator,
|
||||
com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback<Set<CompetitorWithBoatDTO>> callback) {
|
||||
super(sailingService, stringMessages, errorReporter, editable, callback, leaderboardName,
|
||||
canBoatsOfCompetitorsChangePerRace, boatClass, stringMessages.save(), validator);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+22
-88
@@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -44,7 +45,6 @@ import com.google.gwt.user.client.ui.Hidden;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Panel;
|
||||
import com.google.gwt.user.client.ui.SuggestBox;
|
||||
import com.google.gwt.user.client.ui.TabPanel;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
@@ -55,10 +55,7 @@ import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.dto.RaceDTO;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceImpl;
|
||||
import com.sap.sailing.gwt.common.client.suggestion.BoatClassMasterdataSuggestOracle;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.WindImportResult.RaceEntry;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.resulthandling.ExpeditionDataImportResponse;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.resulthandling.ExpeditionDataImportResultsDialog;
|
||||
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
|
||||
import com.sap.sailing.gwt.ui.client.RegattasDisplayer;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
@@ -70,12 +67,11 @@ import com.sap.sailing.gwt.ui.shared.WindDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
|
||||
import com.sap.sse.gwt.client.celltable.BaseCelltable;
|
||||
import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel;
|
||||
import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicator;
|
||||
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
|
||||
/**
|
||||
@@ -87,13 +83,10 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
*
|
||||
*/
|
||||
public class WindPanel extends FormPanel implements RegattasDisplayer, WindShower {
|
||||
|
||||
private static final String WIND_IMPORT_PARAMETER_RACES = "races";
|
||||
|
||||
private static final String EXPEDITON_IMPORT_PARAMETER_BOAT_ID = "boatId";
|
||||
private static final String EXPEDITON_IMPORT_PARAMETER_BOAT_CLASS = "boatClass";
|
||||
|
||||
private static final String URL_SAILINGSERVER_EXPEDITION_FULL_IMPORT = "/../../sailingserver/expedition/import";
|
||||
|
||||
private static final String URL_SAILINGSERVER_EXPEDITION_IMPORT = "/../../sailingserver/expedition-import";
|
||||
private static final String URL_SAILINGSERVER_GRIB_IMPORT = "/../../sailingserver/grib-wind-import";
|
||||
private static final String URL_SAILINGSERVER_NMEA_IMPORT = "/../../sailingserver/nmea-wind-import";
|
||||
@@ -117,23 +110,28 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe
|
||||
private final ListDataProvider<WindDTO> rawWindFixesDataProvider;
|
||||
private final CellTable<WindDTO> rawWindFixesTable;
|
||||
private final VerticalPanel windFixPanel;
|
||||
|
||||
|
||||
/**
|
||||
* Composite pattern over the {@link RegattasDisplayer} interface. Calls to {@link #fillRegattas(Iterable)}
|
||||
* will be forwarded to those objects contained in this collection.
|
||||
*/
|
||||
private final Set<RegattasDisplayer> containedRegattaDisplayers;
|
||||
|
||||
public WindPanel(final SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor,
|
||||
ErrorReporter errorReporter, RegattaRefresher regattaRefresher, final StringMessages stringMessages) {
|
||||
ensureDebugId("WindPanel");
|
||||
|
||||
this.sailingService = sailingService;
|
||||
this.containedRegattaDisplayers = new HashSet<>();
|
||||
this.errorReporter = errorReporter;
|
||||
this.stringMessages = stringMessages;
|
||||
windSourcesToExcludeSelectorPanel = new WindSourcesToExcludeSelectorPanel(sailingService, stringMessages, errorReporter);
|
||||
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
mainPanel.setSize("100%", "100%");
|
||||
this.setWidget(mainPanel);
|
||||
|
||||
trackedRacesListComposite = new TrackedRacesListComposite(null, null, sailingService, errorReporter,
|
||||
regattaRefresher,
|
||||
stringMessages, /*multiselection*/true, /* actionButtonsEnabled */ false);
|
||||
containedRegattaDisplayers.add(trackedRacesListComposite);
|
||||
trackedRacesListComposite.ensureDebugId("TrackedRacesListComposite");
|
||||
mainPanel.add(trackedRacesListComposite);
|
||||
refreshableRaceSelectionModel = (RefreshableMultiSelectionModel<RaceDTO>) trackedRacesListComposite.getSelectionModel();
|
||||
@@ -143,16 +141,13 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe
|
||||
updateWindDisplay();
|
||||
}
|
||||
});
|
||||
|
||||
windCaptionPanel = new CaptionPanel(stringMessages.wind());
|
||||
windCaptionPanel.setVisible(false);
|
||||
mainPanel.add(windCaptionPanel);
|
||||
|
||||
TabPanel tabPanel = new TabPanel();
|
||||
tabPanel.setAnimationEnabled(true);
|
||||
windCaptionPanel.add(tabPanel);
|
||||
tabPanel.setSize("95%", "95%");
|
||||
|
||||
windFixesDisplayPanel = new VerticalPanel();
|
||||
Button addWindFixButton = new Button(stringMessages.actionAddWindData() + "...");
|
||||
addWindFixButton.addClickHandler(new ClickHandler() {
|
||||
@@ -176,16 +171,13 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe
|
||||
}
|
||||
});
|
||||
windFixesDisplayPanel.add(addWindFixButton);
|
||||
|
||||
final VerticalPanel windSourcesPanel = new VerticalPanel();
|
||||
windSourcesPanel.setSpacing(10);
|
||||
tabPanel.add(windSourcesPanel, stringMessages.windSourcesUsed());
|
||||
tabPanel.add(windFixesDisplayPanel, stringMessages.windFixes());
|
||||
tabPanel.selectTab(0);
|
||||
|
||||
raceIsKnownToStartUpwindBox = new CheckBox(stringMessages.raceIsKnownToStartUpwind());
|
||||
windSourcesPanel.add(raceIsKnownToStartUpwindBox);
|
||||
|
||||
windSourcesPanel.add(windSourcesToExcludeSelectorPanel);
|
||||
raceIsKnownToStartUpwindBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
|
||||
@Override
|
||||
@@ -193,13 +185,10 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe
|
||||
setRaceIsKnownToStartUpwind();
|
||||
}
|
||||
});
|
||||
|
||||
windFixPanel = new VerticalPanel();
|
||||
windSourcesPanel.add(windFixPanel);
|
||||
|
||||
windSourceLabel = new Label();
|
||||
windFixesDisplayPanel.add(windSourceLabel);
|
||||
|
||||
// table for the raw wind fixes
|
||||
removeColumn = new IdentityColumn<WindDTO>(new ActionCell<WindDTO>(stringMessages.remove(), new Delegate<WindDTO>() {
|
||||
@Override
|
||||
@@ -252,7 +241,6 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe
|
||||
timeColumn.setSortable(true);
|
||||
speedInKnotsColumn.setSortable(true);
|
||||
windDirectionInDegColumn.setSortable(true);
|
||||
|
||||
AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class);
|
||||
rawWindFixesTable = new BaseCelltable<WindDTO>(/* pageSize */10000, tableRes);
|
||||
rawWindFixesTable.addColumn(timeColumn, stringMessages.time());
|
||||
@@ -266,13 +254,14 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe
|
||||
rawWindFixesTable.addColumnSortHandler(columnSortHandler);
|
||||
rawWindFixesTable.getColumnSortList().push(timeColumn);
|
||||
windFixesDisplayPanel.add(rawWindFixesTable);
|
||||
|
||||
mainPanel.add(createExpeditionWindImportPanel());
|
||||
mainPanel.add(createGribWindImportPanel());
|
||||
mainPanel.add(createNmeaWindImportPanel());
|
||||
mainPanel.add(createBravoWindImportPanel());
|
||||
mainPanel.add(createIgtimiWindImportPanel(mainPanel));
|
||||
mainPanel.add(createExpeditionAllInOneImportPanel());
|
||||
final Pair<CaptionPanel, ExpeditionAllInOneImportPanel> expeditionAllInOneRootAndImportPanel = createExpeditionAllInOneImportPanel(regattaRefresher);
|
||||
mainPanel.add(expeditionAllInOneRootAndImportPanel.getA());
|
||||
containedRegattaDisplayers.add(expeditionAllInOneRootAndImportPanel.getB());
|
||||
}
|
||||
|
||||
private CaptionPanel createIgtimiWindImportPanel(VerticalPanel mainPanel) {
|
||||
@@ -448,68 +437,11 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe
|
||||
return new WindImportFileUploadForm(form, formContentPanel, fileUpload, submitButton);
|
||||
}
|
||||
|
||||
private CaptionPanel createExpeditionAllInOneImportPanel() {
|
||||
private Pair<CaptionPanel, ExpeditionAllInOneImportPanel> createExpeditionAllInOneImportPanel(RegattaRefresher regattaRefresher) {
|
||||
final CaptionPanel rootPanel = new CaptionPanel(stringMessages.importFullExpeditionData());
|
||||
final FormPanel formPanel = new FormPanel();
|
||||
final BusyIndicator busyIndicator = new SimpleBusyIndicator();
|
||||
final Button uploadButton = new Button(stringMessages.upload());
|
||||
uploadButton.addClickHandler(event -> {
|
||||
uploadButton.setEnabled(false);
|
||||
busyIndicator.setBusy(true);
|
||||
formPanel.submit();
|
||||
});
|
||||
formPanel.setMethod(FormPanel.METHOD_POST);
|
||||
formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
|
||||
formPanel.setAction(GWT.getHostPageBaseURL() + URL_SAILINGSERVER_EXPEDITION_FULL_IMPORT);
|
||||
formPanel.addSubmitCompleteHandler(event -> {
|
||||
uploadButton.setEnabled(true);
|
||||
busyIndicator.setBusy(false);
|
||||
final ExpeditionDataImportResponse response = ExpeditionDataImportResponse.parse(event.getResults());
|
||||
if (response == null) {
|
||||
Window.alert(StringMessages.INSTANCE.unexpectedErrorDuringFileImport());
|
||||
} else if (response.hasEventId()) {
|
||||
new ExpeditionAllInOneAfterImportHandler(response.getEventId(), response.getRegattaName(),
|
||||
response.getLeaderboardGroupName(), response.getLeaderboardName(), response.getRaceName(),
|
||||
response.getRaceColumnName(), response.getFleetName(), response.getGpsDeviceIds(),
|
||||
response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService,
|
||||
errorReporter, stringMessages);
|
||||
} else {
|
||||
ExpeditionDataImportResultsDialog.showResults(response);
|
||||
}
|
||||
});
|
||||
rootPanel.add(formPanel);
|
||||
final VerticalPanel contentPanel = new VerticalPanel();
|
||||
formPanel.add(contentPanel);
|
||||
final FileUpload fileUpload = new FileUpload();
|
||||
fileUpload.setName("upload");
|
||||
contentPanel.add(fileUpload);
|
||||
final HorizontalPanel boatClassPanel = new HorizontalPanel();
|
||||
boatClassPanel.setSpacing(5);
|
||||
contentPanel.add(boatClassPanel);
|
||||
final Label boatClassLabel = new Label(stringMessages.boatClass() + ":");
|
||||
boatClassPanel.add(boatClassLabel);
|
||||
boatClassPanel.setCellVerticalAlignment(boatClassLabel, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
final SuggestBox boatClassInput = new SuggestBox(new BoatClassMasterdataSuggestOracle());
|
||||
boatClassInput.getValueBox().setName(EXPEDITON_IMPORT_PARAMETER_BOAT_CLASS);
|
||||
boatClassPanel.add(boatClassInput);
|
||||
boatClassPanel.setCellVerticalAlignment(boatClassInput, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
final HorizontalPanel controlPanel = new HorizontalPanel();
|
||||
controlPanel.setSpacing(5);
|
||||
controlPanel.add(uploadButton);
|
||||
controlPanel.add(busyIndicator);
|
||||
contentPanel.add(controlPanel);
|
||||
final Runnable validation = () -> {
|
||||
final String filename = fileUpload.getFilename(), boatClass = boatClassInput.getValue();
|
||||
final boolean fileValid = filename != null && !filename.trim().isEmpty();
|
||||
final boolean boatClassValid = boatClass != null && !boatClass.trim().isEmpty();
|
||||
uploadButton.setEnabled(fileValid && boatClassValid);
|
||||
};
|
||||
|
||||
fileUpload.addChangeHandler(event -> validation.run());
|
||||
boatClassInput.addSelectionHandler(event -> validation.run());
|
||||
boatClassInput.addKeyUpHandler(event -> validation.run());
|
||||
validation.run();
|
||||
return rootPanel;
|
||||
final ExpeditionAllInOneImportPanel expeditionAllInOneImportPanel = new ExpeditionAllInOneImportPanel(stringMessages, sailingService, errorReporter, regattaRefresher);
|
||||
rootPanel.add(expeditionAllInOneImportPanel);
|
||||
return new Pair<>(rootPanel, expeditionAllInOneImportPanel);
|
||||
}
|
||||
|
||||
private CaptionPanel createExpeditionWindImportPanel() {
|
||||
@@ -627,7 +559,9 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe
|
||||
|
||||
@Override
|
||||
public void fillRegattas(Iterable<RegattaDTO> result) {
|
||||
trackedRacesListComposite.fillRegattas(result);
|
||||
for (final RegattasDisplayer containedRegattaDisplayer : containedRegattaDisplayers) {
|
||||
containedRegattaDisplayer.fillRegattas(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+20
-12
@@ -1,8 +1,13 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole.resulthandling;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gwt.json.client.JSONArray;
|
||||
import com.google.gwt.json.client.JSONObject;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
|
||||
public class ExpeditionDataImportResponse extends AbstractDataImportResponse {
|
||||
|
||||
public static final ExpeditionDataImportResponse parse(String json) {
|
||||
@@ -24,22 +29,25 @@ public class ExpeditionDataImportResponse extends AbstractDataImportResponse {
|
||||
public final native String getLeaderboardName() /*-{
|
||||
return this.leaderboardName;
|
||||
}-*/;
|
||||
|
||||
|
||||
public final native String getRegattaName() /*-{
|
||||
return this.regattaName;
|
||||
}-*/;
|
||||
|
||||
public final native String getRaceName() /*-{
|
||||
return this.raceName;
|
||||
}-*/;
|
||||
|
||||
public final native String getRaceColumnName() /*-{
|
||||
return this.raceColumnName;
|
||||
}-*/;
|
||||
|
||||
public final native String getFleetName() /*-{
|
||||
return this.fleetName;
|
||||
}-*/;
|
||||
public final List<Triple<String, String, String>> getRaceEntries() {
|
||||
ArrayList<Triple<String, String, String>> raceNameRaceColumnNameFleetNameList = new ArrayList<>();
|
||||
JSONObject jsonView = new JSONObject(this);
|
||||
JSONArray entryList = jsonView.get("raceNameRaceColumnNameFleetNameList").isArray();
|
||||
for (int i = 0; i < entryList.size(); i++) {
|
||||
JSONObject entry = entryList.get(i).isObject();
|
||||
String raceName = entry.get("raceName").isString().stringValue();
|
||||
String raceColumnName = entry.get("raceColumnName").isString().stringValue();
|
||||
String fleetName = entry.get("fleetName").isString().stringValue();
|
||||
raceNameRaceColumnNameFleetNameList
|
||||
.add(new Triple<String, String, String>(raceName, raceColumnName, fleetName));
|
||||
}
|
||||
return raceNameRaceColumnNameFleetNameList;
|
||||
}
|
||||
|
||||
public final List<String> getGpsDeviceIds() {
|
||||
return getStringList("gpsDeviceIds");
|
||||
|
||||
+4
-2
@@ -28,13 +28,14 @@ import com.sap.sailing.domain.common.RankingMetrics;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.domain.common.ServiceException;
|
||||
import com.sap.sailing.domain.common.UnableToCloseDeviceMappingException;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
|
||||
import com.sap.sailing.domain.common.abstractlog.TimePointSpecificationFoundInLog;
|
||||
import com.sap.sailing.domain.common.dto.BoatDTO;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO;
|
||||
import com.sap.sailing.domain.common.dto.FleetDTO;
|
||||
import com.sap.sailing.domain.common.dto.IncrementalOrFullLeaderboardDTO;
|
||||
import com.sap.sailing.domain.common.dto.PairingListDTO;
|
||||
@@ -764,8 +765,9 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
/**
|
||||
* Slices a new race from the race specified by the given {@link RegattaAndRaceIdentifier} using the given time range.
|
||||
* A new {@link RaceColumn} with the given name is added to the {@link RegattaLeaderboard}.
|
||||
* @throws ServiceException
|
||||
*/
|
||||
RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo);
|
||||
RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException;
|
||||
|
||||
/**
|
||||
* Returns specific data needed for the slicing UI.
|
||||
|
||||
Executable → Regular
+5
@@ -2071,6 +2071,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String importFinished();
|
||||
String importFinishedMessage();
|
||||
String importFinishedGotoRaceboard();
|
||||
String importFinishedGotoRaceboardWithName(String name);
|
||||
String importFinishedGotoEvent();
|
||||
String chooseAName();
|
||||
String errorFillingRaceLogsFromPairingList(String message);
|
||||
@@ -2148,4 +2149,8 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String expeditionRaceJibCarStbd();
|
||||
String expeditionRaceMastButt();
|
||||
String milliBarUnits();
|
||||
String newExpeditionRace();
|
||||
String newExpeditionCompetitor();
|
||||
String selectOneCompetitorToMapTheImportedData();
|
||||
String startTypingForSuggestions();
|
||||
}
|
||||
+5
@@ -2066,6 +2066,7 @@ importCanceledByUser=Import canceled!
|
||||
importFinished=Finished importing data
|
||||
importFinishedMessage=Successfully imported expedition data.
|
||||
importFinishedGotoRaceboard=Open raceboard
|
||||
importFinishedGotoRaceboardWithName=Open raceboard for "{0}"
|
||||
importFinishedGotoEvent=Open event
|
||||
chooseAName=Choose a name
|
||||
errorFillingRaceLogsFromPairingList=Error filling race logs from pairing list: {0}
|
||||
@@ -2138,3 +2139,7 @@ expeditionRaceJibCarPort=eaJibCarPFromBow
|
||||
expeditionRaceJibCarStbd=eaJibCarSFromBow
|
||||
expeditionRaceMastButt=exMastButt
|
||||
milliBarUnits=mbar
|
||||
newExpeditionRace=Create a new race
|
||||
newExpeditionCompetitor=Add a new Competitor
|
||||
selectOneCompetitorToMapTheImportedData=Please select one competitor on the left side. The imported data will be mapped to this competitor.
|
||||
startTypingForSuggestions=Start typing to get suggestions
|
||||
+5
@@ -2063,6 +2063,7 @@ importCanceledByUser=Import abgebrochen!
|
||||
importFinished=Importvorgang abgeschlossen
|
||||
importFinishedMessage=Erfolgreich Expeditionsdaten eingelesen
|
||||
importFinishedGotoRaceboard=Raceboard öffnen
|
||||
importFinishedGotoRaceboardWithName=Raceboard für "{0}" öffnen
|
||||
importFinishedGotoEvent=Event öffnen
|
||||
chooseAName=Namen auswählen
|
||||
errorFillingRaceLogsFromPairingList=Fehler beim Befüllen der Rennprotokolle aus der Gegner-Paarungsliste: {0}
|
||||
@@ -2134,3 +2135,7 @@ expeditionRaceLoadP=eFShroudP
|
||||
expeditionRaceJibCarPort=eaJibCarPFromBow
|
||||
expeditionRaceJibCarStbd=eaJibCarSFromBow
|
||||
expeditionRaceMastButt=exMastButt
|
||||
newExpeditionRace=Neues Rennen anlegen
|
||||
newExpeditionCompetitor=Neuen Teilnehmer hinzufügen
|
||||
selectOneCompetitorToMapTheImportedData=Bitte einen Teilnehmer auf der linken Seite auswählen. Die importierten Daten werden dem ausgewählten Teinehmer zugeordnet.
|
||||
startTypingForSuggestions=Tippen starten, um Vorschlagsliste zuerhalten
|
||||
+32
-14
@@ -1,6 +1,8 @@
|
||||
package com.sap.sailing.gwt.ui.client.shared.race;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gwt.user.client.ui.Anchor;
|
||||
@@ -9,21 +11,32 @@ import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.settings.client.EntryPointWithSettingsLinkFactory;
|
||||
import com.sap.sailing.gwt.ui.client.EntryPointLinkFactory;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
|
||||
|
||||
/**
|
||||
* Summary dialog to be shown after actions that generate a new TrackedRace.
|
||||
* the dialog shows a link to the RaceBoard for the generated TrackedRace.
|
||||
* In addition, if available a link to the associated event is shown.
|
||||
* Summary dialog to be shown after actions that generate a new TrackedRace. the dialog shows a link to the RaceBoard
|
||||
* for the generated TrackedRace. In addition, if available a link to the associated event is shown.
|
||||
*/
|
||||
public class TrackedRaceCreationResultDialog extends DataEntryDialog<Void> {
|
||||
|
||||
private final VerticalPanel verticalPanel;
|
||||
|
||||
public TrackedRaceCreationResultDialog(String title, String message, UUID eventId, String regattaName, String raceName,
|
||||
String leaderboardName, String leaderboardGroupName) {
|
||||
super(title, message,
|
||||
StringMessages.INSTANCE.ok(), StringMessages.INSTANCE.cancel(), /* validator */ null,
|
||||
public TrackedRaceCreationResultDialog(String title, String message, UUID eventId, String regattaName,
|
||||
String raceName, String leaderboardName, String leaderboardGroupName) {
|
||||
this(title, message, eventId, regattaName, createSingleRaceList(raceName), leaderboardName,
|
||||
leaderboardGroupName);
|
||||
}
|
||||
|
||||
private static List<Pair<String, String>> createSingleRaceList(String raceName) {
|
||||
ArrayList<Pair<String, String>> rv = new ArrayList<>();
|
||||
rv.add(new Pair<String, String>(raceName, null));
|
||||
return rv;
|
||||
}
|
||||
|
||||
public TrackedRaceCreationResultDialog(String title, String message, UUID eventId, String regattaName,
|
||||
List<Pair<String, String>> raceNameRaceColumnName, String leaderboardName, String leaderboardGroupName) {
|
||||
super(title, message, StringMessages.INSTANCE.ok(), StringMessages.INSTANCE.cancel(), /* validator */ null,
|
||||
new DialogCallback<Void>() {
|
||||
@Override
|
||||
public void ok(Void editedObject) {
|
||||
@@ -36,19 +49,24 @@ public class TrackedRaceCreationResultDialog extends DataEntryDialog<Void> {
|
||||
|
||||
verticalPanel = new VerticalPanel();
|
||||
verticalPanel.setSpacing(20);
|
||||
Anchor raceboardAnchor = new Anchor(StringMessages.INSTANCE.importFinishedGotoRaceboard(),
|
||||
EntryPointWithSettingsLinkFactory.createRaceBoardLinkWithDefaultSettings(eventId, leaderboardName,
|
||||
leaderboardGroupName, regattaName, raceName));
|
||||
raceboardAnchor.setTarget("_blank");
|
||||
verticalPanel.add(raceboardAnchor);
|
||||
|
||||
boolean multiRace = raceNameRaceColumnName.size() > 1;
|
||||
for (Pair<String, String> raceName : raceNameRaceColumnName) {
|
||||
String anchorLabel = multiRace ? StringMessages.INSTANCE.importFinishedGotoRaceboardWithName(raceName.getB())
|
||||
: StringMessages.INSTANCE.importFinishedGotoRaceboard();
|
||||
Anchor raceboardAnchor = new Anchor(anchorLabel,
|
||||
EntryPointWithSettingsLinkFactory.createRaceBoardLinkWithDefaultSettings(eventId, leaderboardName,
|
||||
leaderboardGroupName, regattaName, raceName.getA()));
|
||||
raceboardAnchor.setTarget("_blank");
|
||||
verticalPanel.add(raceboardAnchor);
|
||||
}
|
||||
|
||||
if (eventId != null) {
|
||||
Anchor eventAnchor = new Anchor(StringMessages.INSTANCE.importFinishedGotoEvent(),
|
||||
EntryPointLinkFactory.createEventPlaceLink(eventId.toString(), Collections.emptyMap()));
|
||||
eventAnchor.setTarget("_blank");
|
||||
verticalPanel.add(eventAnchor);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-2
@@ -147,8 +147,9 @@ public class SliceRaceHandler {
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter
|
||||
.reportError(StringMessages.INSTANCE.errorWhileSlicingARace());
|
||||
errorReporter.reportError(
|
||||
StringMessages.INSTANCE.errorWhileSlicingARace(),
|
||||
caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+17
-6
@@ -17,6 +17,7 @@ import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -224,6 +225,7 @@ import com.sap.sailing.domain.common.RegattaScoreCorrections.ScoreCorrectionForC
|
||||
import com.sap.sailing.domain.common.RegattaScoreCorrections.ScoreCorrectionsForRace;
|
||||
import com.sap.sailing.domain.common.ScoreCorrectionProvider;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.domain.common.ServiceException;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
@@ -546,6 +548,7 @@ import com.sap.sse.gwt.shared.replication.ReplicaDTO;
|
||||
import com.sap.sse.gwt.shared.replication.ReplicationMasterDTO;
|
||||
import com.sap.sse.gwt.shared.replication.ReplicationStateDTO;
|
||||
import com.sap.sse.i18n.ResourceBundleStringMessages;
|
||||
import com.sap.sse.i18n.impl.ResourceBundleStringMessagesImpl;
|
||||
import com.sap.sse.pairinglist.PairingList;
|
||||
import com.sap.sse.pairinglist.PairingListTemplate;
|
||||
import com.sap.sse.pairinglist.impl.PairingListTemplateImpl;
|
||||
@@ -574,6 +577,8 @@ import com.sapsailing.xrr.structureimport.eventimport.RegattaJSON;
|
||||
public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements SailingService, RaceFetcher, RegattaFetcher {
|
||||
private static final Logger logger = Logger.getLogger(SailingServiceImpl.class.getName());
|
||||
|
||||
private static final String STRING_MESSAGES_BASE_NAME = "stringmessages/StringMessages";
|
||||
|
||||
private static final long serialVersionUID = 9031688830194537489L;
|
||||
|
||||
private final ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
|
||||
@@ -623,6 +628,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
|
||||
private static final int LEADERBOARD_DIFFERENCE_CACHE_SIZE = 50;
|
||||
|
||||
private ResourceBundleStringMessages serverStringMessages;
|
||||
|
||||
private final LinkedHashMap<String, LeaderboardDTO> leaderboardByNameResultsCacheById;
|
||||
|
||||
@@ -693,6 +699,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
// providing the updates is not outperformed by all the re-calculations happening here. Leave at least one
|
||||
// core to other things, but by using at least three threads ensure that no simplistic deadlocks may occur.
|
||||
executor = ThreadPoolUtil.INSTANCE.getDefaultForegroundTaskThreadPoolExecutor();
|
||||
|
||||
serverStringMessages = new ResourceBundleStringMessagesImpl(STRING_MESSAGES_BASE_NAME,
|
||||
this.getClass().getClassLoader(), StandardCharsets.UTF_8.name());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7496,23 +7505,25 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
|
||||
@Override
|
||||
public RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName,
|
||||
TimePoint sliceFrom, TimePoint sliceTo) {
|
||||
TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException {
|
||||
final Locale locale = getClientLocale();
|
||||
|
||||
SecurityUtils.getSubject().checkPermission(Permission.MANAGE_TRACKED_RACES.getStringPermissionForObjects(Mode.UPDATE));
|
||||
if (!canSliceRace(raceIdentifier)) {
|
||||
throw new RuntimeException("Can not slice race");
|
||||
throw new ServiceException(serverStringMessages.get(locale, "slicingCannotSliceRace"));
|
||||
}
|
||||
final String trackedRaceName = newRaceColumnName;
|
||||
final RegattaIdentifier regattaIdentifier = new RegattaName(raceIdentifier.getRegattaName());
|
||||
final Regatta regatta = getService().getRegatta(regattaIdentifier);
|
||||
if (regatta.getRaceColumnByName(newRaceColumnName) != null) {
|
||||
throw new RuntimeException("The race column name is already used in the given regatta");
|
||||
throw new ServiceException(serverStringMessages.get(locale, "slicingRaceColumnAlreadyUsedThe"));
|
||||
}
|
||||
final DynamicTrackedRace trackedRaceToSlice = getService().getTrackedRace(raceIdentifier);
|
||||
final TimePoint startOfTrackingOfRaceToSlice = trackedRaceToSlice.getStartOfTracking();
|
||||
final TimePoint endOfTrackingOfRaceToSlice = trackedRaceToSlice.getEndOfTracking();
|
||||
if (sliceFrom == null || sliceTo == null || startOfTrackingOfRaceToSlice.after(sliceFrom)
|
||||
|| (endOfTrackingOfRaceToSlice != null && endOfTrackingOfRaceToSlice.before(sliceTo))) {
|
||||
throw new RuntimeException("The TimeRange to slice is not part of the race");
|
||||
throw new ServiceException(serverStringMessages.get(locale, "slicingTimeRangeOutOfBounds"));
|
||||
}
|
||||
final RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) getService().getLeaderboardByName(raceIdentifier.getRegattaName());
|
||||
final Pair<RaceColumn, Fleet> raceColumnAndFleetOfRaceToSlice = regattaLeaderboard.getRaceColumnAndFleet(trackedRaceToSlice);
|
||||
@@ -7743,7 +7754,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
|
||||
final DynamicTrackedRace trackedRace = WaitForTrackedRaceUtil.waitForTrackedRace(raceColumn, fleet, 10);
|
||||
if (trackedRace == null) {
|
||||
throw new IllegalStateException("Could not obtain sliced race");
|
||||
throw new ServiceException(serverStringMessages.get(locale, "slicingCouldNotObtainRace"));
|
||||
}
|
||||
for (WindSource windSourceToCopy : trackedRaceToSlice.getWindSources()) {
|
||||
if (windSourceToCopy.canBeStored()) {
|
||||
@@ -7774,7 +7785,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
}
|
||||
return trackedRace.getRaceIdentifier();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error while slicing race", e);
|
||||
throw new ServiceException(serverStringMessages.get(locale, "slicingError"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
slicingCannotSliceRace=Can not slice race
|
||||
slicingRaceColumnAlreadyUsedThe=Race column name is already used in the given regatta
|
||||
slicingTimeRangeOutOfBounds=The TimeRange to slice is not part of the race
|
||||
slicingCouldNotObtainRace=Could not obtain sliced race
|
||||
slicingError=Error slicing race
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
slicingCannotSliceRace=Rennen kann nicht geschnitten werden
|
||||
slicingRaceColumnAlreadyUsedThe=Der Rennspaltenname ist in der Regatta bereits verwendet
|
||||
slicingTimeRangeOutOfBounds=Die angegebene Zeitspanne ist ausserhalb des Rennens
|
||||
slicingCouldNotObtainRace=Das geschnittene Rennen konnte nicht gefunden werden
|
||||
slicingError=Fehler beim Schneiden des Rennens
|
||||
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
+2
-2
@@ -9,10 +9,10 @@ import com.sap.sailing.domain.base.SharedDomainFactory;
|
||||
import com.sap.sailing.domain.common.MarkType;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
|
||||
import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.impl.AbstractColor;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
/**
|
||||
* Deserializer for marks.
|
||||
@@ -27,7 +27,7 @@ public class MarkDeserializer implements JsonDeserializer<Mark> {
|
||||
|
||||
@Override
|
||||
public Mark deserialize(JSONObject object) throws JsonDeserializationException {
|
||||
Serializable id = Helpers.tryUuidConversion((Serializable) object.get(MarkJsonSerializer.FIELD_ID));
|
||||
Serializable id = UUIDHelper.tryUuidConversion((Serializable) object.get(MarkJsonSerializer.FIELD_ID));
|
||||
String colorAsString = (String) object.get(MarkJsonSerializer.FIELD_COLOR);
|
||||
Color color = colorAsString == null ? null : AbstractColor.getCssColor(colorAsString);
|
||||
String pattern = (String) object.get(MarkJsonSerializer.FIELD_PATTERN);
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.impl.RGBColor;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public class BoatJsonDeserializer implements JsonDeserializer<DynamicBoat> {
|
||||
private static final Logger logger = Logger.getLogger(BoatJsonDeserializer.class.getName());
|
||||
@@ -63,7 +64,7 @@ public class BoatJsonDeserializer implements JsonDeserializer<DynamicBoat> {
|
||||
Constructor<?> constructorFromString = idClass.getConstructor(String.class);
|
||||
boatId = (Serializable) constructorFromString.newInstance(boatIdFromJson.toString());
|
||||
} else if (UUID.class.isAssignableFrom(idClass)) {
|
||||
boatId = Helpers.tryUuidConversion(boatIdFromJson);
|
||||
boatId = UUIDHelper.tryUuidConversion(boatIdFromJson);
|
||||
} else {
|
||||
boatId = boatIdFromJson;
|
||||
}
|
||||
|
||||
+2
-1
@@ -21,6 +21,7 @@ import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerialize
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.impl.MillisecondsDurationImpl;
|
||||
import com.sap.sse.common.impl.RGBColor;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public class CompetitorJsonDeserializer implements JsonDeserializer<DynamicCompetitor> {
|
||||
private final CompetitorFactory competitorWithBoatFactory;
|
||||
@@ -52,7 +53,7 @@ public class CompetitorJsonDeserializer implements JsonDeserializer<DynamicCompe
|
||||
Constructor<?> constructorFromString = idClass.getConstructor(String.class);
|
||||
competitorId = (Serializable) constructorFromString.newInstance(competitorId.toString());
|
||||
} else if (UUID.class.isAssignableFrom(idClass)) {
|
||||
competitorId = Helpers.tryUuidConversion(competitorId);
|
||||
competitorId = UUIDHelper.tryUuidConversion(competitorId);
|
||||
}
|
||||
String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME);
|
||||
String shortName = (String) object.get(CompetitorJsonConstants.FIELD_SHORT_NAME);
|
||||
|
||||
+2
-1
@@ -14,6 +14,7 @@ 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.JsonDeserializer;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public class CompetitorWithBoatRefJsonDeserializer extends CompetitorJsonDeserializer {
|
||||
private final BoatFactory boatFactory;
|
||||
@@ -47,7 +48,7 @@ public class CompetitorWithBoatRefJsonDeserializer extends CompetitorJsonDeseria
|
||||
Constructor<?> constructorFromString = boatIdClass.getConstructor(String.class);
|
||||
boatId = (Serializable) constructorFromString.newInstance(boatId.toString());
|
||||
} else if (UUID.class.isAssignableFrom(boatIdClass)) {
|
||||
boatId = Helpers.tryUuidConversion(boatId);
|
||||
boatId = UUIDHelper.tryUuidConversion(boatId);
|
||||
}
|
||||
}
|
||||
final DynamicBoat existingBoat = (DynamicBoat) (boatId != null ? boatFactory.getExistingBoatById(boatId) : null);
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ import com.sap.sailing.domain.base.SharedDomainFactory;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.CourseAreaJsonSerializer;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public class CourseAreaJsonDeserializer implements JsonDeserializer<CourseArea> {
|
||||
|
||||
@@ -24,7 +25,7 @@ public class CourseAreaJsonDeserializer implements JsonDeserializer<CourseArea>
|
||||
String name = (String) object.get(CourseAreaJsonSerializer.FIELD_NAME);
|
||||
Serializable id = (Serializable) object.get(CourseAreaJsonSerializer.FIELD_ID);
|
||||
|
||||
return factory.getOrCreateCourseArea((UUID) Helpers.tryUuidConversion(id), name);
|
||||
return factory.getOrCreateCourseArea((UUID) UUIDHelper.tryUuidConversion(id), name);
|
||||
}
|
||||
|
||||
}
|
||||
-18
@@ -1,9 +1,7 @@
|
||||
package com.sap.sailing.server.gateway.deserialization.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
@@ -12,7 +10,6 @@ import org.json.simple.JSONObject;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
|
||||
|
||||
public class Helpers {
|
||||
|
||||
private final static Logger logger = Logger.getLogger(Helpers.class.getName());
|
||||
|
||||
public static JSONArray toJSONArraySafe(Object object) throws JsonDeserializationException {
|
||||
@@ -62,19 +59,4 @@ 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());
|
||||
} catch (IllegalArgumentException iae) {
|
||||
logger.warning("The serializable " + serializableId.toString() + " could not be converted to a UUID");
|
||||
}
|
||||
return serializableId;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-1
@@ -16,6 +16,7 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.impl.RGBColor;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public class LegacyBoatJsonDeserializer implements JsonDeserializer<DynamicBoat> {
|
||||
private final BoatClassJsonDeserializer boatClassDeserializer;
|
||||
@@ -41,7 +42,7 @@ public class LegacyBoatJsonDeserializer implements JsonDeserializer<DynamicBoat>
|
||||
Constructor<?> constructorFromString = idClass.getConstructor(String.class);
|
||||
boatId = (Serializable) constructorFromString.newInstance(boatId.toString());
|
||||
} else if (UUID.class.isAssignableFrom(idClass)) {
|
||||
boatId = Helpers.tryUuidConversion(boatId);
|
||||
boatId = UUIDHelper.tryUuidConversion(boatId);
|
||||
}
|
||||
}
|
||||
String name = (String) object.get(BoatJsonSerializer.FIELD_NAME);
|
||||
|
||||
+2
-1
@@ -21,6 +21,7 @@ import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerialize
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.impl.MillisecondsDurationImpl;
|
||||
import com.sap.sse.common.impl.RGBColor;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public class LegacyCompetitorWithContainedBoatJsonDeserializer implements JsonDeserializer<CompetitorWithBoat> {
|
||||
protected final CompetitorFactory competitorWithBoatFactory;
|
||||
@@ -52,7 +53,7 @@ public class LegacyCompetitorWithContainedBoatJsonDeserializer implements JsonDe
|
||||
Constructor<?> constructorFromString = idClass.getConstructor(String.class);
|
||||
competitorId = (Serializable) constructorFromString.newInstance(competitorId.toString());
|
||||
} else if (UUID.class.isAssignableFrom(idClass)) {
|
||||
competitorId = Helpers.tryUuidConversion(competitorId);
|
||||
competitorId = UUIDHelper.tryUuidConversion(competitorId);
|
||||
}
|
||||
String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME);
|
||||
String shortName = (String) object.get(CompetitorJsonConstants.FIELD_SHORT_NAME);
|
||||
|
||||
+2
-1
@@ -18,6 +18,7 @@ import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.impl.BaseRaceLogEventSerializer;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public abstract class BaseRaceLogEventDeserializer implements JsonDeserializer<RaceLogEvent> {
|
||||
|
||||
@@ -55,7 +56,7 @@ public abstract class BaseRaceLogEventDeserializer implements JsonDeserializer<R
|
||||
}
|
||||
return deserialize(
|
||||
object,
|
||||
Helpers.tryUuidConversion(id),
|
||||
UUIDHelper.tryUuidConversion(id),
|
||||
new MillisecondsTimePoint(createdAt.longValue()),
|
||||
author,
|
||||
timeStamp == null ? null : new MillisecondsTimePoint(timeStamp.longValue()),
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogFinishPositioningConfirmedEventSerializer;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public abstract class RaceLogFinishPositioningEventDeserializer extends BaseRaceLogEventDeserializer {
|
||||
|
||||
@@ -47,7 +48,7 @@ public abstract class RaceLogFinishPositioningEventDeserializer extends BaseRace
|
||||
for (Object object : jsonPositionedCompetitors) {
|
||||
JSONObject jsonPositionedCompetitor = Helpers.toJSONObjectSafe(object);
|
||||
Serializable competitorId = (Serializable) jsonPositionedCompetitor.get(RaceLogFinishPositioningConfirmedEventSerializer.FIELD_COMPETITOR_ID);
|
||||
competitorId = Helpers.tryUuidConversion(competitorId);
|
||||
competitorId = UUIDHelper.tryUuidConversion(competitorId);
|
||||
final String competitorDisplayName = (String) jsonPositionedCompetitor.get(RaceLogFinishPositioningConfirmedEventSerializer.FIELD_COMPETITOR_NAME);
|
||||
final String maxPointsReasonName = (String) jsonPositionedCompetitor.get(RaceLogFinishPositioningConfirmedEventSerializer.FIELD_SCORE_CORRECTIONS_MAX_POINTS_REASON);
|
||||
final MaxPointsReason maxPointsReason = MaxPointsReason.valueOf(maxPointsReasonName);
|
||||
|
||||
+2
-2
@@ -12,9 +12,9 @@ import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogRevokeEventSerializer;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public class RaceLogRevokeEventDeserializer extends BaseRaceLogEventDeserializer {
|
||||
public RaceLogRevokeEventDeserializer(JsonDeserializer<DynamicCompetitor> competitorDeserializer) {
|
||||
@@ -24,7 +24,7 @@ public class RaceLogRevokeEventDeserializer extends BaseRaceLogEventDeserializer
|
||||
@Override
|
||||
protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List<Competitor> competitors)
|
||||
throws JsonDeserializationException {
|
||||
Serializable revokedEventId = Helpers.tryUuidConversion(
|
||||
Serializable revokedEventId = UUIDHelper.tryUuidConversion(
|
||||
(Serializable) object.get(RaceLogRevokeEventSerializer.FIELD_REVOKED_EVENT_ID));
|
||||
String revokedEventType = (String) object.get(RaceLogRevokeEventSerializer.FIELD_REVOKED_EVENT_TYPE);
|
||||
String revokedEventShortInfo = (String) object.get(RaceLogRevokeEventSerializer.FIELD_REVOKED_EVENT_SHORT_INFO);
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@ import com.sap.sailing.server.gateway.deserialization.TypeBasedJsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.GPSFixJsonHandler;
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
public class DeviceAndSessionIdentifierWithGPSFixesDeserializer
|
||||
implements JsonDeserializer<Util.Triple<DeviceIdentifier, Serializable, List<GPSFix>>> {
|
||||
@@ -41,7 +42,7 @@ implements JsonDeserializer<Util.Triple<DeviceIdentifier, Serializable, List<GPS
|
||||
|
||||
Object sessionObject = object.get(FIELD_SESSION_UUID);
|
||||
Serializable sessionId = sessionObject == null ?
|
||||
null : Helpers.tryUuidConversion(((Serializable) sessionObject));
|
||||
null : UUIDHelper.tryUuidConversion(((Serializable) sessionObject));
|
||||
|
||||
JSONArray fixesJson = Helpers.getNestedArraySafe(object, FIELD_FIXES);
|
||||
List<GPSFix> fixes = new ArrayList<GPSFix>();
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
allInOneErrorImportFileMissing=No file to import found!
|
||||
allInOneErrorUnknownImportMode=Unknown import mode!
|
||||
allInOneErrorMissingBoatClass=No boat class name found!
|
||||
allInOneErrorMissingRegattaClass=No regatta name found!
|
||||
allInOneErrorGPSDataImportFailed=Failed to import GPS data!
|
||||
allInOneErrorInvalidData=The regatta could not be resolved, please ensure the name is correct
|
||||
allInOneErrorInvalidRegattaName=Please enter a valid regatta name
|
||||
allInOneErrorInvalidImportMode=Not handled ImportMode
|
||||
allInOneErrorMultiSeries=There is more than one series in this regatta, cannot add race
|
||||
allInOneErrorInvalidSeries=There is no series in this regatta, cannot add race
|
||||
allInOneErrorSplitFleetNotSupported=The expedition importer cannot handle split fleet racing
|
||||
allInOneErrorInvalidRace=To add competitors, a race must be existing
|
||||
allInOneErrorInvalidLeaderBoardEventLink=The Event for the leaderboard could not be obtained, please ensure the leaderboard is properly attached to an leaderboard group that is attached to an event
|
||||
allInOneErrorInvalidLeaderBoard=The Leaderboard could not be resolved, please ensure a leaderboard for the regatta exists
|
||||
allInOneErrorSensorDataImportFailed=Failed to import sensor data!
|
||||
allInOneErrorBoatClassDeterminationFailed=Failed to determine boat class!
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
allInOneErrorImportFileMissing=Die Importdatei wurde nicht gefunden!
|
||||
allInOneErrorUnknownImportMode=Unbekannter Importmodus!
|
||||
allInOneErrorMissingBoatClass=Keine Bootsklasse gefunden!
|
||||
allInOneErrorMissingRegattaClass=Kein Regattaname gefunden!
|
||||
allInOneErrorGPSDataImportFailed=Fehler beim Import der GPS-Daten!
|
||||
allInOneErrorInvalidData=Die Regatta konnte nicht gefunden werden. Bitte sicherstellen, dass der Name gültig ist.
|
||||
allInOneErrorInvalidRegattaName=Bitte einen gültigen Regattanamen eingeben
|
||||
allInOneErrorInvalidImportMode=Nicht unterstützter Importmodus
|
||||
allInOneErrorMultiSeries=Es existiert mehr als eine Serie in der Regatta, Rennen kann nicht hinzugefügt werden
|
||||
allInOneErrorInvalidSeries=Es existiert keine Serie in der Regatta, Rennen kann nicht hinzugefügt werden
|
||||
allInOneErrorSplitFleetNotSupported=Der Expeditionimporter kann nicht in Regatten mit mehreren Flotten importieren
|
||||
allInOneErrorInvalidRace=Um Teilnehmer hinzuzufügen, muss ein Rennen existieren
|
||||
allInOneErrorInvalidLeaderBoardEventLink=Das Event welches zu der Rangliste gehört konnnte nicht bestimmt werden. Bitte sicherstellen, dass die Rangliste an einem Event registiert ist.
|
||||
allInOneErrorInvalidLeaderBoard=Die Rangliste konnte nicht aufgelöst werden. Bitte sicherstellen, dass eine Rangliste für die Regatta existiert.
|
||||
allInOneErrorSensorDataImportFailed=Fehler beim Import der Sensor-Daten!
|
||||
allInOneErrorBoatClassDeterminationFailed=Fehler beim Bestimmen der Bootsklasse
|
||||
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
+3
-2
@@ -124,6 +124,7 @@ 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.MillisecondsTimePoint;
|
||||
import com.sap.sse.util.impl.UUIDHelper;
|
||||
|
||||
@Path("/v1/leaderboards")
|
||||
public class LeaderboardsResource extends AbstractLeaderboardsResource {
|
||||
@@ -322,7 +323,7 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource {
|
||||
from, /* to */ null);
|
||||
} else {
|
||||
// map to a mark
|
||||
final Mark mappedToMark = domainFactory.getExistingMarkById(Helpers.tryUuidConversion(markId));
|
||||
final Mark mappedToMark = domainFactory.getExistingMarkById(UUIDHelper.tryUuidConversion(markId));
|
||||
mappedTo = mappedToMark;
|
||||
if (mappedToMark == null) {
|
||||
logger.warning("No mark found for id " + markId);
|
||||
@@ -396,7 +397,7 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource {
|
||||
} else {
|
||||
// map to mark
|
||||
DomainFactory domainFactory = getService().getDomainObjectFactory().getBaseDomainFactory();
|
||||
final Mark mappedToMark = domainFactory.getExistingMarkById(Helpers.tryUuidConversion(markId));
|
||||
final Mark mappedToMark = domainFactory.getExistingMarkById(UUIDHelper.tryUuidConversion(markId));
|
||||
mappedTo = mappedToMark;
|
||||
if (mappedToMark == null) {
|
||||
logger.warning("No mark found for id " + markId);
|
||||
|
||||
+57
-12
@@ -1,8 +1,10 @@
|
||||
package com.sap.sailing.server.gateway.trackfiles.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -15,30 +17,37 @@ import org.apache.commons.fileupload.FileItem;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.common.dto.ExpeditionAllInOneConstants;
|
||||
import com.sap.sailing.domain.common.dto.ExpeditionAllInOneConstants.ImportMode;
|
||||
import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapterFactory;
|
||||
import com.sap.sailing.server.gateway.impl.AbstractFileUploadServlet;
|
||||
import com.sap.sailing.server.gateway.trackfiles.impl.ExpeditionAllInOneImporter.ImporterResult;
|
||||
import com.sap.sse.i18n.ResourceBundleStringMessages;
|
||||
import com.sap.sse.i18n.impl.ResourceBundleStringMessagesImpl;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
/**
|
||||
* Import servlet for sensor data files. Importers are located through the OSGi service registry and matched against the
|
||||
* name provided by the upload form.
|
||||
*
|
||||
* @see ExpeditionAllInOneImporter
|
||||
*/
|
||||
public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet {
|
||||
private static final long serialVersionUID = 1120226743039934620L;
|
||||
private static final Logger logger = Logger.getLogger(ExpeditionAllInOneImportServlet.class.getName());
|
||||
|
||||
private static final String REQUEST_PARAMETER_BOAT_CLASS = "boatClass";
|
||||
private static final String ERROR_MESSAGE_IMPORT_FILE_MISSING = "No file to import found!";
|
||||
private static final String ERROR_MESSAGE_BOAT_CLASS_MISSING = "No boat class name found!";
|
||||
private static final String STRING_MESSAGES_BASE_NAME = "stringmessages/StringMessages";
|
||||
|
||||
private ServiceTracker<RaceLogTrackingAdapterFactory, RaceLogTrackingAdapterFactory> raceLogTrackingAdapterTracker;
|
||||
private ResourceBundleStringMessages serverStringMessages;
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
raceLogTrackingAdapterTracker = ServiceTrackerFactory.createAndOpen(getContext(),
|
||||
RaceLogTrackingAdapterFactory.class);
|
||||
serverStringMessages = new ResourceBundleStringMessagesImpl(STRING_MESSAGES_BASE_NAME,
|
||||
this.getClass().getClassLoader(), StandardCharsets.UTF_8.name());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,25 +62,63 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet {
|
||||
String fileName = null;
|
||||
FileItem fileItem = null;
|
||||
String boatClassName = null;
|
||||
String regattaName = null;
|
||||
String importModeName = null;
|
||||
String localeName = null;
|
||||
for (FileItem fi : fileItems) {
|
||||
if (!fi.isFormField()) {
|
||||
fileName = fi.getName();
|
||||
fileItem = fi;
|
||||
} else if (fi.getFieldName() != null) {
|
||||
if (REQUEST_PARAMETER_BOAT_CLASS.equals(fi.getFieldName())) {
|
||||
if (ExpeditionAllInOneConstants.REQUEST_PARAMETER_BOAT_CLASS.equals(fi.getFieldName())) {
|
||||
boatClassName = fi.getString();
|
||||
}
|
||||
if (ExpeditionAllInOneConstants.REQUEST_PARAMETER_REGATTA_NAME.equals(fi.getFieldName())) {
|
||||
regattaName = fi.getString();
|
||||
}
|
||||
if (ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE.equals(fi.getFieldName())) {
|
||||
importModeName = fi.getString();
|
||||
}
|
||||
if (ExpeditionAllInOneConstants.REQUEST_PARAMETER_LOCALE.equals(fi.getFieldName())) {
|
||||
localeName = fi.getString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Locale uiLocale;
|
||||
if (localeName == null) {
|
||||
uiLocale = Locale.ENGLISH;
|
||||
} else {
|
||||
try {
|
||||
uiLocale = Locale.forLanguageTag(localeName);
|
||||
} catch (Exception e) {
|
||||
uiLocale = Locale.ENGLISH;
|
||||
}
|
||||
}
|
||||
if (fileItem == null) {
|
||||
throw new AllinOneImportException(ERROR_MESSAGE_IMPORT_FILE_MISSING);
|
||||
throw new AllinOneImportException(serverStringMessages.get(uiLocale, "allInOneErrorImportFileMissing"));
|
||||
}
|
||||
if (boatClassName == null || boatClassName.isEmpty()) {
|
||||
throw new AllinOneImportException(ERROR_MESSAGE_BOAT_CLASS_MISSING);
|
||||
final ImportMode importMode;
|
||||
if (importModeName == null) {
|
||||
importMode = ImportMode.NEW_EVENT;
|
||||
} else {
|
||||
try {
|
||||
importMode = ImportMode.valueOf(importModeName);
|
||||
} catch (Exception e) {
|
||||
throw new AllinOneImportException(serverStringMessages.get(uiLocale, "allInOneErrorUnknownImportMode"));
|
||||
}
|
||||
}
|
||||
importerResult = new ExpeditionAllInOneImporter(getService(),
|
||||
if (importMode == ImportMode.NEW_EVENT) {
|
||||
if (boatClassName == null || boatClassName.isEmpty()) {
|
||||
throw new AllinOneImportException(serverStringMessages.get(uiLocale, "allInOneErrorMissingBoatClass"));
|
||||
}
|
||||
} else {
|
||||
if (regattaName == null || regattaName.isEmpty()) {
|
||||
throw new AllinOneImportException(serverStringMessages.get(uiLocale, "allInOneErrorMissingRegattaClass"));
|
||||
}
|
||||
}
|
||||
importerResult = new ExpeditionAllInOneImporter(serverStringMessages, uiLocale, getService(),
|
||||
raceLogTrackingAdapterTracker.getService().getAdapter(getService().getBaseDomainFactory()),
|
||||
getServiceFinderFactory(), getContext()).importFiles(fileName, fileItem, boatClassName);
|
||||
getServiceFinderFactory(), getContext()).importFiles(fileName, fileItem, boatClassName, importMode, regattaName);
|
||||
} catch (AllinOneImportException e) {
|
||||
importerResult = new ImporterResult(e, e.additionalErrors);
|
||||
logger.log(Level.SEVERE, e.getMessage());
|
||||
@@ -89,9 +136,7 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet {
|
||||
json.put("leaderboardName", importerResult.leaderboardName);
|
||||
json.put("leaderboardGroupName", importerResult.leaderboardGroupName);
|
||||
json.put("regattaName", importerResult.regattaName);
|
||||
json.put("raceName", importerResult.raceName);
|
||||
json.put("raceColumnName", importerResult.raceColumnName);
|
||||
json.put("fleetName", importerResult.fleetName);
|
||||
json.put("raceNameRaceColumnNameFleetNameList", ImportResultSerializer.serializeRaceList(importerResult.raceNameRaceColumnNameFleetnameList));
|
||||
json.put("errors", ImportResultSerializer.serializeErrorList(importerResult.errorList));
|
||||
json.put("gpsDeviceIds", ImportResultSerializer.serializeTrackList(importerResult.importGpsFixData));
|
||||
json.put("sensorDeviceIds", ImportResultSerializer.serializeTrackList(importerResult.importSensorFixData));
|
||||
|
||||
+358
-83
@@ -12,11 +12,17 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
@@ -25,31 +31,45 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImp
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
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.common.LeaderboardNameConstants;
|
||||
import com.sap.sailing.domain.common.Placemark;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.RankingMetrics;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaName;
|
||||
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.dto.ExpeditionAllInOneConstants.ImportMode;
|
||||
import com.sap.sailing.domain.common.dto.FleetDTO;
|
||||
import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO;
|
||||
import com.sap.sailing.domain.common.dto.SeriesCreationParametersDTO;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.common.tracking.BravoExtendedFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
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.racelogtracking.RaceLogTrackingAdapter;
|
||||
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
|
||||
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifierImpl;
|
||||
import com.sap.sailing.domain.trackimport.DoubleVectorFixImporter;
|
||||
import com.sap.sailing.domain.trackimport.GPSFixImporter;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.RaceHandle;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.geocoding.ReverseGeocoder;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.gateway.trackfiles.impl.ImportResultDTO.ErrorImportDTO;
|
||||
import com.sap.sailing.server.gateway.trackfiles.impl.ImportResultDTO.TrackImportDTO;
|
||||
@@ -62,48 +82,91 @@ import com.sap.sailing.server.operationaltransformation.CreateLeaderboardGroup;
|
||||
import com.sap.sailing.server.operationaltransformation.CreateRegattaLeaderboard;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateEvent;
|
||||
import com.sap.sailing.server.util.WaitForTrackedRaceUtil;
|
||||
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TypeBasedServiceFinderFactory;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.i18n.ResourceBundleStringMessages;
|
||||
|
||||
/**
|
||||
* Importer for expedition data that imports all available data for a boat:
|
||||
* <ul>
|
||||
* <li>{@link GPSFixMoving} and {@link BravoExtendedFix} instances are imported as a distinct track that needs to be
|
||||
* mapped to a specific competitor afterwards</li>
|
||||
* <li>Wind fixes are being imported as a new {@link WindTrack}</li>
|
||||
* </ul>
|
||||
* There are several {@link ImportMode ImportModes} which have specific preconditions and activate different importing
|
||||
* behavior:
|
||||
* <ul>
|
||||
* <li>{@link ImportMode#NEW_EVENT} requires a boatclass name to be given. In this case new {@link Event},
|
||||
* {@link Regatta} and {@link RegattaLeaderboard} entities are created with one {@link RaceColumn} for a new
|
||||
* {@link TrackedRace} to be the target of the imported data. The names of the created entities as well as the created
|
||||
* {@link RaceColumn} and {@link WindSource} are generated from the name of the given {@link FileItem}.</li>
|
||||
* <li>{@link ImportMode#NEW_COMPETITOR} requires a regatta name to be given. In this case the wind data is being
|
||||
* imported as new {@link WindSource} to any existing race of the given regatta. The name of the {@link WindSource} is
|
||||
* determined from the name of the given {@link FileItem}. No new entities are created.</li>
|
||||
* <li>{@link ImportMode#NEW_RACE} requires a regatta name to be given. In this case the a new {@link RaceColumn} is
|
||||
* created in the last existing {@link Series}. A new {@link WindSource} is added to the {@link TrackedRace} associated
|
||||
* with the newly added {@link RaceColumn}. This mode does not support importing in cases where fleet racing is used by
|
||||
* a {@link Regatta}.</li>
|
||||
* </ul>
|
||||
* The imported {@link GPSFixMoving} and {@link BravoExtendedFix} tracks aren't mapped to a {@link Competitor} by the
|
||||
* importer. Instead the IDs of the imported tracks are contained in the result and are expected to be mapped by the
|
||||
* user afterwards.
|
||||
*
|
||||
* This importer is intended to be used by {@link ExpeditionAllInOneImportServlet}.
|
||||
*/
|
||||
public class ExpeditionAllInOneImporter {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ExpeditionAllInOneImporter.class.getName());
|
||||
|
||||
private static final String ERROR_MESSAGE_GPS_DATA_IMPORT_FAILED = "Failed to import GPS data!";
|
||||
private static final String ERROR_MESSAGE_SENSOR_DATA_IMPORT_FAILED = "Failed to import sensor data!";
|
||||
private static final String ERROR_MESSAGE_BOAT_CLASS_DETERMINATION_FAILED = "Failed to determine boat class!";
|
||||
private static final double VENUE_RANGE_CHECK = 10;
|
||||
|
||||
private final RacingEventService service;
|
||||
private final RaceLogTrackingAdapter adapter;
|
||||
private final TypeBasedServiceFinderFactory serviceFinderFactory;
|
||||
private final BundleContext context;
|
||||
|
||||
private ResourceBundleStringMessages serverStringMessages;
|
||||
private Locale uiLocale;
|
||||
|
||||
public static class ImporterResult {
|
||||
final UUID eventId;
|
||||
final String leaderboardName, leaderboardGroupName, regattaName, raceName, raceColumnName, fleetName;
|
||||
final List<Triple<String, String, String>> raceNameRaceColumnNameFleetnameList = new ArrayList<>();
|
||||
final String leaderboardName, leaderboardGroupName, regattaName;
|
||||
final List<TrackImportDTO> importGpsFixData, importSensorFixData;
|
||||
final String sensorFixImporterType;
|
||||
final List<ErrorImportDTO> errorList = new ArrayList<>();
|
||||
|
||||
public ImporterResult(String error) {
|
||||
this(null, "", "", "", Collections.emptyList(), Collections.emptyList(),
|
||||
Collections.emptyList(), "", Collections.emptyList());
|
||||
errorList.add(new ErrorImportDTO(error));
|
||||
}
|
||||
|
||||
public ImporterResult(Throwable exception, List<ErrorImportDTO> additionalErrors) {
|
||||
this(null, "", "", new RegattaNameAndRaceName("", ""), "", "", Collections.emptyList(),
|
||||
Collections.emptyList(), "", additionalErrors);
|
||||
this.errorList.add(new ErrorImportDTO(exception.getClass().getName(), exception.getMessage()));
|
||||
this(null, "", "","", Collections.emptyList(), Collections.emptyList(),
|
||||
Collections.emptyList(), "", Collections.emptyList());
|
||||
errorList.add(new ErrorImportDTO(exception.getClass().getName(), exception.getMessage()));
|
||||
if (additionalErrors != null) {
|
||||
errorList.addAll(additionalErrors);
|
||||
}
|
||||
}
|
||||
|
||||
private ImporterResult(final UUID eventId, final String leaderboardName, String leaderboardGroupName,
|
||||
final RegattaAndRaceIdentifier regattaAndRaceIdentifier, final String raceColumnName,
|
||||
final String fleetName, final List<TrackImportDTO> importGpsFixData,
|
||||
final List<TrackImportDTO> importSensorFixData, final String sensorFixImporterType,
|
||||
List<ErrorImportDTO> errors) {
|
||||
final String regattaName, List<Triple<String, String, String>> raceNameRaceColumnNameFleetnameList,
|
||||
final List<TrackImportDTO> importGpsFixData, final List<TrackImportDTO> importSensorFixData,
|
||||
final String sensorFixImporterType, List<ErrorImportDTO> errors) {
|
||||
this.eventId = eventId;
|
||||
this.leaderboardName = leaderboardName;
|
||||
this.leaderboardGroupName = leaderboardGroupName;
|
||||
this.regattaName = regattaAndRaceIdentifier.getRegattaName();
|
||||
this.raceName = regattaAndRaceIdentifier.getRaceName();
|
||||
this.raceColumnName = raceColumnName;
|
||||
this.fleetName = fleetName;
|
||||
this.regattaName = regattaName;
|
||||
if (raceNameRaceColumnNameFleetnameList != null) {
|
||||
this.raceNameRaceColumnNameFleetnameList.addAll(raceNameRaceColumnNameFleetnameList);
|
||||
}
|
||||
this.importGpsFixData = importGpsFixData;
|
||||
this.importSensorFixData = importSensorFixData;
|
||||
this.sensorFixImporterType = sensorFixImporterType;
|
||||
@@ -111,8 +174,10 @@ public class ExpeditionAllInOneImporter {
|
||||
}
|
||||
}
|
||||
|
||||
public ExpeditionAllInOneImporter(final RacingEventService service, RaceLogTrackingAdapter adapter,
|
||||
public ExpeditionAllInOneImporter(ResourceBundleStringMessages serverStringMessages, Locale uiLocale, final RacingEventService service, RaceLogTrackingAdapter adapter,
|
||||
final TypeBasedServiceFinderFactory serviceFinderFactory, final BundleContext context) {
|
||||
this.serverStringMessages = serverStringMessages;
|
||||
this.uiLocale = uiLocale;
|
||||
this.service = service;
|
||||
this.adapter = adapter;
|
||||
this.serviceFinderFactory = serviceFinderFactory;
|
||||
@@ -120,36 +185,16 @@ public class ExpeditionAllInOneImporter {
|
||||
}
|
||||
|
||||
public ImporterResult importFiles(final String filenameWithSuffix, final FileItem fileItem,
|
||||
final String boatClassName) throws AllinOneImportException {
|
||||
final String boatClassName, ImportMode importMode, String existingRegattaName) throws AllinOneImportException {
|
||||
final List<ErrorImportDTO> errors = new ArrayList<>();
|
||||
final String importTimeString = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now(ZoneOffset.UTC));
|
||||
|
||||
final String filename = ExpeditionImportFilenameUtils.truncateFilenameExtentions(filenameWithSuffix);
|
||||
final String filenameWithDateTimeSuffix = filename + "_" + importTimeString;
|
||||
final String eventName = filenameWithDateTimeSuffix;
|
||||
final String description = MessageFormat.format("Event imported from expedition file ''{0}'' on {1}",
|
||||
filenameWithSuffix, importTimeString);
|
||||
final String leaderboardGroupName = filenameWithDateTimeSuffix;
|
||||
final String regattaNameAndleaderboardName = filenameWithDateTimeSuffix;
|
||||
final RegattaIdentifier regattaIdentifier = new RegattaName(filenameWithDateTimeSuffix);
|
||||
final String raceColumnName = filename;
|
||||
final String trackedRaceName = filenameWithDateTimeSuffix;
|
||||
final String courseAreaName = "Default";
|
||||
final UUID courseAreaId = UUID.randomUUID();
|
||||
// This is just the default used in the UI
|
||||
final Double buoyZoneRadiusInHullLengths = 3.0;
|
||||
// TODO is this a proper id for the WindSource used here?
|
||||
final String windSourceId = filenameWithDateTimeSuffix;
|
||||
|
||||
// TODO guess venue based on the reverse geocoder?
|
||||
final String venueName = filename;
|
||||
|
||||
final String fleetName = LeaderboardNameConstants.DEFAULT_FLEET_NAME;
|
||||
final String seriesName = Series.DEFAULT_NAME;
|
||||
|
||||
// TODO wild guess...
|
||||
final ScoringSchemeType scoringSchemeType = ScoringSchemeType.LOW_POINT;
|
||||
final RankingMetrics rankingMetric = RankingMetrics.ONE_DESIGN;
|
||||
final int[] discardThresholds = new int[0];
|
||||
|
||||
final ImportResultDTO jsonHolderForGpsFixImport = new ImportResultDTO(logger);
|
||||
@@ -157,12 +202,14 @@ public class ExpeditionAllInOneImporter {
|
||||
try {
|
||||
new TrackFilesImporter(service, serviceFinderFactory, context).importFixes(jsonHolderForGpsFixImport,
|
||||
GPSFixImporter.EXPEDITION_TYPE, filesForGpsFixImport);
|
||||
this.ensureSuccessfulImport(jsonHolderForGpsFixImport, ERROR_MESSAGE_GPS_DATA_IMPORT_FAILED);
|
||||
this.ensureSuccessfulImport(jsonHolderForGpsFixImport,
|
||||
serverStringMessages.get(uiLocale, "allInOneErrorGPSDataImportFailed"));
|
||||
} catch (IOException e1) {
|
||||
errors.addAll(jsonHolderForGpsFixImport.getErrorList());
|
||||
throw new AllinOneImportException(e1, errors);
|
||||
}
|
||||
errors.addAll(jsonHolderForGpsFixImport.getErrorList());
|
||||
|
||||
|
||||
final ImportResultDTO jsonHolderForSensorFixImport = new ImportResultDTO(logger);
|
||||
final String sensorFixImporterType = DoubleVectorFixImporter.EXPEDITION_EXTENDED_TYPE;
|
||||
@@ -171,7 +218,8 @@ public class ExpeditionAllInOneImporter {
|
||||
try {
|
||||
new SensorDataImporter(service, context).importFiles(false, jsonHolderForSensorFixImport,
|
||||
importerNamesAndFilesForSensorFixImport);
|
||||
this.ensureSuccessfulImport(jsonHolderForSensorFixImport, ERROR_MESSAGE_SENSOR_DATA_IMPORT_FAILED);
|
||||
this.ensureSuccessfulImport(jsonHolderForSensorFixImport,
|
||||
serverStringMessages.get(uiLocale, "allInOneErrorSensorDataImportFailed"));
|
||||
} catch (IOException e1) {
|
||||
errors.addAll(jsonHolderForSensorFixImport.getErrorList());
|
||||
throw new AllinOneImportException(e1, errors);
|
||||
@@ -194,14 +242,244 @@ public class ExpeditionAllInOneImporter {
|
||||
lastFixAt = deviceTrackEnd;
|
||||
}
|
||||
}
|
||||
|
||||
final TimePoint eventStartDate = firstFixAt;
|
||||
final TimePoint eventEndDate = lastFixAt;
|
||||
|
||||
final UUID eventId;
|
||||
final String leaderboardGroupName;
|
||||
final String regattaNameAndleaderboardName;
|
||||
final List<Triple<String, String, String>> raceNameRaceColumnNameFleetnameList = new ArrayList<>();
|
||||
final List<DynamicTrackedRace> trackedRaces = new ArrayList<>();
|
||||
if (importMode == ImportMode.NEW_EVENT) {
|
||||
leaderboardGroupName = filenameWithDateTimeSuffix;
|
||||
regattaNameAndleaderboardName = filenameWithDateTimeSuffix;
|
||||
String raceColumnName = filename;
|
||||
eventId = UUID.randomUUID();
|
||||
String fleetName = LeaderboardNameConstants.DEFAULT_FLEET_NAME;
|
||||
final DynamicTrackedRace trackedRace = createEventStructureWithASingleRaceAndTrackIt(filenameWithSuffix, boatClassName, errors, importTimeString, filename,
|
||||
filenameWithDateTimeSuffix, trackedRaceName, discardThresholds, firstFixAt, lastFixAt,
|
||||
eventStartDate, eventEndDate, eventId, leaderboardGroupName, regattaNameAndleaderboardName,
|
||||
fleetName, raceColumnName);
|
||||
trackedRaces.add(trackedRace);
|
||||
raceNameRaceColumnNameFleetnameList.add(new Triple<>(trackedRaceName, raceColumnName, fleetName));
|
||||
updateVenueName(filename, jsonHolderForGpsFixImport.getImportResult(), eventId);
|
||||
} else {
|
||||
regattaNameAndleaderboardName = existingRegattaName;
|
||||
if (existingRegattaName != null && !existingRegattaName.isEmpty()) {
|
||||
final Regatta regatta = service.getRegattaByName(existingRegattaName);
|
||||
if (regatta == null) {
|
||||
return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorInvalidData"));
|
||||
}
|
||||
final Leaderboard leaderboard = service.getLeaderboardByName(existingRegattaName);
|
||||
if (leaderboard == null || !(leaderboard instanceof RegattaLeaderboard)) {
|
||||
return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorInvalidLeaderBoard"));
|
||||
}
|
||||
final RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard;
|
||||
|
||||
final Pair<Event, LeaderboardGroup> foundEventAndLeaderboardGroup = findEventAndLeaderboardGroupForExistingLeaderboard(leaderboard);
|
||||
|
||||
if (foundEventAndLeaderboardGroup == null) {
|
||||
return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorInvalidLeaderBoardEventLink"));
|
||||
}
|
||||
|
||||
eventId = foundEventAndLeaderboardGroup.getA().getId();
|
||||
ensureEventLongEnough(firstFixAt, lastFixAt, eventId);
|
||||
leaderboardGroupName = foundEventAndLeaderboardGroup.getB().getName();
|
||||
|
||||
if (importMode == ImportMode.NEW_COMPETITOR) {
|
||||
final Iterable<RaceColumn> raceColumns = regattaLeaderboard.getRaceColumns();
|
||||
if (Util.isEmpty(raceColumns)) {
|
||||
return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorInvalidRace"));
|
||||
}
|
||||
try {
|
||||
for (RaceColumn raceColumn : raceColumns) {
|
||||
final Iterable<? extends Fleet> fleets = raceColumn.getFleets();
|
||||
if (Util.size(fleets) != 1) {
|
||||
return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorSplitFleetNotSupported"));
|
||||
}
|
||||
final Fleet fleet = fleets.iterator().next();
|
||||
DynamicTrackedRace trackedRaceForColumn = (DynamicTrackedRace) raceColumn.getTrackedRace(fleet);
|
||||
if (trackedRaceForColumn == null) {
|
||||
trackedRaceForColumn = trackRace(regattaLeaderboard, raceColumn, fleet);
|
||||
}
|
||||
trackedRaces.add(trackedRaceForColumn);
|
||||
raceNameRaceColumnNameFleetnameList
|
||||
.add(new Triple<>(trackedRaceForColumn.getRaceIdentifier().getRaceName(),
|
||||
raceColumn.getName(), fleet.getName()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new AllinOneImportException(e, errors);
|
||||
}
|
||||
} else if (importMode == ImportMode.NEW_RACE) {
|
||||
final Iterable<? extends Series> seriesInRegatta = regatta.getSeries();
|
||||
if (Util.isEmpty(seriesInRegatta)) {
|
||||
return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorInvalidSeries"));
|
||||
}
|
||||
final Series series = Util.get(seriesInRegatta, Util.size(seriesInRegatta) - 1);
|
||||
final Iterable<? extends Fleet> fleets = series.getFleets();
|
||||
if (Util.size(fleets) != 1) {
|
||||
return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorMultiSeries"));
|
||||
}
|
||||
final Fleet fleet = fleets.iterator().next();
|
||||
final String fleetName = fleet.getName();
|
||||
// When uploading files with identical name, the second RaceColumn will be named with the upload time in its name
|
||||
final String raceColumnName = regatta.getRaceColumnByName(filename) == null ? filename : filenameWithDateTimeSuffix;
|
||||
final RaceColumn raceColumn = service.apply(new AddColumnToSeries(regatta.getRegattaIdentifier(), series.getName(), raceColumnName));
|
||||
|
||||
final Event event = service.addEvent(eventName, description, eventStartDate, eventEndDate, venueName, true,
|
||||
UUID.randomUUID());
|
||||
final DynamicTrackedRace trackedRace = createTrackedRaceAndSetupRaceTimes(errors, trackedRaceName, firstFixAt, lastFixAt, regatta, regattaLeaderboard,
|
||||
raceColumn, fleet);
|
||||
trackedRaces.add(trackedRace);
|
||||
raceNameRaceColumnNameFleetnameList.add(new Triple<>(trackedRaceName, raceColumnName, fleetName));
|
||||
} else {
|
||||
return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorInvalidImportMode") + importMode);
|
||||
}
|
||||
} else {
|
||||
return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorInvalidRegattaName"));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
final WindImportResult windImportResult = new AbstractWindImporter.WindImportResult();
|
||||
final WindSourceWithAdditionalID windSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION,
|
||||
windSourceId);
|
||||
final Map<InputStream, String> streamsWithFilenames = new HashMap<>();
|
||||
streamsWithFilenames.put(fileItem.getInputStream(), filenameWithSuffix);
|
||||
new WindImporter().importWindToWindSourceAndTrackedRaces(service, windImportResult, windSource,
|
||||
trackedRaces, streamsWithFilenames);
|
||||
|
||||
return new ImporterResult(eventId, regattaNameAndleaderboardName, leaderboardGroupName,
|
||||
regattaNameAndleaderboardName, raceNameRaceColumnNameFleetnameList,
|
||||
jsonHolderForGpsFixImport.getImportResult(), jsonHolderForSensorFixImport.getImportResult(),
|
||||
sensorFixImporterType, errors);
|
||||
} catch (Exception e) {
|
||||
throw new AllinOneImportException(e, errors);
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureEventLongEnough(TimePoint firstFixAt, TimePoint lastFixAt, UUID eventId) {
|
||||
Event event = service.getEvent(eventId);
|
||||
TimePoint startDate = event.getStartDate();
|
||||
if(firstFixAt.before(startDate)) {
|
||||
startDate = firstFixAt;
|
||||
}
|
||||
TimePoint endDate = event.getEndDate();
|
||||
if(lastFixAt.after(endDate)) {
|
||||
endDate = lastFixAt;
|
||||
}
|
||||
Iterable<UUID> leaderboardGroups = StreamSupport.stream(event.getLeaderboardGroups().spliterator(), false).map(t -> t.getId()).collect(Collectors.toList());
|
||||
|
||||
service.apply(new UpdateEvent(event.getId(), event.getName(), event.getDescription(), startDate,
|
||||
endDate, event.getVenue().getName(), event.isPublic(),
|
||||
leaderboardGroups, event.getOfficialWebsiteURL(), event.getBaseURL(),
|
||||
event.getSailorsInfoWebsiteURLs(), event.getImages(), event.getVideos(), event.getWindFinderReviewedSpotsCollectionIds()));
|
||||
}
|
||||
|
||||
private Pair<Event, LeaderboardGroup> findEventAndLeaderboardGroupForExistingLeaderboard(final Leaderboard leaderboard) {
|
||||
for (Event event : service.getAllEvents()) {
|
||||
for (LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) {
|
||||
for (Leaderboard lb : leaderboardGroup.getLeaderboards()) {
|
||||
if (lb.equals(leaderboard)) {
|
||||
return new Pair<>(event, leaderboardGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private DynamicTrackedRace createEventStructureWithASingleRaceAndTrackIt(final String filenameWithSuffix, final String boatClassName,
|
||||
final List<ErrorImportDTO> errors, final String importTimeString, final String filename,
|
||||
final String filenameWithDateTimeSuffix, final String trackedRaceName, final int[] discardThresholds,
|
||||
TimePoint firstFixAt, TimePoint lastFixAt, final TimePoint eventStartDate, final TimePoint eventEndDate,
|
||||
final UUID eventId, final String leaderboardGroupName, final String regattaNameAndleaderboardName,
|
||||
final String fleetName, final String raceColumnName) throws AllinOneImportException {
|
||||
final DynamicTrackedRace trackedRace;
|
||||
|
||||
final String eventName = filenameWithDateTimeSuffix;
|
||||
final String description = MessageFormat.format("Event imported from expedition file ''{0}'' on {1}",
|
||||
filenameWithSuffix, importTimeString);
|
||||
final RegattaIdentifier regattaIdentifier = new RegattaName(filenameWithDateTimeSuffix);
|
||||
// This is just the default used in the UI
|
||||
final Double buoyZoneRadiusInHullLengths = 3.0;
|
||||
|
||||
final String seriesName = Series.DEFAULT_NAME;
|
||||
|
||||
final Event event = service.addEvent(eventName, description, eventStartDate, eventEndDate, filename, true,
|
||||
eventId);
|
||||
|
||||
final UUID courseAreaId = addDefaultCourseArea(event);
|
||||
|
||||
final Regatta regatta = createRegattaWithOneRaceColumn(boatClassName, regattaNameAndleaderboardName,
|
||||
fleetName, raceColumnName, regattaIdentifier, courseAreaId, buoyZoneRadiusInHullLengths,
|
||||
seriesName);
|
||||
final RegattaLeaderboard regattaLeaderboard = service.apply(new CreateRegattaLeaderboard(regattaIdentifier, null,
|
||||
discardThresholds));
|
||||
|
||||
createLeaderboardGroupAndAddItToTheEvent(leaderboardGroupName, regattaNameAndleaderboardName, description, event);
|
||||
|
||||
final RaceColumn raceColumn = regattaLeaderboard.getRaceColumns().iterator().next();
|
||||
final Fleet fleet = raceColumn.getFleets().iterator().next();
|
||||
|
||||
trackedRace = createTrackedRaceAndSetupRaceTimes(errors, trackedRaceName, firstFixAt, lastFixAt, regatta, regattaLeaderboard,
|
||||
raceColumn, fleet);
|
||||
return trackedRace;
|
||||
}
|
||||
|
||||
private void updateVenueName(String filename, List<TrackImportDTO> list, UUID eventId) {
|
||||
for (TrackImportDTO f : list) {
|
||||
TrackFileImportDeviceIdentifier deviceIdentifier = TrackFileImportDeviceIdentifierImpl
|
||||
.getOrCreate(f.getDevice());
|
||||
final TimePoint end = f.getRange().to();
|
||||
try {
|
||||
final CompletableFuture<GPSFix> waitForFix = new CompletableFuture<>();
|
||||
service.getSensorFixStore().loadFixes(waitForFix::complete, deviceIdentifier, end, end, true);
|
||||
GPSFix gpsFix = waitForFix.getNow(null);
|
||||
if (gpsFix != null) {
|
||||
Position pos = gpsFix.getPosition();
|
||||
if (pos != null) {
|
||||
try {
|
||||
Placemark reverseVenue = ReverseGeocoder.INSTANCE.getPlacemarkFirst(pos, VENUE_RANGE_CHECK,
|
||||
new Placemark.ByPopulationDistanceRatio(pos));
|
||||
if (reverseVenue != null) {
|
||||
String newVenueName = reverseVenue.getName();
|
||||
Event event = service.getEvent(eventId);
|
||||
Iterable<UUID> leaderboardGroups = StreamSupport
|
||||
.stream(event.getLeaderboardGroups().spliterator(), false).map(t -> t.getId())
|
||||
.collect(Collectors.toList());
|
||||
service.apply(new UpdateEvent(event.getId(), event.getName(), event.getDescription(),
|
||||
event.getStartDate(), event.getEndDate(), newVenueName, event.isPublic(),
|
||||
leaderboardGroups, event.getOfficialWebsiteURL(), event.getBaseURL(),
|
||||
event.getSailorsInfoWebsiteURLs(), event.getImages(), event.getVideos(),
|
||||
event.getWindFinderReviewedSpotsCollectionIds()));
|
||||
break;
|
||||
}
|
||||
} catch (IOException | ParseException e) {
|
||||
logger.log(Level.WARNING, "Could not reverse determine location " + pos, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (NoCorrespondingServiceRegisteredException | TransformationException e) {
|
||||
logger.log(Level.WARNING, "Could not reverse determine location", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private UUID addDefaultCourseArea(final Event event) {
|
||||
final String courseAreaName = "Default";
|
||||
final UUID courseAreaId = UUID.randomUUID();
|
||||
service.addCourseAreas(event.getId(), new String[] { courseAreaName }, new UUID[] { courseAreaId });
|
||||
return courseAreaId;
|
||||
}
|
||||
|
||||
private Regatta createRegattaWithOneRaceColumn(final String boatClassName, final String regattaNameAndleaderboardName, final String fleetName,
|
||||
final String raceColumnName, final RegattaIdentifier regattaIdentifier, final UUID courseAreaId,
|
||||
final Double buoyZoneRadiusInHullLengths, final String seriesName) throws AllinOneImportException {
|
||||
|
||||
// TODO wild guess...
|
||||
final ScoringSchemeType scoringSchemeType = ScoringSchemeType.LOW_POINT;
|
||||
final RankingMetrics rankingMetric = RankingMetrics.ONE_DESIGN;
|
||||
|
||||
final Regatta regatta;
|
||||
final ScoringScheme scoringScheme = service.getBaseDomainFactory().createScoringScheme(scoringSchemeType);
|
||||
|
||||
final LinkedHashMap<String, SeriesCreationParametersDTO> seriesCreationParameters = new LinkedHashMap<>();
|
||||
@@ -214,73 +492,70 @@ public class ExpeditionAllInOneImporter {
|
||||
final RegattaCreationParametersDTO regattaCreationParameters = new RegattaCreationParametersDTO(
|
||||
seriesCreationParameters);
|
||||
|
||||
final Regatta regatta = service.apply(new AddSpecificRegatta(regattaNameAndleaderboardName, boatClassName,
|
||||
/* can boats of competitors change */ false,
|
||||
/* start date */ null, /* end date */ null, UUID.randomUUID(),
|
||||
regatta = service.apply(new AddSpecificRegatta(regattaNameAndleaderboardName, boatClassName,
|
||||
/* can boats of competitors change */ false,
|
||||
/* start date */ null, /* end date */ null, UUID.randomUUID(),
|
||||
regattaCreationParameters, true, scoringScheme, courseAreaId, buoyZoneRadiusInHullLengths, true,
|
||||
false, rankingMetric));
|
||||
this.ensureBoatClassDetermination(regatta);
|
||||
service.apply(new AddColumnToSeries(regattaIdentifier, seriesName, raceColumnName));
|
||||
final RegattaLeaderboard regattaLeaderboard = service.apply(new CreateRegattaLeaderboard(regattaIdentifier, null,
|
||||
discardThresholds));
|
||||
return regatta;
|
||||
}
|
||||
|
||||
private void createLeaderboardGroupAndAddItToTheEvent(final String leaderboardGroupName, final String regattaNameAndleaderboardName,
|
||||
final String description, final Event event) {
|
||||
final LeaderboardGroup leaderboardGroup = service.apply(new CreateLeaderboardGroup(leaderboardGroupName,
|
||||
description, null, false, Collections.singletonList(regattaNameAndleaderboardName), null, null));
|
||||
service.apply(new UpdateEvent(event.getId(), event.getName(), event.getDescription(), event.getStartDate(),
|
||||
event.getEndDate(), event.getVenue().getName(), event.isPublic(),
|
||||
Collections.singleton(leaderboardGroup.getId()), event.getOfficialWebsiteURL(), event.getBaseURL(),
|
||||
event.getSailorsInfoWebsiteURLs(), event.getImages(), event.getVideos(), event.getWindFinderReviewedSpotsCollectionIds()));
|
||||
}
|
||||
|
||||
final RaceColumn raceColumn = regattaLeaderboard.getRaceColumns().iterator().next();
|
||||
final Fleet fleet = raceColumn.getFleets().iterator().next();
|
||||
|
||||
private DynamicTrackedRace createTrackedRaceAndSetupRaceTimes(final List<ErrorImportDTO> errors,
|
||||
final String trackedRaceName, TimePoint firstFixAt, TimePoint lastFixAt, final Regatta regatta,
|
||||
final RegattaLeaderboard regattaLeaderboard, final RaceColumn raceColumn, final Fleet fleet)
|
||||
throws AllinOneImportException {
|
||||
final RaceLog raceLog = raceColumn.getRaceLog(fleet);
|
||||
|
||||
final AbstractLogEventAuthor author = service.getServerAuthor();
|
||||
|
||||
final TimePoint startOfTracking = firstFixAt;
|
||||
final TimePoint endOfTracking = lastFixAt;
|
||||
raceLog.add(new RaceLogStartOfTrackingEventImpl(startOfTracking, author, raceLog.getCurrentPassId()));
|
||||
raceLog.add(new RaceLogEndOfTrackingEventImpl(endOfTracking, author, raceLog.getCurrentPassId()));
|
||||
// TODO explicitly set startOfRace?
|
||||
|
||||
try {
|
||||
TimePoint startTrackingTimePoint = MillisecondsTimePoint.now();
|
||||
// this ensures that the events consistently have different timepoints to ensure a consistent result of the state analysis
|
||||
// that's why we can't jus call adapter.denoteRaceForRaceLogTracking
|
||||
// this ensures that the events consistently have different timepoints to ensure a consistent result of the
|
||||
// state analysis
|
||||
// that's why we can't just call adapter.denoteRaceForRaceLogTracking
|
||||
final TimePoint denotationTimePoint = startTrackingTimePoint.minus(1);
|
||||
raceLog.add(new RaceLogDenoteForTrackingEventImpl(denotationTimePoint,
|
||||
service.getServerAuthor(), raceLog.getCurrentPassId(), trackedRaceName, regatta.getBoatClass(), UUID.randomUUID()));
|
||||
|
||||
raceLog.add(new RaceLogStartTrackingEventImpl(startTrackingTimePoint, author, raceLog.getCurrentPassId()));
|
||||
|
||||
final RaceHandle raceHandle = adapter.startTracking(service, regattaLeaderboard, raceColumn, fleet,
|
||||
/* trackWind */ true, /* correctWindDirectionByMagneticDeclination */ true);
|
||||
|
||||
// wait for the RaceDefinition to be created
|
||||
raceHandle.getRace();
|
||||
|
||||
final DynamicTrackedRace trackedRace = WaitForTrackedRaceUtil.waitForTrackedRace(raceColumn, fleet, 10);
|
||||
if (trackedRace == null) {
|
||||
throw new IllegalStateException("Could not obtain imported race");
|
||||
}
|
||||
|
||||
final WindImportResult windImportResult = new AbstractWindImporter.WindImportResult();
|
||||
final WindSourceWithAdditionalID windSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION,
|
||||
windSourceId);
|
||||
final Map<InputStream, String> streamsWithFilenames = new HashMap<>();
|
||||
streamsWithFilenames.put(fileItem.getInputStream(), filenameWithSuffix);
|
||||
new WindImporter().importWindToWindSourceAndTrackedRaces(service, windImportResult, windSource,
|
||||
Arrays.asList(trackedRace), streamsWithFilenames);
|
||||
raceLog.add(new RaceLogDenoteForTrackingEventImpl(denotationTimePoint, service.getServerAuthor(),
|
||||
raceLog.getCurrentPassId(), trackedRaceName, regatta.getBoatClass(), UUID.randomUUID()));
|
||||
|
||||
return new ImporterResult(event.getId(), regattaNameAndleaderboardName, leaderboardGroupName,
|
||||
trackedRace.getRaceIdentifier(), raceColumnName, fleetName,
|
||||
jsonHolderForGpsFixImport.getImportResult(), jsonHolderForSensorFixImport.getImportResult(),
|
||||
sensorFixImporterType, errors);
|
||||
raceLog.add(new RaceLogStartTrackingEventImpl(startTrackingTimePoint, author, raceLog.getCurrentPassId()));
|
||||
|
||||
return trackRace(regattaLeaderboard, raceColumn, fleet);
|
||||
} catch (Exception e) {
|
||||
throw new AllinOneImportException(e, errors);
|
||||
}
|
||||
}
|
||||
|
||||
private DynamicTrackedRace trackRace(final RegattaLeaderboard regattaLeaderboard, final RaceColumn raceColumn,
|
||||
final Fleet fleet) throws NotDenotedForRaceLogTrackingException, Exception {
|
||||
DynamicTrackedRace trackedRace;
|
||||
final RaceHandle raceHandle = adapter.startTracking(service, regattaLeaderboard, raceColumn, fleet,
|
||||
/* trackWind */ false, /* correctWindDirectionByMagneticDeclination */ true);
|
||||
// wait for the RaceDefinition to be created
|
||||
raceHandle.getRace();
|
||||
trackedRace = WaitForTrackedRaceUtil.waitForTrackedRace(raceColumn, fleet, 10);
|
||||
if (trackedRace == null) {
|
||||
throw new IllegalStateException("Could not obtain imported race");
|
||||
}
|
||||
return trackedRace;
|
||||
}
|
||||
|
||||
private void ensureSuccessfulImport(ImportResultDTO result, String errorMessage) throws AllinOneImportException {
|
||||
if (!result.getErrorList().isEmpty()) {
|
||||
throw new AllinOneImportException(errorMessage, result.getErrorList());
|
||||
@@ -289,7 +564,7 @@ public class ExpeditionAllInOneImporter {
|
||||
|
||||
private void ensureBoatClassDetermination(Regatta regatta) throws AllinOneImportException {
|
||||
if (regatta.getBoatClass() == null) {
|
||||
throw new AllinOneImportException(ERROR_MESSAGE_BOAT_CLASS_DETERMINATION_FAILED);
|
||||
throw new AllinOneImportException(serverStringMessages.get(uiLocale, "allInOneErrorBoatClassDeterminationFailed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -50,8 +50,12 @@ class ImportResultDTO {
|
||||
private final String filename;
|
||||
private final String requestedImporter;
|
||||
|
||||
ErrorImportDTO(String name, String message) {
|
||||
this(null, name, message, null, null);
|
||||
ErrorImportDTO(String message) {
|
||||
this(null, null, message, null, null);
|
||||
}
|
||||
|
||||
ErrorImportDTO(String classname, String message) {
|
||||
this(null, classname, message, null, null);
|
||||
}
|
||||
|
||||
ErrorImportDTO(String exUUID, String name, String message, String filename, String requestedImporter) {
|
||||
|
||||
+15
@@ -8,6 +8,7 @@ import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.server.gateway.trackfiles.impl.ImportResultDTO.ErrorImportDTO;
|
||||
import com.sap.sailing.server.gateway.trackfiles.impl.ImportResultDTO.TrackImportDTO;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
|
||||
/**
|
||||
* Utility class providing convenience methods to serialize import result objects into JSON objects.
|
||||
@@ -34,6 +35,18 @@ class ImportResultSerializer {
|
||||
static JSONArray serializeErrorList(List<ErrorImportDTO> errorList) {
|
||||
return serializeList(errorList, ImportResultSerializer::serializeError);
|
||||
}
|
||||
|
||||
public static JSONArray serializeRaceList(List<Triple<String, String, String>> raceNameRaceColumnNameFleetnameList) {
|
||||
return serializeList(raceNameRaceColumnNameFleetnameList, ImportResultSerializer::serializeRaceEntry);
|
||||
}
|
||||
|
||||
private static JSONObject serializeRaceEntry(Triple<String, String, String> entry) {
|
||||
final JSONObject json = new JSONObject();
|
||||
json.put("raceName", entry.getA());
|
||||
json.put("raceColumnName", entry.getB());
|
||||
json.put("fleetName", entry.getC());
|
||||
return json;
|
||||
}
|
||||
|
||||
private static JSONObject serializeError(ErrorImportDTO error) {
|
||||
final JSONObject json = new JSONObject();
|
||||
@@ -44,4 +57,6 @@ class ImportResultSerializer {
|
||||
json.put("message", error.getMessage());
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console -clean"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dfile.encoding=cp1252 -Dexpedition.udp.port=5010 -Xmx6000m -XX:+UseG1GC -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -Dkiwo.results=${project_loc:com.sap.sailing.kiworesultimport.test}/resources -Dpersistentcompetitors.clear=false -XX:+UseMembar -Dpolardata.source.url=https://www.sapsailing.com -Drestore.tracked.races=true"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dfile.encoding=cp1252 -Dexpedition.udp.port=5010 -Xmx6000m -XX:+UseG1GC -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -Dkiwo.results=${project_loc:com.sap.sailing.kiworesultimport.test}/resources -Dpersistentcompetitors.clear=false -XX:+UseMembar -Dpolardata.source.url=https://www.sapsailing.com -Drestore.tracked.races=false"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc}"/>
|
||||
<stringAttribute key="pde.version" value="3.3"/>
|
||||
<stringAttribute key="profilingTraceType-ALLOCATION_TRACE" value="KEY_APPLICATION_FILTER%CTX_KEY%*%CTX_ENTRY%INCREASE_COUNT%CTX_KEY%8192%CTX_ENTRY%KEY_MIN_SIZE%CTX_KEY%32%CTX_ENTRY%KEY_MAX_SIZE%CTX_KEY%65536%CTX_ENTRY%KEY_INC_LINE_NRS%CTX_KEY%true%CTX_ENTRY%KEY_SESSION_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_ENABLEMENT%CTX_KEY%false%CTX_ENTRY%CLASS_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_USER_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_REQUEST_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_TENANT_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_ADAPTIVE%CTX_KEY%false%CTX_ENTRY%"/>
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
Any previously imported expedition tracks may be dropped and reimported to gain access to the newly introduced measures.</li>
|
||||
<li>The settings dialog of the competitor charts in <tt>RaceBoard.html</tt> now provides the measures in alphabetical order (based on the current locale).
|
||||
Expedition specific measures - if available - are shown at the end of the list.</li>
|
||||
<li>The all in one expedition import has been extended to be able to import new competitor tracks or new races to an existing regatta.
|
||||
Previously it was only possible to import a new event structure.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="articleSubheadline">March 2018</h2>
|
||||
|
||||
@@ -493,6 +493,15 @@ public class Util {
|
||||
return joinStrings(separator, Arrays.asList(strings));
|
||||
}
|
||||
|
||||
public static String join(String separator, Object... objects) {
|
||||
final String[] strings = new String[objects.length];
|
||||
int i=0;
|
||||
for (Object o : objects) {
|
||||
strings[i++] = o.toString();
|
||||
}
|
||||
return joinStrings(separator, Arrays.asList(strings));
|
||||
}
|
||||
|
||||
public static String joinStrings(String separator, Iterable<String> strings) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
boolean first = true;
|
||||
|
||||
@@ -63,6 +63,11 @@ public abstract class AbstractEntryPoint<S extends StringMessages> implements En
|
||||
public void reportError(String message) {
|
||||
errorReporter.reportError(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportError(String title, String message) {
|
||||
errorReporter.reportError(title, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportError(String message, boolean silentMode) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.sap.sse.gwt.client;
|
||||
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.DialogBox;
|
||||
@@ -26,6 +27,16 @@ public class DefaultErrorReporter<S extends StringMessages> implements ErrorRepo
|
||||
persistentAlertLabel.setStyleName("global-alert-message");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void reportError(String title, String message) {
|
||||
errorDialogBox.setText(title);
|
||||
serverResponseLabel.addStyleName("serverResponseLabelError"); //$NON-NLS-1$
|
||||
serverResponseLabel.setHTML(SafeHtmlUtils.fromString(message).asString() + "<br><br>");
|
||||
errorDialogBox.center();
|
||||
dialogCloseButton.setFocus(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportError(String message) {
|
||||
errorDialogBox.setText(message);
|
||||
|
||||
@@ -2,7 +2,11 @@ package com.sap.sse.gwt.client;
|
||||
|
||||
import com.google.gwt.core.client.EntryPoint;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.http.client.RequestBuilder;
|
||||
import com.google.gwt.i18n.client.LocaleInfo;
|
||||
import com.google.gwt.user.client.rpc.RpcRequestBuilder;
|
||||
import com.google.gwt.user.client.rpc.ServiceDefTarget;
|
||||
import com.sap.sse.gwt.shared.RpcConstants;
|
||||
|
||||
public class EntryPointHelper {
|
||||
/**
|
||||
@@ -18,6 +22,13 @@ public class EntryPointHelper {
|
||||
String moduleBaseURL = GWT.getModuleBaseURL();
|
||||
String baseURL = moduleBaseURL.substring(0, moduleBaseURL.lastIndexOf('/', moduleBaseURL.length()-2)+1);
|
||||
serviceToRegister.setServiceEntryPoint(baseURL + servicePath);
|
||||
serviceToRegister.setRpcRequestBuilder(new RpcRequestBuilder() {
|
||||
@Override
|
||||
protected void doFinish(RequestBuilder rb) {
|
||||
super.doFinish(rb);
|
||||
rb.setHeader(RpcConstants.HEADER_LOCALE, LocaleInfo.getCurrentLocale().getLocaleName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,8 +4,11 @@ import com.google.gwt.user.client.ui.Widget;
|
||||
|
||||
public interface ErrorReporter {
|
||||
void reportError(String message);
|
||||
void reportError(String title, String message);
|
||||
void reportError(String message, boolean silentMode);
|
||||
|
||||
void reportPersistentInformation(String message);
|
||||
|
||||
|
||||
Widget getPersistentInformationWidget();
|
||||
|
||||
}
|
||||
+19
-1
@@ -1,6 +1,7 @@
|
||||
package com.sap.sse.gwt.dispatch.servlets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -10,6 +11,7 @@ import com.google.gwt.user.client.rpc.SerializationException;
|
||||
import com.google.gwt.user.server.rpc.RPCServletUtils;
|
||||
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
|
||||
import com.google.gwt.user.server.rpc.SerializationPolicy;
|
||||
import com.sap.sse.gwt.shared.RpcConstants;
|
||||
|
||||
/**
|
||||
* Using GWT in a proxyfied environment can be tricky and leads to strange errors
|
||||
@@ -66,5 +68,21 @@ public abstract class ProxiedRemoteServiceServlet extends RemoteServiceServlet {
|
||||
} else {
|
||||
super.doUnexpectedFailure(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Locale getClientLocale() {
|
||||
final HttpServletRequest request = getThreadLocalRequest();
|
||||
if (request != null) {
|
||||
final String localeString = request.getHeader(RpcConstants.HEADER_LOCALE);
|
||||
if (localeString != null && ! localeString.isEmpty()) {
|
||||
try {
|
||||
return Locale.forLanguageTag(localeString);
|
||||
} catch (Exception e) {
|
||||
// non-parseable locales are ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
// Using default locale if the client locale could not be determined
|
||||
return Locale.ENGLISH;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.sap.sse.gwt.shared;
|
||||
|
||||
public interface RpcConstants {
|
||||
public static final String HEADER_LOCALE = "X-Client-Locale";
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.sap.sse.util.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class UUIDHelper {
|
||||
private static final Logger logger = Logger.getLogger(UUIDHelper.class.getName());
|
||||
|
||||
/**
|
||||
* 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());
|
||||
} catch (IllegalArgumentException iae) {
|
||||
logger.fine("The serializable " + serializableId.toString() + " could not be converted to a UUID");
|
||||
}
|
||||
return serializableId;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user