From 20a4933b668fc9764594d1472800b4bb22a4fe5d Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Thu, 22 Mar 2018 11:52:14 +0100 Subject: [PATCH 01/59] Bug 4371: First stub to support importing an additional competitor or importing an additional race --- .../gwt/ui/adminconsole/WindPanel.java | 35 ++- .../impl/ExpeditionAllInOneImportServlet.java | 24 +- .../impl/ExpeditionAllInOneImporter.java | 287 +++++++++++++----- 3 files changed, 270 insertions(+), 76 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index eb8e5a80712..888af9c074f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -37,6 +37,7 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CaptionPanel; import com.google.gwt.user.client.ui.CheckBox; 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.HTML; import com.google.gwt.user.client.ui.HasVerticalAlignment; @@ -44,6 +45,7 @@ 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.RadioButton; import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.TabPanel; import com.google.gwt.user.client.ui.TextBox; @@ -469,7 +471,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe Window.alert(StringMessages.INSTANCE.unexpectedErrorDuringFileImport()); } else if (response.hasEventId()) { new ExpeditionAllInOneAfterImportHandler(response.getEventId(), response.getRegattaName(), - response.getLeaderboardGroupName(), response.getLeaderboardName(), response.getRaceName(), + response.getLeaderboardName(), response.getLeaderboardGroupName(), response.getRaceName(), response.getRaceColumnName(), response.getFleetName(), response.getGpsDeviceIds(), response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService, errorReporter, stringMessages); @@ -483,6 +485,37 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe final FileUpload fileUpload = new FileUpload(); fileUpload.setName("upload"); contentPanel.add(fileUpload); + + final FlowPanel importModePanel = new FlowPanel(); + contentPanel.add(importModePanel); + final FlowPanel regattaNamePanel = new FlowPanel(); + regattaNamePanel.setVisible(false); + contentPanel.add(regattaNamePanel); + final RadioButton newEventImport = new RadioButton("importMode", "TODO new event"); + newEventImport.setFormValue("NEW_EVENT"); + newEventImport.setValue(true); + importModePanel.add(newEventImport); + newEventImport.addClickHandler(event -> { + regattaNamePanel.setVisible(false); + }); + final RadioButton newCompetitorImport = new RadioButton("importMode", "TODO new competitor"); + newCompetitorImport.setFormValue("NEW_COMPETITOR"); + importModePanel.add(newCompetitorImport); + newCompetitorImport.addClickHandler(event -> { + regattaNamePanel.setVisible(true); + }); + final RadioButton newRaceImport = new RadioButton("importMode", "TODO new race"); + newRaceImport.setFormValue("NEW_RACE"); + importModePanel.add(newRaceImport); + newRaceImport.addClickHandler(event -> { + regattaNamePanel.setVisible(true); + }); + final Label regattaNameLabel = new Label("TODO: regatta name" + ":"); + regattaNamePanel.add(regattaNameLabel); + final TextBox regattaName = new TextBox(); + regattaName.setName("regattaName"); + regattaNamePanel.add(regattaName); + final HorizontalPanel boatClassPanel = new HorizontalPanel(); boatClassPanel.setSpacing(5); contentPanel.add(boatClassPanel); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java index 11f4e3e23ec..97ca6e87975 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java @@ -17,6 +17,7 @@ import org.osgi.util.tracker.ServiceTracker; import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapterFactory; import com.sap.sailing.server.gateway.impl.AbstractFileUploadServlet; +import com.sap.sailing.server.gateway.trackfiles.impl.ExpeditionAllInOneImporter.ImportMode; import com.sap.sailing.server.gateway.trackfiles.impl.ExpeditionAllInOneImporter.ImporterResult; import com.sap.sse.util.ServiceTrackerFactory; @@ -29,8 +30,11 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { private static final Logger logger = Logger.getLogger(ExpeditionAllInOneImportServlet.class.getName()); private static final String REQUEST_PARAMETER_BOAT_CLASS = "boatClass"; + private static final String REQUEST_PARAMETER_REGATTA_NAME = "regattaName"; + private static final String REQUEST_PARAMETER_IMPORT_MODE = "importMode"; 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 ERROR_MESSAGE_UNKNOWN_IMPORT_MODE = "Unkonwn import mode!"; private ServiceTracker raceLogTrackingAdapterTracker; @@ -53,6 +57,8 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { String fileName = null; FileItem fileItem = null; String boatClassName = null; + String regattaName = null; + String importModeName = null; for (FileItem fi : fileItems) { if (!fi.isFormField()) { fileName = fi.getName(); @@ -61,6 +67,12 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { if (REQUEST_PARAMETER_BOAT_CLASS.equals(fi.getFieldName())) { boatClassName = fi.getString(); } + if (REQUEST_PARAMETER_REGATTA_NAME.equals(fi.getFieldName())) { + regattaName = fi.getString(); + } + if (REQUEST_PARAMETER_IMPORT_MODE.equals(fi.getFieldName())) { + importModeName = fi.getString(); + } } } if (fileItem == null) { @@ -69,9 +81,19 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { 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(ERROR_MESSAGE_UNKNOWN_IMPORT_MODE); + } + } importerResult = new ExpeditionAllInOneImporter(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()); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index c6feaa5d4ca..6ecbfc95a76 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -42,6 +42,8 @@ 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.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; import com.sap.sailing.domain.leaderboard.ScoringScheme; @@ -64,6 +66,7 @@ import com.sap.sailing.server.operationaltransformation.UpdateEvent; import com.sap.sailing.server.util.WaitForTrackedRaceUtil; 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.impl.MillisecondsTimePoint; @@ -78,6 +81,12 @@ public class ExpeditionAllInOneImporter { private final RaceLogTrackingAdapter adapter; private final TypeBasedServiceFinderFactory serviceFinderFactory; private final BundleContext context; + + public enum ImportMode { + NEW_EVENT, + NEW_COMPETITOR, + NEW_RACE + } public static class ImporterResult { final UUID eventId; @@ -120,33 +129,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 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; @@ -197,44 +189,197 @@ public class ExpeditionAllInOneImporter { final TimePoint eventStartDate = firstFixAt; final TimePoint eventEndDate = lastFixAt; - - final Event event = service.addEvent(eventName, description, eventStartDate, eventEndDate, venueName, true, - UUID.randomUUID()); - service.addCourseAreas(event.getId(), new String[] { courseAreaName }, new UUID[] { courseAreaId }); - - final ScoringScheme scoringScheme = service.getBaseDomainFactory().createScoringScheme(scoringSchemeType); - final LinkedHashMap seriesCreationParameters = new LinkedHashMap<>(); - final List fleets = new ArrayList<>(); - fleets.add(new FleetDTO(fleetName, 0, null)); - seriesCreationParameters.put(seriesName, - new SeriesCreationParametersDTO(fleets, /*isMedal*/ false, - /* isFleetsCanRunInParallel */ false, /*isStartsWithZeroScore*/ false, /*firstColumnIsNonDiscardableCarryForward*/false, /*discardingThresholds*/ null, - /*hasSplitFleetContiguousScoring*/ false, /*maximumNumberOfDiscards*/ null)); - final RegattaCreationParametersDTO regattaCreationParameters = new RegattaCreationParametersDTO( - seriesCreationParameters); - - final Regatta regatta = service.apply(new AddSpecificRegatta(regattaNameAndleaderboardName, boatClassName, null, 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)); + final UUID eventId; + final String leaderboardGroupName; + final String regattaNameAndleaderboardName; + final Regatta regatta; + final RegattaLeaderboard regattaLeaderboard; + // TODO Should we return all TrackedRaces? Alternatively make final when all errors are handled + DynamicTrackedRace trackedRace; + final List trackedRaces = new ArrayList<>(); + final String fleetName; + final String raceColumnName; + if (importMode == ImportMode.NEW_EVENT) { + final String eventName = filenameWithDateTimeSuffix; + final String description = MessageFormat.format("Event imported from expedition file ''{0}'' on {1}", + filenameWithSuffix, importTimeString); + // TODO guess venue based on the reverse geocoder? + final String venueName = filename; + leaderboardGroupName = filenameWithDateTimeSuffix; + regattaNameAndleaderboardName = filenameWithDateTimeSuffix; + raceColumnName = filename; + final RegattaIdentifier regattaIdentifier = new RegattaName(filenameWithDateTimeSuffix); + final String courseAreaName = "Default"; + final UUID courseAreaId = UUID.randomUUID(); + // This is just the default used in the UI + final Double buoyZoneRadiusInHullLengths = 3.0; - 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())); + fleetName = LeaderboardNameConstants.DEFAULT_FLEET_NAME; + final String seriesName = Series.DEFAULT_NAME; + + final Event event = service.addEvent(eventName, description, eventStartDate, eventEndDate, venueName, true, + UUID.randomUUID()); + eventId = event.getId(); + service.addCourseAreas(event.getId(), new String[] { courseAreaName }, new UUID[] { courseAreaId }); + + final ScoringScheme scoringScheme = service.getBaseDomainFactory().createScoringScheme(scoringSchemeType); + + final LinkedHashMap seriesCreationParameters = new LinkedHashMap<>(); + final List fleets = new ArrayList<>(); + fleets.add(new FleetDTO(fleetName, 0, null)); + seriesCreationParameters.put(seriesName, + new SeriesCreationParametersDTO(fleets, /*isMedal*/ false, + /* isFleetsCanRunInParallel */ false, /*isStartsWithZeroScore*/ false, /*firstColumnIsNonDiscardableCarryForward*/false, /*discardingThresholds*/ null, + /*hasSplitFleetContiguousScoring*/ false, /*maximumNumberOfDiscards*/ null)); + final RegattaCreationParametersDTO regattaCreationParameters = new RegattaCreationParametersDTO( + seriesCreationParameters); + + regatta = service.apply(new AddSpecificRegatta(regattaNameAndleaderboardName, boatClassName, null, null, UUID.randomUUID(), + regattaCreationParameters, true, scoringScheme, courseAreaId, buoyZoneRadiusInHullLengths, true, + false, rankingMetric)); + this.ensureBoatClassDetermination(regatta); + service.apply(new AddColumnToSeries(regattaIdentifier, seriesName, raceColumnName)); + regattaLeaderboard = service.apply(new CreateRegattaLeaderboard(regattaIdentifier, null, + discardThresholds)); + + 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(); + + trackedRace = createTrackedAndSetupRaceTimes(errors, trackedRaceName, firstFixAt, lastFixAt, regatta, regattaLeaderboard, + raceColumn, fleet); + trackedRaces.add(trackedRace); + } else { + regattaNameAndleaderboardName = existingRegattaName; + if (existingRegattaName != null && !existingRegattaName.isEmpty()) { + regatta = service.getRegattaByName(existingRegattaName); + if (regatta == null) { + // TODO error + } + final Leaderboard leaderboard = service.getLeaderboardByName(existingRegattaName); + if (leaderboard == null || !(leaderboard instanceof RegattaLeaderboard)) { + // TODO error + } + regattaLeaderboard = (RegattaLeaderboard) leaderboard; + + Event foundEvent = null; + LeaderboardGroup foundLeaderboardGroup = null; + search: for (Event event : service.getAllEvents()) { + for (LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { + for (Leaderboard lb : leaderboardGroup.getLeaderboards()) { + if (lb.equals(leaderboard)) { + foundEvent = event; + foundLeaderboardGroup = leaderboardGroup; + break search; + } + } + } + } + if (foundEvent == null) { + // TODO error? + } + eventId = foundEvent.getId(); + leaderboardGroupName = foundLeaderboardGroup.getName(); + + if (importMode == ImportMode.NEW_COMPETITOR) { + final Iterable raceColumns = regattaLeaderboard.getRaceColumns(); + if (Util.isEmpty(raceColumns)) { + // TODO error: no race to import to + } + try { + Fleet firstFleet = null; + DynamicTrackedRace firstTrackedRace = null; + RaceColumn firstRaceColumn = null; + for (RaceColumn raceColumn : raceColumns) { + final Iterable fleets = raceColumn.getFleets(); + if (Util.size(fleets) != 1) { + // TODO error: split fleet racing not supported here + } + final Fleet fleet = fleets.iterator().next(); + DynamicTrackedRace trackedRaceForColumn = (DynamicTrackedRace) raceColumn.getTrackedRace(fleet); + if (trackedRaceForColumn == null) { + trackedRaceForColumn = trackRace(regattaLeaderboard, raceColumn, fleet); + } + trackedRaces.add(trackedRaceForColumn); + if (firstTrackedRace == null) { + firstTrackedRace = trackedRaceForColumn; + firstFleet = fleet; + firstRaceColumn = raceColumn; + } + } + // TODO we remember the first trackedRace for now. Should we remember all? + trackedRace = firstTrackedRace; + fleetName = firstFleet.getName(); + raceColumnName = firstRaceColumn.getName(); + } catch (Exception e) { + throw new AllinOneImportException(e, errors); + } + } else { + // ImportMode.NEW_RACE + final Iterable seriesInRegatta = regatta.getSeries(); + if (Util.isEmpty(seriesInRegatta)) { + // TODO error + } + final Series series = Util.get(seriesInRegatta, Util.size(seriesInRegatta) - 1); + final Iterable fleets = series.getFleets(); + if (Util.size(fleets) != 1) { + // TODO error + } + final Fleet fleet = fleets.iterator().next(); + fleetName = fleet.getName(); + // When uploading files with identical name, the second RaceColumn will be named with the upload time in its name + raceColumnName = regatta.getRaceColumnByName(filename) == null ? filename : filenameWithDateTimeSuffix; + final RaceColumn raceColumn = service.apply(new AddColumnToSeries(regatta.getRegattaIdentifier(), series.getName(), raceColumnName)); - final RaceColumn raceColumn = regattaLeaderboard.getRaceColumns().iterator().next(); - final Fleet fleet = raceColumn.getFleets().iterator().next(); + trackedRace = createTrackedAndSetupRaceTimes(errors, trackedRaceName, firstFixAt, lastFixAt, regatta, regattaLeaderboard, + raceColumn, fleet); + trackedRaces.add(trackedRace); + } + } else { + // TODO error + + // TODO remove when all errors are handled -> it should be assigned in all code paths that do not result in an error + eventId = null; + leaderboardGroupName = null; + trackedRace = null; + fleetName = null; + raceColumnName = null; + } + } + try { + final WindImportResult windImportResult = new AbstractWindImporter.WindImportResult(); + final WindSourceWithAdditionalID windSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION, + windSourceId); + final Map streamsWithFilenames = new HashMap<>(); + streamsWithFilenames.put(fileItem.getInputStream(), filenameWithSuffix); + new WindImporter().importWindToWindSourceAndTrackedRaces(service, windImportResult, windSource, + trackedRaces, streamsWithFilenames); + + return new ImporterResult(eventId, regattaNameAndleaderboardName, leaderboardGroupName, + trackedRace.getRaceIdentifier(), raceColumnName, fleetName, + jsonHolderForGpsFixImport.getImportResult(), jsonHolderForSensorFixImport.getImportResult(), + sensorFixImporterType, errors); + } catch (Exception e) { + throw new AllinOneImportException(e, errors); + } + } + + private DynamicTrackedRace createTrackedAndSetupRaceTimes(final List 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())); @@ -244,41 +389,35 @@ public class ExpeditionAllInOneImporter { 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 + // 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 streamsWithFilenames = new HashMap<>(); - streamsWithFilenames.put(fileItem.getInputStream(), filenameWithSuffix); - new WindImporter().importWindToWindSourceAndTrackedRaces(service, windImportResult, windSource, - Arrays.asList(trackedRace), streamsWithFilenames); - - return new ImporterResult(event.getId(), regattaNameAndleaderboardName, leaderboardGroupName, - trackedRace.getRaceIdentifier(), raceColumnName, fleetName, - jsonHolderForGpsFixImport.getImportResult(), jsonHolderForSensorFixImport.getImportResult(), - sensorFixImporterType, errors); + 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 */ true, /* 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()); From 439e4680ef7c0399e2e6adfcfc5b4f453d8ad7f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Thu, 5 Apr 2018 14:36:51 +0200 Subject: [PATCH 02/59] bug4371 added error handling --- .../impl/ExpeditionAllInOneImporter.java | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 6ecbfc95a76..d7173dda106 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -81,7 +81,7 @@ public class ExpeditionAllInOneImporter { private final RaceLogTrackingAdapter adapter; private final TypeBasedServiceFinderFactory serviceFinderFactory; private final BundleContext context; - + public enum ImportMode { NEW_EVENT, NEW_COMPETITOR, @@ -95,10 +95,19 @@ public class ExpeditionAllInOneImporter { final String sensorFixImporterType; final List errorList = new ArrayList<>(); - public ImporterResult(Throwable exception, List additionalErrors) { + public ImporterResult(String error, List additionalErrors) { this(null, "", "", new RegattaNameAndRaceName("", ""), "", "", Collections.emptyList(), Collections.emptyList(), "", additionalErrors); - this.errorList.add(new ErrorImportDTO(exception.getClass().getName(), exception.getMessage())); + errorList.add(new ErrorImportDTO("Import Error", error)); + } + + public ImporterResult(Throwable exception, List additionalErrors) { + this(null, "", "", new RegattaNameAndRaceName("", ""), "", "", 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, @@ -261,11 +270,11 @@ public class ExpeditionAllInOneImporter { if (existingRegattaName != null && !existingRegattaName.isEmpty()) { regatta = service.getRegattaByName(existingRegattaName); if (regatta == null) { - // TODO error + return new ImporterResult("The regatta could not be resolved, please ensure the name is correct", null); } final Leaderboard leaderboard = service.getLeaderboardByName(existingRegattaName); if (leaderboard == null || !(leaderboard instanceof RegattaLeaderboard)) { - // TODO error + return new ImporterResult("The Leaderboard could not be resolved, please ensure a leaderboard named like the regatta exists", null); } regattaLeaderboard = (RegattaLeaderboard) leaderboard; @@ -283,7 +292,7 @@ public class ExpeditionAllInOneImporter { } } if (foundEvent == null) { - // TODO error? + return new ImporterResult("The Event for the leaderboard could not be obtained, please ensure the leaderboard is properly attached to an leaderboardgroup that is attached to an event", null); } eventId = foundEvent.getId(); leaderboardGroupName = foundLeaderboardGroup.getName(); @@ -291,7 +300,7 @@ public class ExpeditionAllInOneImporter { if (importMode == ImportMode.NEW_COMPETITOR) { final Iterable raceColumns = regattaLeaderboard.getRaceColumns(); if (Util.isEmpty(raceColumns)) { - // TODO error: no race to import to + return new ImporterResult("To add competitors, a race must be existing", null); } try { Fleet firstFleet = null; @@ -300,7 +309,7 @@ public class ExpeditionAllInOneImporter { for (RaceColumn raceColumn : raceColumns) { final Iterable fleets = raceColumn.getFleets(); if (Util.size(fleets) != 1) { - // TODO error: split fleet racing not supported here + return new ImporterResult("The expedition importer, cannot handle split fleet racing", null); } final Fleet fleet = fleets.iterator().next(); DynamicTrackedRace trackedRaceForColumn = (DynamicTrackedRace) raceColumn.getTrackedRace(fleet); @@ -325,12 +334,12 @@ public class ExpeditionAllInOneImporter { // ImportMode.NEW_RACE final Iterable seriesInRegatta = regatta.getSeries(); if (Util.isEmpty(seriesInRegatta)) { - // TODO error + return new ImporterResult("There is no series in this regatta, cannot add race", null); } final Series series = Util.get(seriesInRegatta, Util.size(seriesInRegatta) - 1); final Iterable fleets = series.getFleets(); if (Util.size(fleets) != 1) { - // TODO error + return new ImporterResult("There is more than one series in this regatta, cannot add race", null); } final Fleet fleet = fleets.iterator().next(); fleetName = fleet.getName(); @@ -343,14 +352,7 @@ public class ExpeditionAllInOneImporter { trackedRaces.add(trackedRace); } } else { - // TODO error - - // TODO remove when all errors are handled -> it should be assigned in all code paths that do not result in an error - eventId = null; - leaderboardGroupName = null; - trackedRace = null; - fleetName = null; - raceColumnName = null; + return new ImporterResult("Please enter a valid regatta name to proceed", null); } } @@ -372,14 +374,14 @@ public class ExpeditionAllInOneImporter { } } - private DynamicTrackedRace createTrackedAndSetupRaceTimes(final List errors, final String trackedRaceName, - TimePoint firstFixAt, TimePoint lastFixAt, final Regatta regatta, + private DynamicTrackedRace createTrackedAndSetupRaceTimes(final List 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())); @@ -388,14 +390,15 @@ public class ExpeditionAllInOneImporter { try { TimePoint startTrackingTimePoint = MillisecondsTimePoint.now(); - // this ensures that the events consistently have different timepoints to ensure a consistent result of the state analysis + // 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 RaceLogDenoteForTrackingEventImpl(denotationTimePoint, service.getServerAuthor(), + raceLog.getCurrentPassId(), trackedRaceName, regatta.getBoatClass(), UUID.randomUUID())); + raceLog.add(new RaceLogStartTrackingEventImpl(startTrackingTimePoint, author, raceLog.getCurrentPassId())); - + return trackRace(regattaLeaderboard, raceColumn, fleet); } catch (Exception e) { throw new AllinOneImportException(e, errors); @@ -407,10 +410,10 @@ public class ExpeditionAllInOneImporter { DynamicTrackedRace trackedRace; final RaceHandle raceHandle = adapter.startTracking(service, regattaLeaderboard, raceColumn, fleet, /* trackWind */ true, /* 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"); From ba4c733ea057c80db5e7ccd92a2a76394984fa63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Thu, 5 Apr 2018 15:16:03 +0200 Subject: [PATCH 03/59] fixed error handling --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index d7173dda106..00fd3504dd6 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -97,8 +97,11 @@ public class ExpeditionAllInOneImporter { public ImporterResult(String error, List additionalErrors) { this(null, "", "", new RegattaNameAndRaceName("", ""), "", "", Collections.emptyList(), - Collections.emptyList(), "", additionalErrors); + Collections.emptyList(), "", Collections.emptyList()); errorList.add(new ErrorImportDTO("Import Error", error)); + if (additionalErrors != null) { + errorList.addAll(additionalErrors); + } } public ImporterResult(Throwable exception, List additionalErrors) { From f6bbce15a4014b4ad23543979f0af8fd77c8ae5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Fri, 6 Apr 2018 17:36:15 +0200 Subject: [PATCH 04/59] extracted constants, improved messages, added suggests for regattas, improved error handling --- .../dto/ExpeditionAllInOneConstants.java | 13 ++ .../gwt/ui/adminconsole/WindPanel.java | 116 ++++++++++++++++-- .../sailing/gwt/ui/client/StringMessages.java | 2 + .../gwt/ui/client/StringMessages.properties | 4 +- .../ui/client/StringMessages_de.properties | 4 +- .../impl/ExpeditionAllInOneImportServlet.java | 14 +-- .../impl/ExpeditionAllInOneImporter.java | 52 +++++--- .../trackfiles/impl/ImportResultDTO.java | 8 +- 8 files changed, 170 insertions(+), 43 deletions(-) create mode 100644 java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/ExpeditionAllInOneConstants.java diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/ExpeditionAllInOneConstants.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/ExpeditionAllInOneConstants.java new file mode 100644 index 00000000000..ac11b79ee99 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/ExpeditionAllInOneConstants.java @@ -0,0 +1,13 @@ +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 enum ImportMode{ + NEW_COMPETITOR, NEW_EVENT, NEW_RACE; + } + + private ExpeditionAllInOneConstants() { + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index 888af9c074f..575191e1c8e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -17,6 +17,8 @@ import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.logical.shared.SelectionEvent; +import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.i18n.client.NumberFormat; @@ -44,9 +46,12 @@ 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.MultiWordSuggestOracle; import com.google.gwt.user.client.ui.Panel; 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.TabPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; @@ -55,6 +60,7 @@ import com.google.gwt.view.client.SelectionChangeEvent; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.WindSourceType; +import com.sap.sailing.domain.common.dto.ExpeditionAllInOneConstants; 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; @@ -89,7 +95,6 @@ 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"; @@ -120,6 +125,13 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe private final CellTable rawWindFixesTable; private final VerticalPanel windFixPanel; + private RadioButton newEventImport; + private RadioButton newCompetitorImport; + private RadioButton newRaceImport; + private SuggestBox regatttaSuggestBox; + private SuggestBox boatClassInput; + private MultiWordSuggestOracle regattaOracle; + public WindPanel(final SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, ErrorReporter errorReporter, RegattaRefresher regattaRefresher, final StringMessages stringMessages) { ensureDebugId("WindPanel"); @@ -132,7 +144,6 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe VerticalPanel mainPanel = new VerticalPanel(); mainPanel.setSize("100%", "100%"); this.setWidget(mainPanel); - trackedRacesListComposite = new TrackedRacesListComposite(null, null, sailingService, errorReporter, regattaRefresher, stringMessages, /*multiselection*/true, /* actionButtonsEnabled */ false); @@ -146,6 +157,8 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe } }); + regattaOracle = new MultiWordSuggestOracle(". _"); + windCaptionPanel = new CaptionPanel(stringMessages.wind()); windCaptionPanel.setVisible(false); mainPanel.add(windCaptionPanel); @@ -475,6 +488,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe response.getRaceColumnName(), response.getFleetName(), response.getGpsDeviceIds(), response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService, errorReporter, stringMessages); + refreshRegattaOracle(); } else { ExpeditionDataImportResultsDialog.showResults(response); } @@ -491,38 +505,56 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe final FlowPanel regattaNamePanel = new FlowPanel(); regattaNamePanel.setVisible(false); contentPanel.add(regattaNamePanel); - final RadioButton newEventImport = new RadioButton("importMode", "TODO new event"); + newEventImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.createNewEvent()); newEventImport.setFormValue("NEW_EVENT"); newEventImport.setValue(true); importModePanel.add(newEventImport); newEventImport.addClickHandler(event -> { regattaNamePanel.setVisible(false); + boatClassInput.setEnabled(true); + boatClassInput.setValue(null); }); - final RadioButton newCompetitorImport = new RadioButton("importMode", "TODO new competitor"); - newCompetitorImport.setFormValue("NEW_COMPETITOR"); + 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); + regatttaSuggestBox.setEnabled(true); + regatttaSuggestBox.setValue(null); + boatClassInput.setEnabled(false); }); - final RadioButton newRaceImport = new RadioButton("importMode", "TODO new race"); - newRaceImport.setFormValue("NEW_RACE"); + 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); + regatttaSuggestBox.setEnabled(true); + regatttaSuggestBox.setValue(null); + boatClassInput.setEnabled(false); }); - final Label regattaNameLabel = new Label("TODO: regatta name" + ":"); + + fileUpload.addChangeHandler(new ChangeHandler() { + @Override + public void onChange(ChangeEvent event) { + enableExpeditionRadios(fileUpload.getFilename() != null); + } + }); + + final Label regattaNameLabel = new Label(stringMessages.regattaName()); regattaNamePanel.add(regattaNameLabel); final TextBox regattaName = new TextBox(); regattaName.setName("regattaName"); - regattaNamePanel.add(regattaName); - + + refreshRegattaOracle(); + regatttaSuggestBox = new SuggestBox(regattaOracle , regattaName); + regattaNamePanel.add(regatttaSuggestBox); 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 = new SuggestBox(new BoatClassMasterdataSuggestOracle()); boatClassInput.getValueBox().setName(EXPEDITON_IMPORT_PARAMETER_BOAT_CLASS); boatClassPanel.add(boatClassInput); boatClassPanel.setCellVerticalAlignment(boatClassInput, HasVerticalAlignment.ALIGN_MIDDLE); @@ -531,6 +563,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe 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(); @@ -538,13 +571,74 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe uploadButton.setEnabled(fileValid && boatClassValid); }; + regatttaSuggestBox.addSelectionHandler(new SelectionHandler() { + + @Override + public void onSelection(SelectionEvent event) { + final String selected = event.getSelectedItem().getReplacementString(); + if (selected != null) { + sailingService.getRegattaByName(selected, new AsyncCallback() { + @Override + public void onSuccess(RegattaDTO result) { + boatClassInput.setEnabled(true); + if (result.boatClass != null) { + boatClassInput.setValue(result.boatClass.getName(), true); + validation.run(); + } + } + + @Override + public void onFailure(Throwable caught) { + boatClassInput.setEnabled(true); + errorReporter.reportError("Could not determine Regatta " + selected); + } + }); + } + } + }); + + fileUpload.addChangeHandler(event -> validation.run()); boatClassInput.addSelectionHandler(event -> validation.run()); boatClassInput.addKeyUpHandler(event -> validation.run()); validation.run(); + + enableExpeditionRadios(false); return rootPanel; } + protected void enableExpeditionRadios(boolean b) { + newCompetitorImport.setEnabled(b); + newEventImport.setEnabled(b); + newRaceImport.setEnabled(b); + if(!b) { + //also prevent later stages + regatttaSuggestBox.setEnabled(false); + boatClassInput.setEnabled(false); + } else { + //set consistent start scenario after choosing different file + newEventImport.setValue(true); + boatClassInput.setEnabled(true); + boatClassInput.setValue(null); + } + } + + private void refreshRegattaOracle() { + sailingService.getRegattas(new AsyncCallback>() { + @Override + public void onSuccess(List result) { + regattaOracle.clear(); + for (RegattaDTO regatta : result) { + regattaOracle.add(regatta.getName()); + } + } + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Could not load regattanames " + caught.getMessage()); + } + }); + } + private CaptionPanel createExpeditionWindImportPanel() { /* * To style the "browse" button of the file upload widget diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 203ce57c7bd..44e0c48d690 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -2068,4 +2068,6 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String windFinderWeatherData(); String positionEditOnNonTrackingRace(); String errorCreatingLeaderboardGroup(String name); + String newExpeditionRace(); + String newExpeditionCompetitor(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 76d99e243d5..47156c08be3 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -2055,4 +2055,6 @@ enterTagsForTheImage=Enter tags for the image unableToResolveWindFinderSpotId=Unable to resolve WindFinder spot with ID {0}: {1} windFinderWeatherData=Weather Data positionEditOnNonTrackingRace=This race is currently not tracked, fix updates are no longer received by the TrackedRace! Is is necessary to reload the race, to see the changes. -errorCreatingLeaderboardGroup=Error trying to create new leaderboard group {0} \ No newline at end of file +errorCreatingLeaderboardGroup=Error trying to create new leaderboard group {0} +newExpeditionRace=Create a new race +newExpeditionCompetitor=Add a new Competitor \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index cdc1bc3ae8e..7f1f7b2b2dc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -2052,4 +2052,6 @@ enterTagsForTheImage=Tags zum Bild erfassen unableToResolveWindFinderSpotId=WindFinder-Station mit Kennung {0} wurde nicht gefunden: {1} windFinderWeatherData=Wetter​daten positionEditOnNonTrackingRace=Dieses Rennen wird derzeit nicht getracked, Fixänderungen werden nicht vom TrackedRace empfangen. Es ist notwendig das Rennen neu zu laden, um die Änderungen zu sehen. -errorCreatingLeaderboardGroup=Fehler bei dem Versuch eine neue Leaderboardgruppe {0} anzulegen \ No newline at end of file +errorCreatingLeaderboardGroup=Fehler bei dem Versuch eine neue Leaderboardgruppe {0} anzulegen +newExpeditionRace=Neues Rennen anlegen +newExpeditionCompetitor=Neuen Competitor hinzufügen \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java index 97ca6e87975..b7f32866434 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java @@ -15,9 +15,10 @@ 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.ImportMode; import com.sap.sailing.server.gateway.trackfiles.impl.ExpeditionAllInOneImporter.ImporterResult; import com.sap.sse.util.ServiceTrackerFactory; @@ -29,12 +30,9 @@ 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 REQUEST_PARAMETER_REGATTA_NAME = "regattaName"; - private static final String REQUEST_PARAMETER_IMPORT_MODE = "importMode"; 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 ERROR_MESSAGE_UNKNOWN_IMPORT_MODE = "Unkonwn import mode!"; + private static final String ERROR_MESSAGE_UNKNOWN_IMPORT_MODE = "Unknown import mode!"; private ServiceTracker raceLogTrackingAdapterTracker; @@ -64,13 +62,13 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { 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 (REQUEST_PARAMETER_REGATTA_NAME.equals(fi.getFieldName())) { + if (ExpeditionAllInOneConstants.REQUEST_PARAMETER_REGATTA_NAME.equals(fi.getFieldName())) { regattaName = fi.getString(); } - if (REQUEST_PARAMETER_IMPORT_MODE.equals(fi.getFieldName())) { + if (ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE.equals(fi.getFieldName())) { importModeName = fi.getString(); } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 00fd3504dd6..418a03b6f67 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -38,6 +38,7 @@ 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.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; @@ -71,6 +72,24 @@ import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class ExpeditionAllInOneImporter { + private static final String ERROR_MESSAGE_INVALID_REGATTA_NAME = "Please enter a valid regatta name to proceed"; + + private static final String ERROR_MESSAGE_INVALID_IMPORTMODE = "Currently not handled ImportMode "; + + private static final String ERROR_MESSAGE_MULTI_SERIES = "There is more than one series in this regatta, cannot add race"; + + private static final String ERROR_MESSAGE_INVALID_SERIES = "There is no series in this regatta, cannot add race"; + + private static final String ERROR_MESSAGE_SPLITFLEET_NOT_SUPPORTED = "The expedition importer, cannot handle split fleet racing"; + + private static final String ERROR_MESSAGE_INVALID_RACE = "To add competitors, a race must be existing"; + + private static final String ERROR_MESSAGE_INVALID_LEADERBOARD_EVENT_LINK = "The Event for the leaderboard could not be obtained, please ensure the leaderboard is properly attached to an leaderboardgroup that is attached to an event"; + + private static final String ERROR_MESSAGE_INVALID_LEADERBOARD = "The Leaderboard could not be resolved, please ensure a leaderboard named like the regatta exists"; + + private static final String ERROR_MESSAGE_INVALID_REGATTA = "The regatta could not be resolved, please ensure the name is correct"; + 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!"; @@ -82,12 +101,6 @@ public class ExpeditionAllInOneImporter { private final TypeBasedServiceFinderFactory serviceFinderFactory; private final BundleContext context; - public enum ImportMode { - NEW_EVENT, - NEW_COMPETITOR, - NEW_RACE - } - public static class ImporterResult { final UUID eventId; final String leaderboardName, leaderboardGroupName, regattaName, raceName, raceColumnName, fleetName; @@ -95,13 +108,10 @@ public class ExpeditionAllInOneImporter { final String sensorFixImporterType; final List errorList = new ArrayList<>(); - public ImporterResult(String error, List additionalErrors) { + public ImporterResult(String error) { this(null, "", "", new RegattaNameAndRaceName("", ""), "", "", Collections.emptyList(), Collections.emptyList(), "", Collections.emptyList()); - errorList.add(new ErrorImportDTO("Import Error", error)); - if (additionalErrors != null) { - errorList.addAll(additionalErrors); - } + errorList.add(new ErrorImportDTO(error)); } public ImporterResult(Throwable exception, List additionalErrors) { @@ -273,11 +283,11 @@ public class ExpeditionAllInOneImporter { if (existingRegattaName != null && !existingRegattaName.isEmpty()) { regatta = service.getRegattaByName(existingRegattaName); if (regatta == null) { - return new ImporterResult("The regatta could not be resolved, please ensure the name is correct", null); + return new ImporterResult(ERROR_MESSAGE_INVALID_REGATTA); } final Leaderboard leaderboard = service.getLeaderboardByName(existingRegattaName); if (leaderboard == null || !(leaderboard instanceof RegattaLeaderboard)) { - return new ImporterResult("The Leaderboard could not be resolved, please ensure a leaderboard named like the regatta exists", null); + return new ImporterResult(ERROR_MESSAGE_INVALID_LEADERBOARD); } regattaLeaderboard = (RegattaLeaderboard) leaderboard; @@ -295,7 +305,7 @@ public class ExpeditionAllInOneImporter { } } if (foundEvent == null) { - return new ImporterResult("The Event for the leaderboard could not be obtained, please ensure the leaderboard is properly attached to an leaderboardgroup that is attached to an event", null); + return new ImporterResult(ERROR_MESSAGE_INVALID_LEADERBOARD_EVENT_LINK); } eventId = foundEvent.getId(); leaderboardGroupName = foundLeaderboardGroup.getName(); @@ -303,7 +313,7 @@ public class ExpeditionAllInOneImporter { if (importMode == ImportMode.NEW_COMPETITOR) { final Iterable raceColumns = regattaLeaderboard.getRaceColumns(); if (Util.isEmpty(raceColumns)) { - return new ImporterResult("To add competitors, a race must be existing", null); + return new ImporterResult(ERROR_MESSAGE_INVALID_RACE); } try { Fleet firstFleet = null; @@ -312,7 +322,7 @@ public class ExpeditionAllInOneImporter { for (RaceColumn raceColumn : raceColumns) { final Iterable fleets = raceColumn.getFleets(); if (Util.size(fleets) != 1) { - return new ImporterResult("The expedition importer, cannot handle split fleet racing", null); + return new ImporterResult(ERROR_MESSAGE_SPLITFLEET_NOT_SUPPORTED); } final Fleet fleet = fleets.iterator().next(); DynamicTrackedRace trackedRaceForColumn = (DynamicTrackedRace) raceColumn.getTrackedRace(fleet); @@ -333,16 +343,16 @@ public class ExpeditionAllInOneImporter { } catch (Exception e) { throw new AllinOneImportException(e, errors); } - } else { + } else if (importMode == ImportMode.NEW_RACE){ // ImportMode.NEW_RACE final Iterable seriesInRegatta = regatta.getSeries(); if (Util.isEmpty(seriesInRegatta)) { - return new ImporterResult("There is no series in this regatta, cannot add race", null); + return new ImporterResult(ERROR_MESSAGE_INVALID_SERIES); } final Series series = Util.get(seriesInRegatta, Util.size(seriesInRegatta) - 1); final Iterable fleets = series.getFleets(); if (Util.size(fleets) != 1) { - return new ImporterResult("There is more than one series in this regatta, cannot add race", null); + return new ImporterResult(ERROR_MESSAGE_MULTI_SERIES); } final Fleet fleet = fleets.iterator().next(); fleetName = fleet.getName(); @@ -353,9 +363,11 @@ public class ExpeditionAllInOneImporter { trackedRace = createTrackedAndSetupRaceTimes(errors, trackedRaceName, firstFixAt, lastFixAt, regatta, regattaLeaderboard, raceColumn, fleet); trackedRaces.add(trackedRace); + } else { + return new ImporterResult(ERROR_MESSAGE_INVALID_IMPORTMODE + importMode); } } else { - return new ImporterResult("Please enter a valid regatta name to proceed", null); + return new ImporterResult(ERROR_MESSAGE_INVALID_REGATTA_NAME); } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ImportResultDTO.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ImportResultDTO.java index a27a274aae7..2f39536c11f 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ImportResultDTO.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ImportResultDTO.java @@ -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) { From 55d9c338e361043d2518d69f2a1aab5b0e8d3040 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Tue, 10 Apr 2018 09:00:16 +0200 Subject: [PATCH 05/59] Bug 4371: Deactivated autocomplete for the expedition all in one import fields --- .../main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index 575191e1c8e..608b135fbad 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -468,6 +468,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe 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); From 9e756586f41c43d0e478c5d46d5bcd68d30aea33 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Tue, 10 Apr 2018 17:30:00 +0200 Subject: [PATCH 06/59] Bug 4371: Implemented simplifications of the competitor mapping workflow by evaluating the selection in the competitor registration dialog --- .../CompetitorRegistrationsPanel.java | 6 ++ .../ExpeditionAllInOneAfterImportHandler.java | 88 ++++++++++++++----- ...egattaLogCompetitorRegistrationDialog.java | 11 ++- 3 files changed, 81 insertions(+), 24 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java index d324b1a7519..a362b9a44e2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java @@ -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 competitorsImported) { allCompetitorsTable.getFilterField().removeAll(competitorsImported); registeredCompetitorsTable.getFilterField().addAll(competitorsImported); + validateAndUpdate(); } private void moveSelected(CompetitorTableWrapper> from, @@ -319,4 +321,8 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl public void moveFromPoolToRegistered(Collection registeredCompetitors) { move(allCompetitorsTable, registeredCompetitorsTable, registeredCompetitors); } + + public Set getSelectedRegisteredCompetitors() { + return registeredCompetitorsTable.getSelectionModel().getSelectedSet(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java index 6bc6e4a358a..4ee90273613 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java @@ -23,6 +23,7 @@ import com.sap.sse.common.Util; 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; public class ExpeditionAllInOneAfterImportHandler { @@ -89,32 +90,73 @@ 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(), + 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> { + private CompetitorRegistrationsPanel competitorRegistrationsPanel; + @Override + public String getErrorMessage(Set valueToValidate) { + if (competitorRegistrationsPanel == null || competitorRegistrationsPanel.getSelectedRegisteredCompetitors().size() != 1) { + return "TODO: select one competitor in the left table"; + } + return null; + } + public void setCompetitorRegistrationsPanel(CompetitorRegistrationsPanel competitorRegistrationsPanel) { + this.competitorRegistrationsPanel = competitorRegistrationsPanel; + } + } + + private class CallbackForCompetitorRegistrationDialog extends CancelImportDialogCallback> { + private CompetitorRegistrationsPanel competitorRegistrationsPanel; + + @Override + public void ok(Set competitors) { + if (competitors.isEmpty()) { + Window.alert(stringMessages.importCanceledNoCompetitorAdded()); + } else { + sailingService.setCompetitorRegistrationsInRegattaLog(leaderboard.getName(), + competitors, new AsyncCallback() { + @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>() { - @Override - public void ok(final Set competitors) { - if (competitors.isEmpty()) { - Window.alert(stringMessages.importCanceledNoCompetitorAdded()); - } else { - sailingService.setCompetitorRegistrationsInRegattaLog(leaderboard.getName(), - competitors, new AsyncCallback() { - @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 mappedCompetitors) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java index bd79b45613f..22122cb82c5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java @@ -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> 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> validator, + com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback> callback) { + super(sailingService, stringMessages, errorReporter, editable, callback, leaderboardName, + canBoatsOfCompetitorsChangePerRace, boatClass, stringMessages.save(), validator); } @Override From aa7ce81c4b834c4b49499c915a7ea31d6b3c49e1 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 11 Apr 2018 13:02:58 +0200 Subject: [PATCH 07/59] Bug 4371: Improved validation and not asking for a boat class when importing expedition data to an existing regatta --- .../gwt/ui/adminconsole/WindPanel.java | 68 +++++++++---------- .../impl/ExpeditionAllInOneImportServlet.java | 13 +++- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index 608b135fbad..eb3fe678eae 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -477,23 +477,6 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe 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.getLeaderboardName(), response.getLeaderboardGroupName(), response.getRaceName(), - response.getRaceColumnName(), response.getFleetName(), response.getGpsDeviceIds(), - response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService, - errorReporter, stringMessages); - refreshRegattaOracle(); - } else { - ExpeditionDataImportResultsDialog.showResults(response); - } - }); rootPanel.add(formPanel); final VerticalPanel contentPanel = new VerticalPanel(); formPanel.add(contentPanel); @@ -505,6 +488,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe contentPanel.add(importModePanel); final FlowPanel regattaNamePanel = new FlowPanel(); regattaNamePanel.setVisible(false); + final HorizontalPanel boatClassPanel = new HorizontalPanel(); contentPanel.add(regattaNamePanel); newEventImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.createNewEvent()); newEventImport.setFormValue("NEW_EVENT"); @@ -512,8 +496,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe importModePanel.add(newEventImport); newEventImport.addClickHandler(event -> { regattaNamePanel.setVisible(false); - boatClassInput.setEnabled(true); - boatClassInput.setValue(null); + boatClassPanel.setVisible(true); }); newCompetitorImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.newExpeditionCompetitor()); newCompetitorImport.setFormValue(ExpeditionAllInOneConstants.ImportMode.NEW_COMPETITOR.name()); @@ -522,7 +505,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe regattaNamePanel.setVisible(true); regatttaSuggestBox.setEnabled(true); regatttaSuggestBox.setValue(null); - boatClassInput.setEnabled(false); + boatClassPanel.setVisible(false); }); newRaceImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.newExpeditionRace()); newRaceImport.setFormValue(ExpeditionAllInOneConstants.ImportMode.NEW_RACE.name()); @@ -531,7 +514,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe regattaNamePanel.setVisible(true); regatttaSuggestBox.setEnabled(true); regatttaSuggestBox.setValue(null); - boatClassInput.setEnabled(false); + boatClassPanel.setVisible(false); }); fileUpload.addChangeHandler(new ChangeHandler() { @@ -549,7 +532,6 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe refreshRegattaOracle(); regatttaSuggestBox = new SuggestBox(regattaOracle , regattaName); regattaNamePanel.add(regatttaSuggestBox); - final HorizontalPanel boatClassPanel = new HorizontalPanel(); boatClassPanel.setSpacing(5); contentPanel.add(boatClassPanel); final Label boatClassLabel = new Label(stringMessages.boatClass() + ":"); @@ -567,13 +549,33 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe final Runnable validation = () -> { final String filename = fileUpload.getFilename(), boatClass = boatClassInput.getValue(); + final String regattaNameValue = regatttaSuggestBox.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(); - uploadButton.setEnabled(fileValid && boatClassValid); + final boolean regattaNameValid = regattaNameValue != null && !regattaNameValue.trim().isEmpty(); + uploadButton.setEnabled(fileValid && (isNewEventImport ? boatClassValid : regattaNameValid)); }; + + 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.getRaceName(), + response.getRaceColumnName(), response.getFleetName(), response.getGpsDeviceIds(), + response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService, + errorReporter, stringMessages); + refreshRegattaOracle(); + } else { + ExpeditionDataImportResultsDialog.showResults(response); + } + }); regatttaSuggestBox.addSelectionHandler(new SelectionHandler() { - @Override public void onSelection(SelectionEvent event) { final String selected = event.getSelectedItem().getReplacementString(); @@ -581,23 +583,18 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe sailingService.getRegattaByName(selected, new AsyncCallback() { @Override public void onSuccess(RegattaDTO result) { - boatClassInput.setEnabled(true); - if (result.boatClass != null) { - boatClassInput.setValue(result.boatClass.getName(), true); - validation.run(); - } + validation.run(); } @Override public void onFailure(Throwable caught) { - boatClassInput.setEnabled(true); errorReporter.reportError("Could not determine Regatta " + selected); } }); } } }); - + regatttaSuggestBox.addKeyUpHandler(event -> validation.run()); fileUpload.addChangeHandler(event -> validation.run()); boatClassInput.addSelectionHandler(event -> validation.run()); @@ -612,14 +609,11 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe newCompetitorImport.setEnabled(b); newEventImport.setEnabled(b); newRaceImport.setEnabled(b); - if(!b) { - //also prevent later stages - regatttaSuggestBox.setEnabled(false); - boatClassInput.setEnabled(false); - } else { + regatttaSuggestBox.setEnabled(b); + boatClassInput.setEnabled(b); + if(b) { //set consistent start scenario after choosing different file newEventImport.setValue(true); - boatClassInput.setEnabled(true); boatClassInput.setValue(null); } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java index b7f32866434..1d6fced99a5 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java @@ -32,6 +32,7 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { 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 ERROR_MESSAGE_REGATTA_MISSING = "No regatta name found!"; private static final String ERROR_MESSAGE_UNKNOWN_IMPORT_MODE = "Unknown import mode!"; private ServiceTracker raceLogTrackingAdapterTracker; @@ -76,9 +77,6 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { if (fileItem == null) { throw new AllinOneImportException(ERROR_MESSAGE_IMPORT_FILE_MISSING); } - if (boatClassName == null || boatClassName.isEmpty()) { - throw new AllinOneImportException(ERROR_MESSAGE_BOAT_CLASS_MISSING); - } final ImportMode importMode; if (importModeName == null) { importMode = ImportMode.NEW_EVENT; @@ -89,6 +87,15 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { throw new AllinOneImportException(ERROR_MESSAGE_UNKNOWN_IMPORT_MODE); } } + if (importMode == ImportMode.NEW_EVENT) { + if (boatClassName == null || boatClassName.isEmpty()) { + throw new AllinOneImportException(ERROR_MESSAGE_BOAT_CLASS_MISSING); + } + } else { + if (regattaName == null || regattaName.isEmpty()) { + throw new AllinOneImportException(ERROR_MESSAGE_REGATTA_MISSING); + } + } importerResult = new ExpeditionAllInOneImporter(getService(), raceLogTrackingAdapterTracker.getService().getAdapter(getService().getBaseDomainFactory()), getServiceFinderFactory(), getContext()).importFiles(fileName, fileItem, boatClassName, importMode, regattaName); From ef15e1e3bf6f4164f1c8a9b44c6e15e735169675 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 11 Apr 2018 13:11:43 +0200 Subject: [PATCH 08/59] Bug 4371: Improved UI layout --- .../java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index eb3fe678eae..c5626926028 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -486,7 +486,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe final FlowPanel importModePanel = new FlowPanel(); contentPanel.add(importModePanel); - final FlowPanel regattaNamePanel = new FlowPanel(); + final HorizontalPanel regattaNamePanel = new HorizontalPanel(); regattaNamePanel.setVisible(false); final HorizontalPanel boatClassPanel = new HorizontalPanel(); contentPanel.add(regattaNamePanel); @@ -524,14 +524,16 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe } }); - final Label regattaNameLabel = new Label(stringMessages.regattaName()); + final Label regattaNameLabel = new Label(stringMessages.regattaName() + ":"); regattaNamePanel.add(regattaNameLabel); + regattaNamePanel.setCellVerticalAlignment(regattaNameLabel, HasVerticalAlignment.ALIGN_MIDDLE); final TextBox regattaName = new TextBox(); regattaName.setName("regattaName"); refreshRegattaOracle(); regatttaSuggestBox = new SuggestBox(regattaOracle , regattaName); regattaNamePanel.add(regatttaSuggestBox); + regattaNamePanel.setCellVerticalAlignment(regatttaSuggestBox, HasVerticalAlignment.ALIGN_MIDDLE); boatClassPanel.setSpacing(5); contentPanel.add(boatClassPanel); final Label boatClassLabel = new Label(stringMessages.boatClass() + ":"); From ec37d1e8f47a65b3a11a8a1bb24786abaae1ba3e Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 11 Apr 2018 13:12:31 +0200 Subject: [PATCH 09/59] Bug 4371: Fixed typo --- .../gwt/ui/adminconsole/WindPanel.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index c5626926028..6c5632660c3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -128,7 +128,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe private RadioButton newEventImport; private RadioButton newCompetitorImport; private RadioButton newRaceImport; - private SuggestBox regatttaSuggestBox; + private SuggestBox regattaSuggestBox; private SuggestBox boatClassInput; private MultiWordSuggestOracle regattaOracle; @@ -503,8 +503,8 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe importModePanel.add(newCompetitorImport); newCompetitorImport.addClickHandler(event -> { regattaNamePanel.setVisible(true); - regatttaSuggestBox.setEnabled(true); - regatttaSuggestBox.setValue(null); + regattaSuggestBox.setEnabled(true); + regattaSuggestBox.setValue(null); boatClassPanel.setVisible(false); }); newRaceImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.newExpeditionRace()); @@ -512,8 +512,8 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe importModePanel.add(newRaceImport); newRaceImport.addClickHandler(event -> { regattaNamePanel.setVisible(true); - regatttaSuggestBox.setEnabled(true); - regatttaSuggestBox.setValue(null); + regattaSuggestBox.setEnabled(true); + regattaSuggestBox.setValue(null); boatClassPanel.setVisible(false); }); @@ -531,9 +531,9 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe regattaName.setName("regattaName"); refreshRegattaOracle(); - regatttaSuggestBox = new SuggestBox(regattaOracle , regattaName); - regattaNamePanel.add(regatttaSuggestBox); - regattaNamePanel.setCellVerticalAlignment(regatttaSuggestBox, HasVerticalAlignment.ALIGN_MIDDLE); + regattaSuggestBox = new SuggestBox(regattaOracle , regattaName); + regattaNamePanel.add(regattaSuggestBox); + regattaNamePanel.setCellVerticalAlignment(regattaSuggestBox, HasVerticalAlignment.ALIGN_MIDDLE); boatClassPanel.setSpacing(5); contentPanel.add(boatClassPanel); final Label boatClassLabel = new Label(stringMessages.boatClass() + ":"); @@ -551,7 +551,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe final Runnable validation = () -> { final String filename = fileUpload.getFilename(), boatClass = boatClassInput.getValue(); - final String regattaNameValue = regatttaSuggestBox.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(); @@ -577,7 +577,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe } }); - regatttaSuggestBox.addSelectionHandler(new SelectionHandler() { + regattaSuggestBox.addSelectionHandler(new SelectionHandler() { @Override public void onSelection(SelectionEvent event) { final String selected = event.getSelectedItem().getReplacementString(); @@ -596,7 +596,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe } } }); - regatttaSuggestBox.addKeyUpHandler(event -> validation.run()); + regattaSuggestBox.addKeyUpHandler(event -> validation.run()); fileUpload.addChangeHandler(event -> validation.run()); boatClassInput.addSelectionHandler(event -> validation.run()); @@ -611,7 +611,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe newCompetitorImport.setEnabled(b); newEventImport.setEnabled(b); newRaceImport.setEnabled(b); - regatttaSuggestBox.setEnabled(b); + regattaSuggestBox.setEnabled(b); boatClassInput.setEnabled(b); if(b) { //set consistent start scenario after choosing different file From 5e1b359a44b092f0a7a4d8ddc11d984a9b8d3c4a Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 11 Apr 2018 13:35:01 +0200 Subject: [PATCH 10/59] Whitespace change only --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index dc7717a4493..7ec4d06e5fa 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -366,7 +366,7 @@ public class ExpeditionAllInOneImporter { raceColumn, fleet); trackedRaces.add(trackedRace); } else { - return new ImporterResult(ERROR_MESSAGE_INVALID_IMPORTMODE + importMode); + return new ImporterResult(ERROR_MESSAGE_INVALID_IMPORTMODE + importMode); } } else { return new ImporterResult(ERROR_MESSAGE_INVALID_REGATTA_NAME); From 506525f42ec7aaf0b238f147aea347bc636c3213 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 11 Apr 2018 14:03:43 +0200 Subject: [PATCH 11/59] Bug 4371: I18n --- .../ExpeditionAllInOneAfterImportHandler.java | 8 ++++++-- .../com/sap/sailing/gwt/ui/client/StringMessages.java | 1 + .../sap/sailing/gwt/ui/client/StringMessages.properties | 3 ++- .../sailing/gwt/ui/client/StringMessages_de.properties | 3 ++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java index 4ee90273613..666f8e0a388 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java @@ -96,7 +96,7 @@ public class ExpeditionAllInOneAfterImportHandler { StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace) { this(boatClass, sailingService, stringMessages, errorReporter, editable, leaderboardName, - canBoatsOfCompetitorsChangePerRace, new ValidatorForCompetitorRegistrationDialog(), + canBoatsOfCompetitorsChangePerRace, new ValidatorForCompetitorRegistrationDialog(stringMessages), new CallbackForCompetitorRegistrationDialog()); } @@ -113,10 +113,14 @@ public class ExpeditionAllInOneAfterImportHandler { private static class ValidatorForCompetitorRegistrationDialog implements Validator> { private CompetitorRegistrationsPanel competitorRegistrationsPanel; + private StringMessages stringMessages; + public ValidatorForCompetitorRegistrationDialog(StringMessages stringMessages) { + this.stringMessages = stringMessages; + } @Override public String getErrorMessage(Set valueToValidate) { if (competitorRegistrationsPanel == null || competitorRegistrationsPanel.getSelectedRegisteredCompetitors().size() != 1) { - return "TODO: select one competitor in the left table"; + return stringMessages.selectOneCompetitorToMapTheImportedData(); } return null; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 35b408242a3..fe15c953f87 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -2109,4 +2109,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String degreesPerSecondUnit(); String newExpeditionRace(); String newExpeditionCompetitor(); + String selectOneCompetitorToMapTheImportedData(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 7d68dfcef0c..b5ea46bc810 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -2096,4 +2096,5 @@ avgTurningRate=Avg. turning rate lowestSpeed=Lowest speed degreesPerSecondUnit=deg/s newExpeditionRace=Create a new race -newExpeditionCompetitor=Add a new Competitor \ No newline at end of file +newExpeditionCompetitor=Add a new Competitor +selectOneCompetitorToMapTheImportedData=Please select one competitor on the left side. The imported data will be mapped to this competitor. \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 31fc419448b..feb54b17e81 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -2094,4 +2094,5 @@ avgTurningRate=Durchschnittliche Drehrate lowestSpeed=Niedrigste Geschwindigkeit degreesPerSecondUnit=deg/s newExpeditionRace=Neues Rennen anlegen -newExpeditionCompetitor=Neuen Competitor hinzufügen \ No newline at end of file +newExpeditionCompetitor=Neuen Competitor hinzufügen +selectOneCompetitorToMapTheImportedData=Bitte einen Teilnehmer auf der linken Seite auswählen. Die importierten Daten werden dem ausgewählten Teinehmer zugeordnet. \ No newline at end of file From 9760b5a2715ae88282e9d8a475383a23cc702aec Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 11 Apr 2018 14:11:40 +0200 Subject: [PATCH 12/59] Bug 4371: Layout improvements --- .../main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index 6c5632660c3..ed80b5296e8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -524,6 +524,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe } }); + regattaNamePanel.setSpacing(5); final Label regattaNameLabel = new Label(stringMessages.regattaName() + ":"); regattaNamePanel.add(regattaNameLabel); regattaNamePanel.setCellVerticalAlignment(regattaNameLabel, HasVerticalAlignment.ALIGN_MIDDLE); From 281787450ad74f6b11c9eedbec9e39aaba4c27cd Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 11 Apr 2018 14:29:19 +0200 Subject: [PATCH 13/59] Bug 4371: Simplified UI state and for expedition all in one import --- .../gwt/ui/adminconsole/WindPanel.java | 58 +++++-------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index ed80b5296e8..da0ed09b26f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -125,13 +125,6 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe private final CellTable rawWindFixesTable; private final VerticalPanel windFixPanel; - private RadioButton newEventImport; - private RadioButton newCompetitorImport; - private RadioButton newRaceImport; - private SuggestBox regattaSuggestBox; - private SuggestBox boatClassInput; - private MultiWordSuggestOracle regattaOracle; - public WindPanel(final SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, ErrorReporter errorReporter, RegattaRefresher regattaRefresher, final StringMessages stringMessages) { ensureDebugId("WindPanel"); @@ -156,8 +149,6 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe updateWindDisplay(); } }); - - regattaOracle = new MultiWordSuggestOracle(". _"); windCaptionPanel = new CaptionPanel(stringMessages.wind()); windCaptionPanel.setVisible(false); @@ -490,7 +481,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe regattaNamePanel.setVisible(false); final HorizontalPanel boatClassPanel = new HorizontalPanel(); contentPanel.add(regattaNamePanel); - newEventImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.createNewEvent()); + final RadioButton newEventImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.createNewEvent()); newEventImport.setFormValue("NEW_EVENT"); newEventImport.setValue(true); importModePanel.add(newEventImport); @@ -498,32 +489,21 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe regattaNamePanel.setVisible(false); boatClassPanel.setVisible(true); }); - newCompetitorImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.newExpeditionCompetitor()); + 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); - regattaSuggestBox.setEnabled(true); - regattaSuggestBox.setValue(null); boatClassPanel.setVisible(false); }); - newRaceImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.newExpeditionRace()); + 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); - regattaSuggestBox.setEnabled(true); - regattaSuggestBox.setValue(null); boatClassPanel.setVisible(false); }); - fileUpload.addChangeHandler(new ChangeHandler() { - @Override - public void onChange(ChangeEvent event) { - enableExpeditionRadios(fileUpload.getFilename() != null); - } - }); - regattaNamePanel.setSpacing(5); final Label regattaNameLabel = new Label(stringMessages.regattaName() + ":"); regattaNamePanel.add(regattaNameLabel); @@ -531,8 +511,9 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe final TextBox regattaName = new TextBox(); regattaName.setName("regattaName"); - refreshRegattaOracle(); - regattaSuggestBox = new SuggestBox(regattaOracle , regattaName); + final MultiWordSuggestOracle regattaOracle = new MultiWordSuggestOracle(". _"); + refreshRegattaOracle(regattaOracle); + final SuggestBox regattaSuggestBox = new SuggestBox(regattaOracle , regattaName); regattaNamePanel.add(regattaSuggestBox); regattaNamePanel.setCellVerticalAlignment(regattaSuggestBox, HasVerticalAlignment.ALIGN_MIDDLE); boatClassPanel.setSpacing(5); @@ -540,7 +521,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe final Label boatClassLabel = new Label(stringMessages.boatClass() + ":"); boatClassPanel.add(boatClassLabel); boatClassPanel.setCellVerticalAlignment(boatClassLabel, HasVerticalAlignment.ALIGN_MIDDLE); - boatClassInput = new SuggestBox(new BoatClassMasterdataSuggestOracle()); + final SuggestBox boatClassInput = new SuggestBox(new BoatClassMasterdataSuggestOracle()); boatClassInput.getValueBox().setName(EXPEDITON_IMPORT_PARAMETER_BOAT_CLASS); boatClassPanel.add(boatClassInput); boatClassPanel.setCellVerticalAlignment(boatClassInput, HasVerticalAlignment.ALIGN_MIDDLE); @@ -559,6 +540,13 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe 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(); @@ -572,7 +560,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe response.getRaceColumnName(), response.getFleetName(), response.getGpsDeviceIds(), response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService, errorReporter, stringMessages); - refreshRegattaOracle(); + refreshRegattaOracle(regattaOracle); } else { ExpeditionDataImportResultsDialog.showResults(response); } @@ -604,24 +592,10 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe boatClassInput.addKeyUpHandler(event -> validation.run()); validation.run(); - enableExpeditionRadios(false); return rootPanel; } - protected void enableExpeditionRadios(boolean b) { - newCompetitorImport.setEnabled(b); - newEventImport.setEnabled(b); - newRaceImport.setEnabled(b); - regattaSuggestBox.setEnabled(b); - boatClassInput.setEnabled(b); - if(b) { - //set consistent start scenario after choosing different file - newEventImport.setValue(true); - boatClassInput.setValue(null); - } - } - - private void refreshRegattaOracle() { + private void refreshRegattaOracle(MultiWordSuggestOracle regattaOracle) { sailingService.getRegattas(new AsyncCallback>() { @Override public void onSuccess(List result) { From 6daa5dde1a8e22d09bf4cd7893282f10e3a2d343 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 11 Apr 2018 14:46:35 +0200 Subject: [PATCH 14/59] Bug 4371: Updated TODOs --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 7ec4d06e5fa..d3e2d17349d 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -217,8 +217,8 @@ public class ExpeditionAllInOneImporter { final String regattaNameAndleaderboardName; final Regatta regatta; final RegattaLeaderboard regattaLeaderboard; - // TODO Should we return all TrackedRaces? Alternatively make final when all errors are handled - DynamicTrackedRace trackedRace; + // TODO Should we return all TrackedRaces and show several RaceBoard links to the user? + final DynamicTrackedRace trackedRace; final List trackedRaces = new ArrayList<>(); final String fleetName; final String raceColumnName; @@ -309,6 +309,7 @@ public class ExpeditionAllInOneImporter { if (foundEvent == null) { return new ImporterResult(ERROR_MESSAGE_INVALID_LEADERBOARD_EVENT_LINK); } + // TODO should we extend the time range of the event to ensure that it includes the newly imported tracks' time ranges? eventId = foundEvent.getId(); leaderboardGroupName = foundLeaderboardGroup.getName(); From b7d84a5e8541ee467671e50266a9e9dceb1ba21f Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 11 Apr 2018 14:48:38 +0200 Subject: [PATCH 15/59] Bug 4371: Removed legacy TODO --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index d3e2d17349d..7825da7c70c 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -158,7 +158,6 @@ public class ExpeditionAllInOneImporter { final String filename = ExpeditionImportFilenameUtils.truncateFilenameExtentions(filenameWithSuffix); final String filenameWithDateTimeSuffix = filename + "_" + importTimeString; final String trackedRaceName = filenameWithDateTimeSuffix; - // TODO is this a proper id for the WindSource used here? final String windSourceId = filenameWithDateTimeSuffix; // TODO wild guess... From 401b16dca8898bed7dfadf28af3fd65f2e1d6aea Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 11 Apr 2018 14:50:49 +0200 Subject: [PATCH 16/59] Bug 4371: Added TODO for hard coded flag that needs to be discussed --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 7825da7c70c..d972b65e214 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -426,7 +426,7 @@ public class ExpeditionAllInOneImporter { final Fleet fleet) throws NotDenotedForRaceLogTrackingException, Exception { DynamicTrackedRace trackedRace; final RaceHandle raceHandle = adapter.startTracking(service, regattaLeaderboard, raceColumn, fleet, - /* trackWind */ true, /* correctWindDirectionByMagneticDeclination */ true); + /* trackWind */ true, /* TODO correctWindDirectionByMagneticDeclination */ true); // wait for the RaceDefinition to be created raceHandle.getRace(); From 60bdff2e1ac03919f5ee4f4023aec8bec060281e Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Thu, 12 Apr 2018 11:13:13 +0200 Subject: [PATCH 17/59] Bug 4371: Added JavaDocs --- .../impl/ExpeditionAllInOneImporter.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index d972b65e214..23f27011525 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -25,6 +25,7 @@ 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; @@ -37,6 +38,7 @@ 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; @@ -44,6 +46,8 @@ 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.tracking.BravoExtendedFix; +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; @@ -53,6 +57,8 @@ 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.server.RacingEventService; import com.sap.sailing.server.gateway.trackfiles.impl.ImportResultDTO.ErrorImportDTO; import com.sap.sailing.server.gateway.trackfiles.impl.ImportResultDTO.TrackImportDTO; @@ -71,6 +77,35 @@ import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; +/** + * Importer for expedition data that imports all available data for a boat: + *
    + *
  • {@link GPSFixMoving} and {@link BravoExtendedFix} instances are imported as a distinct track that needs to be + * mapped to a specific competitor afterwards
  • + *
  • Wind fixes are being imported as a new {@link WindTrack}
  • + *
+ * There are several {@link ImportMode ImportModes} which have specific preconditions and activate different importing + * behavior: + *
    + *
  • {@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}.
  • + *
  • {@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.
  • + *
  • {@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 regatta.
  • + *
+ * 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 String ERROR_MESSAGE_INVALID_REGATTA_NAME = "Please enter a valid regatta name to proceed"; From 35eebad8225cd71529c5b619581650941eb3f8b7 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Thu, 12 Apr 2018 11:28:25 +0200 Subject: [PATCH 18/59] Bug 4371: Added/extended JavaDocs --- .../ExpeditionAllInOneAfterImportHandler.java | 10 ++++++++++ .../impl/ExpeditionAllInOneImportServlet.java | 2 ++ 2 files changed, 12 insertions(+) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java index 666f8e0a388..7695fa387ac 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java @@ -25,6 +25,16 @@ 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; diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java index 1d6fced99a5..19859ca513a 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java @@ -25,6 +25,8 @@ 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; From 8839ec1d0e0430a51115950f0af11758114d0060 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Thu, 12 Apr 2018 11:57:19 +0200 Subject: [PATCH 19/59] Bug 4371: Extracted expedition all in one import UI to a new class --- .../ExpeditionAllInOneImportPanel.java | 214 ++++++++++++++++++ .../gwt/ui/adminconsole/WindPanel.java | 171 +------------- 2 files changed, 216 insertions(+), 169 deletions(-) create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java new file mode 100644 index 00000000000..232a4a4d259 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java @@ -0,0 +1,214 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.List; + +import com.google.gwt.core.client.GWT; +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.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.HorizontalPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.MultiWordSuggestOracle; +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.ui.adminconsole.resulthandling.ExpeditionDataImportResponse; +import com.sap.sailing.gwt.ui.adminconsole.resulthandling.ExpeditionDataImportResultsDialog; +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 { + private static final String EXPEDITON_IMPORT_PARAMETER_BOAT_CLASS = "boatClass"; + + private static final String URL_SAILINGSERVER_EXPEDITION_FULL_IMPORT = "/../../sailingserver/expedition/import"; + + private final MultiWordSuggestOracle regattaOracle; + + private final SailingServiceAsync sailingService; + + private final ErrorReporter errorReporter; + + public ExpeditionAllInOneImportPanel(StringMessages stringMessages, SailingServiceAsync sailingService, + ErrorReporter errorReporter) { + this.sailingService = sailingService; + this.errorReporter = errorReporter; + 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 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("NEW_EVENT"); + 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("regattaName"); + + regattaOracle = new MultiWordSuggestOracle(". _"); + refreshRegattaOracle(); + final SuggestBox regattaSuggestBox = new SuggestBox(regattaOracle, regattaName); + 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().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 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.getRaceName(), + response.getRaceColumnName(), response.getFleetName(), response.getGpsDeviceIds(), + response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService, + errorReporter, stringMessages); + refreshRegattaOracle(); + } else { + ExpeditionDataImportResultsDialog.showResults(response); + } + }); + + regattaSuggestBox.addSelectionHandler(new SelectionHandler() { + @Override + public void onSelection(SelectionEvent event) { + final String selected = event.getSelectedItem().getReplacementString(); + if (selected != null) { + sailingService.getRegattaByName(selected, new AsyncCallback() { + @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); + } + + private void refreshRegattaOracle() { + sailingService.getRegattas(new AsyncCallback>() { + @Override + public void onSuccess(List result) { + regattaOracle.clear(); + for (RegattaDTO regatta : result) { + regattaOracle.add(regatta.getName()); + } + } + + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Could not load regattanames " + caught.getMessage()); + } + }); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index da0ed09b26f..f54d00f73c9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -17,8 +17,6 @@ import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.logical.shared.SelectionEvent; -import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.i18n.client.NumberFormat; @@ -39,19 +37,13 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CaptionPanel; import com.google.gwt.user.client.ui.CheckBox; 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.HTML; 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.MultiWordSuggestOracle; import com.google.gwt.user.client.ui.Panel; -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.TabPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; @@ -60,13 +52,9 @@ import com.google.gwt.view.client.SelectionChangeEvent; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.dto.ExpeditionAllInOneConstants; 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; @@ -82,8 +70,6 @@ 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; /** @@ -98,9 +84,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe 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"; @@ -456,161 +440,10 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe private CaptionPanel createExpeditionAllInOneImportPanel() { final CaptionPanel rootPanel = new CaptionPanel(stringMessages.importFullExpeditionData()); - 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); - rootPanel.add(formPanel); - final VerticalPanel contentPanel = new VerticalPanel(); - formPanel.add(contentPanel); - 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("NEW_EVENT"); - 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("regattaName"); - - final MultiWordSuggestOracle regattaOracle = new MultiWordSuggestOracle(". _"); - refreshRegattaOracle(regattaOracle); - final SuggestBox regattaSuggestBox = new SuggestBox(regattaOracle , regattaName); - 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().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 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.getRaceName(), - response.getRaceColumnName(), response.getFleetName(), response.getGpsDeviceIds(), - response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService, - errorReporter, stringMessages); - refreshRegattaOracle(regattaOracle); - } else { - ExpeditionDataImportResultsDialog.showResults(response); - } - }); - - regattaSuggestBox.addSelectionHandler(new SelectionHandler() { - @Override - public void onSelection(SelectionEvent event) { - final String selected = event.getSelectedItem().getReplacementString(); - if (selected != null) { - sailingService.getRegattaByName(selected, new AsyncCallback() { - @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(); - + rootPanel.add(new ExpeditionAllInOneImportPanel(stringMessages, sailingService, errorReporter)); return rootPanel; } - private void refreshRegattaOracle(MultiWordSuggestOracle regattaOracle) { - sailingService.getRegattas(new AsyncCallback>() { - @Override - public void onSuccess(List result) { - regattaOracle.clear(); - for (RegattaDTO regatta : result) { - regattaOracle.add(regatta.getName()); - } - } - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Could not load regattanames " + caught.getMessage()); - } - }); - } - private CaptionPanel createExpeditionWindImportPanel() { /* * To style the "browse" button of the file upload widget From e14261c792cd85e90b92ae82f1931067206db568 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Thu, 12 Apr 2018 12:00:30 +0200 Subject: [PATCH 20/59] Bug 4371: consistently using constants instead of hard-coded strings --- .../ui/adminconsole/ExpeditionAllInOneImportPanel.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java index 232a4a4d259..6ae759abebd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java @@ -39,8 +39,6 @@ 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 { - private static final String EXPEDITON_IMPORT_PARAMETER_BOAT_CLASS = "boatClass"; - private static final String URL_SAILINGSERVER_EXPEDITION_FULL_IMPORT = "/../../sailingserver/expedition/import"; private final MultiWordSuggestOracle regattaOracle; @@ -79,7 +77,7 @@ public class ExpeditionAllInOneImportPanel extends Composite { contentPanel.add(regattaNamePanel); final RadioButton newEventImport = new RadioButton(ExpeditionAllInOneConstants.REQUEST_PARAMETER_IMPORT_MODE, stringMessages.createNewEvent()); - newEventImport.setFormValue("NEW_EVENT"); + newEventImport.setFormValue(ExpeditionAllInOneConstants.ImportMode.NEW_EVENT.name()); newEventImport.setValue(true); importModePanel.add(newEventImport); newEventImport.addClickHandler(event -> { @@ -108,7 +106,7 @@ public class ExpeditionAllInOneImportPanel extends Composite { regattaNamePanel.add(regattaNameLabel); regattaNamePanel.setCellVerticalAlignment(regattaNameLabel, HasVerticalAlignment.ALIGN_MIDDLE); final TextBox regattaName = new TextBox(); - regattaName.setName("regattaName"); + regattaName.setName(ExpeditionAllInOneConstants.REQUEST_PARAMETER_REGATTA_NAME); regattaOracle = new MultiWordSuggestOracle(". _"); refreshRegattaOracle(); @@ -121,7 +119,7 @@ public class ExpeditionAllInOneImportPanel extends Composite { boatClassPanel.add(boatClassLabel); boatClassPanel.setCellVerticalAlignment(boatClassLabel, HasVerticalAlignment.ALIGN_MIDDLE); final SuggestBox boatClassInput = new SuggestBox(new BoatClassMasterdataSuggestOracle()); - boatClassInput.getValueBox().setName(EXPEDITON_IMPORT_PARAMETER_BOAT_CLASS); + boatClassInput.getValueBox().setName(ExpeditionAllInOneConstants.REQUEST_PARAMETER_BOAT_CLASS); boatClassPanel.add(boatClassInput); boatClassPanel.setCellVerticalAlignment(boatClassInput, HasVerticalAlignment.ALIGN_MIDDLE); final HorizontalPanel controlPanel = new HorizontalPanel(); From 4f2a938303ce0aaf4a141af01be2926917136633 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Thu, 12 Apr 2018 13:42:53 +0200 Subject: [PATCH 21/59] Bug 4371: Improved JavaDocs --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 23f27011525..09d2fcb612e 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -97,14 +97,13 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; *
  • {@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 regatta.
  • + * a {@link Regatta}. * * 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 String ERROR_MESSAGE_INVALID_REGATTA_NAME = "Please enter a valid regatta name to proceed"; From 7f69d2823cd50bd4c3d6732de233037d280b96b7 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Thu, 12 Apr 2018 13:51:11 +0200 Subject: [PATCH 22/59] Bug 4371: Removed legacy TODO --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 09d2fcb612e..3422856bfb1 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -437,7 +437,6 @@ public class ExpeditionAllInOneImporter { 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(); From d7c11170291aeb177ef93974356bdd3304a6d3bc Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 12 Apr 2018 15:38:38 +0200 Subject: [PATCH 23/59] replaced Competitor by Teilnehmer in _de.properties Change-Id: I03837fd8871e1c5f1ebbaa61fc574ad28fd845db --- .../com/sap/sailing/gwt/ui/client/StringMessages_de.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 4ef5acb4454..1ff9556de4a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -2094,5 +2094,5 @@ avgTurningRate=Durchschnittliche Drehrate lowestSpeed=Niedrigste Geschwindigkeit degreesPerSecondUnit=deg/s newExpeditionRace=Neues Rennen anlegen -newExpeditionCompetitor=Neuen Competitor hinzufügen +newExpeditionCompetitor=Neuen Teilnehmer hinzufügen selectOneCompetitorToMapTheImportedData=Bitte einen Teilnehmer auf der linken Seite auswählen. Die importierten Daten werden dem ausgewählten Teinehmer zugeordnet. \ No newline at end of file From 3aad2327f63486231da201cb7523d8b0e1ba8efd Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 12 Apr 2018 16:36:27 +0200 Subject: [PATCH 24/59] use RegattasDisplayer pattern to avoid additional getRegattas call Change-Id: I8cb6c435dbc6978a3b38d68bc2580acced9566eb --- .../suggestion/RegattaSuggestOracle.java | 40 +++++++++++++++ .../ExpeditionAllInOneImportPanel.java | 50 +++++-------------- .../gwt/ui/adminconsole/WindPanel.java | 40 ++++++++------- 3 files changed, 73 insertions(+), 57 deletions(-) create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/suggestion/RegattaSuggestOracle.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/suggestion/RegattaSuggestOracle.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/suggestion/RegattaSuggestOracle.java new file mode 100755 index 00000000000..dbac93da52c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/suggestion/RegattaSuggestOracle.java @@ -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 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 getMatchingStrings(RegattaDTO value) { + return Arrays.asList(value.getName(), value.boatClass.getName()); + } + + @Override + public void fillRegattas(Iterable result) { + final List 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); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java index 6ae759abebd..9f45551b405 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java @@ -1,7 +1,5 @@ package com.sap.sailing.gwt.ui.adminconsole; -import java.util.List; - import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; @@ -17,7 +15,6 @@ import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.MultiWordSuggestOracle; import com.google.gwt.user.client.ui.RadioButton; import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.SuggestOracle; @@ -26,8 +23,11 @@ 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; @@ -38,19 +38,13 @@ 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 { +public class ExpeditionAllInOneImportPanel extends Composite implements RegattasDisplayer { private static final String URL_SAILINGSERVER_EXPEDITION_FULL_IMPORT = "/../../sailingserver/expedition/import"; - private final MultiWordSuggestOracle regattaOracle; + private final RegattaSuggestOracle regattaOracle; - private final SailingServiceAsync sailingService; - - private final ErrorReporter errorReporter; - - public ExpeditionAllInOneImportPanel(StringMessages stringMessages, SailingServiceAsync sailingService, - ErrorReporter errorReporter) { - this.sailingService = sailingService; - this.errorReporter = errorReporter; + 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()); @@ -108,8 +102,7 @@ public class ExpeditionAllInOneImportPanel extends Composite { final TextBox regattaName = new TextBox(); regattaName.setName(ExpeditionAllInOneConstants.REQUEST_PARAMETER_REGATTA_NAME); - regattaOracle = new MultiWordSuggestOracle(". _"); - refreshRegattaOracle(); + regattaOracle = new RegattaSuggestOracle(); final SuggestBox regattaSuggestBox = new SuggestBox(regattaOracle, regattaName); regattaNamePanel.add(regattaSuggestBox); regattaNamePanel.setCellVerticalAlignment(regattaSuggestBox, HasVerticalAlignment.ALIGN_MIDDLE); @@ -127,7 +120,6 @@ public class ExpeditionAllInOneImportPanel extends Composite { 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(); @@ -137,14 +129,12 @@ public class ExpeditionAllInOneImportPanel extends Composite { 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); @@ -157,12 +147,11 @@ public class ExpeditionAllInOneImportPanel extends Composite { response.getRaceColumnName(), response.getFleetName(), response.getGpsDeviceIds(), response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService, errorReporter, stringMessages); - refreshRegattaOracle(); + regattaRefresher.fillRegattas(); } else { ExpeditionDataImportResultsDialog.showResults(response); } }); - regattaSuggestBox.addSelectionHandler(new SelectionHandler() { @Override public void onSelection(SelectionEvent event) { @@ -183,30 +172,15 @@ public class ExpeditionAllInOneImportPanel extends Composite { } }); regattaSuggestBox.addKeyUpHandler(event -> validation.run()); - fileUpload.addChangeHandler(event -> validation.run()); boatClassInput.addSelectionHandler(event -> validation.run()); boatClassInput.addKeyUpHandler(event -> validation.run()); validation.run(); - initWidget(formPanel); } - private void refreshRegattaOracle() { - sailingService.getRegattas(new AsyncCallback>() { - @Override - public void onSuccess(List result) { - regattaOracle.clear(); - for (RegattaDTO regatta : result) { - regattaOracle.add(regatta.getName()); - } - } - - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Could not load regattanames " + caught.getMessage()); - } - }); + @Override + public void fillRegattas(Iterable regattas) { + regattaOracle.fillRegattas(regattas); } - } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index f54d00f73c9..a80c9ef0b09 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -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; @@ -66,6 +67,7 @@ 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; @@ -108,22 +110,28 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe private final ListDataProvider rawWindFixesDataProvider; private final CellTable 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 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) trackedRacesListComposite.getSelectionModel(); @@ -133,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() { @@ -166,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() { @Override @@ -183,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(new ActionCell(stringMessages.remove(), new Delegate() { @Override @@ -242,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(/* pageSize */10000, tableRes); rawWindFixesTable.addColumn(timeColumn, stringMessages.time()); @@ -256,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 expeditionAllInOneRootAndImportPanel = createExpeditionAllInOneImportPanel(regattaRefresher); + mainPanel.add(expeditionAllInOneRootAndImportPanel.getA()); + containedRegattaDisplayers.add(expeditionAllInOneRootAndImportPanel.getB()); } private CaptionPanel createIgtimiWindImportPanel(VerticalPanel mainPanel) { @@ -438,10 +437,11 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe return new WindImportFileUploadForm(form, formContentPanel, fileUpload, submitButton); } - private CaptionPanel createExpeditionAllInOneImportPanel() { + private Pair createExpeditionAllInOneImportPanel(RegattaRefresher regattaRefresher) { final CaptionPanel rootPanel = new CaptionPanel(stringMessages.importFullExpeditionData()); - rootPanel.add(new ExpeditionAllInOneImportPanel(stringMessages, sailingService, errorReporter)); - return rootPanel; + final ExpeditionAllInOneImportPanel expeditionAllInOneImportPanel = new ExpeditionAllInOneImportPanel(stringMessages, sailingService, errorReporter, regattaRefresher); + rootPanel.add(expeditionAllInOneImportPanel); + return new Pair<>(rootPanel, expeditionAllInOneImportPanel); } private CaptionPanel createExpeditionWindImportPanel() { @@ -559,7 +559,9 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe @Override public void fillRegattas(Iterable result) { - trackedRacesListComposite.fillRegattas(result); + for (final RegattasDisplayer containedRegattaDisplayer : containedRegattaDisplayers) { + containedRegattaDisplayer.fillRegattas(result); + } } @Override From be4f1d319742e05393ab188e4a794d4e78176c4c Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 12 Apr 2018 20:55:32 +0200 Subject: [PATCH 25/59] don't track an Expedition log file's race with wind tracker Change-Id: I98137ea3f6508ad4a8cdb620bfc7e3a05be817f7 --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 3422856bfb1..71381f0c029 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -459,11 +459,9 @@ public class ExpeditionAllInOneImporter { final Fleet fleet) throws NotDenotedForRaceLogTrackingException, Exception { DynamicTrackedRace trackedRace; final RaceHandle raceHandle = adapter.startTracking(service, regattaLeaderboard, raceColumn, fleet, - /* trackWind */ true, /* TODO correctWindDirectionByMagneticDeclination */ true); - + /* 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"); From c04803a52a5223dadab3057cc28f8a4ce164544f Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 13 Apr 2018 08:41:50 +0200 Subject: [PATCH 26/59] Bug 4371: Resolved TODO and updated flags when tracking races during import to be consistent on server and client --- .../ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java index 265815718f2..0333303fcd8 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java @@ -239,8 +239,8 @@ public class ExpeditionAllInOneAfterImportHandler { public void onSuccess(Void result) { final List> leaderboardRaceColumnFleetNames = new ArrayList<>(); leaderboardRaceColumnFleetNames.add(new Triple<>(leaderboard.name, raceColumnName, fleetName)); - sailingService.startRaceLogTracking(leaderboardRaceColumnFleetNames, /* trackWind */ true, - /* TODO correctWindByDeclination */ true, new AsyncCallback() { + sailingService.startRaceLogTracking(leaderboardRaceColumnFleetNames, /* trackWind */ false, + /* correctWindByDeclination */ true, new AsyncCallback() { @Override public void onSuccess(Void result) { new ExpeditionAllInOneImportResultDialog(event.id, regatta.getName(), From 7b3d91654037db0c7a915d23d4c14c333886dcbf Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 13 Apr 2018 08:43:11 +0200 Subject: [PATCH 27/59] Bug 4371: Improved method name --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 71381f0c029..89c6fcb5a0e 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -310,7 +310,7 @@ public class ExpeditionAllInOneImporter { final RaceColumn raceColumn = regattaLeaderboard.getRaceColumns().iterator().next(); final Fleet fleet = raceColumn.getFleets().iterator().next(); - trackedRace = createTrackedAndSetupRaceTimes(errors, trackedRaceName, firstFixAt, lastFixAt, regatta, regattaLeaderboard, + trackedRace = createTrackedRaceAndSetupRaceTimes(errors, trackedRaceName, firstFixAt, lastFixAt, regatta, regattaLeaderboard, raceColumn, fleet); trackedRaces.add(trackedRace); } else { @@ -396,7 +396,7 @@ public class ExpeditionAllInOneImporter { raceColumnName = regatta.getRaceColumnByName(filename) == null ? filename : filenameWithDateTimeSuffix; final RaceColumn raceColumn = service.apply(new AddColumnToSeries(regatta.getRegattaIdentifier(), series.getName(), raceColumnName)); - trackedRace = createTrackedAndSetupRaceTimes(errors, trackedRaceName, firstFixAt, lastFixAt, regatta, regattaLeaderboard, + trackedRace = createTrackedRaceAndSetupRaceTimes(errors, trackedRaceName, firstFixAt, lastFixAt, regatta, regattaLeaderboard, raceColumn, fleet); trackedRaces.add(trackedRace); } else { @@ -425,7 +425,7 @@ public class ExpeditionAllInOneImporter { } } - private DynamicTrackedRace createTrackedAndSetupRaceTimes(final List errors, + private DynamicTrackedRace createTrackedRaceAndSetupRaceTimes(final List errors, final String trackedRaceName, TimePoint firstFixAt, TimePoint lastFixAt, final Regatta regatta, final RegattaLeaderboard regattaLeaderboard, final RaceColumn raceColumn, final Fleet fleet) throws AllinOneImportException { From b4bf6ac134b50e66eb2d6873f8acc3861421eaa4 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 13 Apr 2018 08:53:31 +0200 Subject: [PATCH 28/59] Bug 4371: Refactored parts to new methods in ExpeditionAllInOneImporter --- .../impl/ExpeditionAllInOneImporter.java | 87 ++++++++++++------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 89c6fcb5a0e..7c77ef9fa4c 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -195,8 +195,6 @@ public class ExpeditionAllInOneImporter { final String windSourceId = filenameWithDateTimeSuffix; // 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); @@ -248,7 +246,6 @@ public class ExpeditionAllInOneImporter { final UUID eventId; final String leaderboardGroupName; final String regattaNameAndleaderboardName; - final Regatta regatta; final RegattaLeaderboard regattaLeaderboard; // TODO Should we return all TrackedRaces and show several RaceBoard links to the user? final DynamicTrackedRace trackedRace; @@ -265,8 +262,6 @@ public class ExpeditionAllInOneImporter { regattaNameAndleaderboardName = filenameWithDateTimeSuffix; raceColumnName = filename; final RegattaIdentifier regattaIdentifier = new RegattaName(filenameWithDateTimeSuffix); - final String courseAreaName = "Default"; - final UUID courseAreaId = UUID.randomUUID(); // This is just the default used in the UI final Double buoyZoneRadiusInHullLengths = 3.0; @@ -276,36 +271,16 @@ public class ExpeditionAllInOneImporter { final Event event = service.addEvent(eventName, description, eventStartDate, eventEndDate, venueName, true, UUID.randomUUID()); eventId = event.getId(); - service.addCourseAreas(event.getId(), new String[] { courseAreaName }, new UUID[] { courseAreaId }); + + final UUID courseAreaId = addDefaultCourseArea(event); - final ScoringScheme scoringScheme = service.getBaseDomainFactory().createScoringScheme(scoringSchemeType); - - final LinkedHashMap seriesCreationParameters = new LinkedHashMap<>(); - final List fleets = new ArrayList<>(); - fleets.add(new FleetDTO(fleetName, 0, null)); - seriesCreationParameters.put(seriesName, - new SeriesCreationParametersDTO(fleets, /*isMedal*/ false, - /* isFleetsCanRunInParallel */ false, /*isStartsWithZeroScore*/ false, /*firstColumnIsNonDiscardableCarryForward*/false, /*discardingThresholds*/ null, - /*hasSplitFleetContiguousScoring*/ false, /*maximumNumberOfDiscards*/ null)); - final RegattaCreationParametersDTO regattaCreationParameters = new RegattaCreationParametersDTO( - seriesCreationParameters); - - 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 Regatta regatta = createRegattaWithOneRaceColumn(boatClassName, regattaNameAndleaderboardName, + fleetName, raceColumnName, regattaIdentifier, courseAreaId, buoyZoneRadiusInHullLengths, + seriesName); regattaLeaderboard = service.apply(new CreateRegattaLeaderboard(regattaIdentifier, null, discardThresholds)); - 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())); + createLeaderboardGroupAndAddItToTheEvent(leaderboardGroupName, regattaNameAndleaderboardName, description, event); final RaceColumn raceColumn = regattaLeaderboard.getRaceColumns().iterator().next(); final Fleet fleet = raceColumn.getFleets().iterator().next(); @@ -316,7 +291,7 @@ public class ExpeditionAllInOneImporter { } else { regattaNameAndleaderboardName = existingRegattaName; if (existingRegattaName != null && !existingRegattaName.isEmpty()) { - regatta = service.getRegattaByName(existingRegattaName); + final Regatta regatta = service.getRegattaByName(existingRegattaName); if (regatta == null) { return new ImporterResult(ERROR_MESSAGE_INVALID_REGATTA); } @@ -425,6 +400,54 @@ public class ExpeditionAllInOneImporter { } } + 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 seriesCreationParameters = new LinkedHashMap<>(); + final List fleets = new ArrayList<>(); + fleets.add(new FleetDTO(fleetName, 0, null)); + seriesCreationParameters.put(seriesName, + new SeriesCreationParametersDTO(fleets, /*isMedal*/ false, + /* isFleetsCanRunInParallel */ false, /*isStartsWithZeroScore*/ false, /*firstColumnIsNonDiscardableCarryForward*/false, /*discardingThresholds*/ null, + /*hasSplitFleetContiguousScoring*/ false, /*maximumNumberOfDiscards*/ null)); + final RegattaCreationParametersDTO regattaCreationParameters = new RegattaCreationParametersDTO( + seriesCreationParameters); + + 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)); + 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())); + } + private DynamicTrackedRace createTrackedRaceAndSetupRaceTimes(final List errors, final String trackedRaceName, TimePoint firstFixAt, TimePoint lastFixAt, final Regatta regatta, final RegattaLeaderboard regattaLeaderboard, final RaceColumn raceColumn, final Fleet fleet) From 2acd4d045bca7bdffd7015b001256fc858fc78e4 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 13 Apr 2018 09:56:40 +0200 Subject: [PATCH 29/59] Bug 4371: Refactored parts to new methods in ExpeditionAllInOneImporter --- .../impl/ExpeditionAllInOneImporter.java | 110 ++++++++++-------- 1 file changed, 63 insertions(+), 47 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 7c77ef9fa4c..81fb6802865 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -246,47 +246,22 @@ public class ExpeditionAllInOneImporter { final UUID eventId; final String leaderboardGroupName; final String regattaNameAndleaderboardName; - final RegattaLeaderboard regattaLeaderboard; // TODO Should we return all TrackedRaces and show several RaceBoard links to the user? final DynamicTrackedRace trackedRace; final List trackedRaces = new ArrayList<>(); final String fleetName; final String raceColumnName; if (importMode == ImportMode.NEW_EVENT) { - final String eventName = filenameWithDateTimeSuffix; - final String description = MessageFormat.format("Event imported from expedition file ''{0}'' on {1}", - filenameWithSuffix, importTimeString); - // TODO guess venue based on the reverse geocoder? - final String venueName = filename; leaderboardGroupName = filenameWithDateTimeSuffix; regattaNameAndleaderboardName = filenameWithDateTimeSuffix; raceColumnName = filename; - final RegattaIdentifier regattaIdentifier = new RegattaName(filenameWithDateTimeSuffix); - // This is just the default used in the UI - final Double buoyZoneRadiusInHullLengths = 3.0; - + eventId = UUID.randomUUID(); fleetName = LeaderboardNameConstants.DEFAULT_FLEET_NAME; - final String seriesName = Series.DEFAULT_NAME; - final Event event = service.addEvent(eventName, description, eventStartDate, eventEndDate, venueName, true, - UUID.randomUUID()); - eventId = event.getId(); - - final UUID courseAreaId = addDefaultCourseArea(event); - - final Regatta regatta = createRegattaWithOneRaceColumn(boatClassName, regattaNameAndleaderboardName, - fleetName, raceColumnName, regattaIdentifier, courseAreaId, buoyZoneRadiusInHullLengths, - seriesName); - 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); + trackedRace = createEventStructureWithASingleRaceAndTrackIt(filenameWithSuffix, boatClassName, errors, importTimeString, filename, + filenameWithDateTimeSuffix, trackedRaceName, discardThresholds, firstFixAt, lastFixAt, + eventStartDate, eventEndDate, eventId, leaderboardGroupName, regattaNameAndleaderboardName, + fleetName, raceColumnName); trackedRaces.add(trackedRace); } else { regattaNameAndleaderboardName = existingRegattaName; @@ -299,27 +274,16 @@ public class ExpeditionAllInOneImporter { if (leaderboard == null || !(leaderboard instanceof RegattaLeaderboard)) { return new ImporterResult(ERROR_MESSAGE_INVALID_LEADERBOARD); } - regattaLeaderboard = (RegattaLeaderboard) leaderboard; + final RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; - Event foundEvent = null; - LeaderboardGroup foundLeaderboardGroup = null; - search: for (Event event : service.getAllEvents()) { - for (LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { - for (Leaderboard lb : leaderboardGroup.getLeaderboards()) { - if (lb.equals(leaderboard)) { - foundEvent = event; - foundLeaderboardGroup = leaderboardGroup; - break search; - } - } - } - } - if (foundEvent == null) { + final Pair foundEventAndLeaderboardGroup = findEventAndLeaderboardGroupForExistingLeaderboard(leaderboard); + + if (foundEventAndLeaderboardGroup == null) { return new ImporterResult(ERROR_MESSAGE_INVALID_LEADERBOARD_EVENT_LINK); } // TODO should we extend the time range of the event to ensure that it includes the newly imported tracks' time ranges? - eventId = foundEvent.getId(); - leaderboardGroupName = foundLeaderboardGroup.getName(); + eventId = foundEventAndLeaderboardGroup.getA().getId(); + leaderboardGroupName = foundEventAndLeaderboardGroup.getB().getName(); if (importMode == ImportMode.NEW_COMPETITOR) { final Iterable raceColumns = regattaLeaderboard.getRaceColumns(); @@ -400,6 +364,58 @@ public class ExpeditionAllInOneImporter { } } + private Pair 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 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; + // TODO guess venue based on the reverse geocoder? + final String venueName = filename; + 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, venueName, 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 UUID addDefaultCourseArea(final Event event) { final String courseAreaName = "Default"; final UUID courseAreaId = UUID.randomUUID(); From 3ef48460dff8cb5a74b18c43dd67305dfbe65b7f Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 13 Apr 2018 09:58:02 +0200 Subject: [PATCH 30/59] Bug 4371: Removed unnecessary comment --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 81fb6802865..429812404b7 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -319,7 +319,6 @@ public class ExpeditionAllInOneImporter { throw new AllinOneImportException(e, errors); } } else if (importMode == ImportMode.NEW_RACE){ - // ImportMode.NEW_RACE final Iterable seriesInRegatta = regatta.getSeries(); if (Util.isEmpty(seriesInRegatta)) { return new ImporterResult(ERROR_MESSAGE_INVALID_SERIES); From b9c351234f294af9c4f4972a3640724b728db5df Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Mon, 16 Apr 2018 11:41:57 +0200 Subject: [PATCH 31/59] Bug 4371: Added locale parameter for expedition all in one importer as preperation for I18n of error messages --- .../common/dto/ExpeditionAllInOneConstants.java | 1 + .../ExpeditionAllInOneImportPanel.java | 4 ++++ .../impl/ExpeditionAllInOneImportServlet.java | 15 +++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/ExpeditionAllInOneConstants.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/ExpeditionAllInOneConstants.java index ac11b79ee99..7196c13bf99 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/ExpeditionAllInOneConstants.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/ExpeditionAllInOneConstants.java @@ -4,6 +4,7 @@ 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; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java index 9f45551b405..937d706c55e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java @@ -5,6 +5,7 @@ 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; @@ -13,6 +14,7 @@ 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; @@ -59,6 +61,8 @@ public class ExpeditionAllInOneImportPanel extends Composite implements Regattas 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); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java index 19859ca513a..8a13e7bf4c0 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java @@ -3,6 +3,7 @@ package com.sap.sailing.server.gateway.trackfiles.impl; import java.io.IOException; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; @@ -60,6 +61,7 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { String boatClassName = null; String regattaName = null; String importModeName = null; + String localeName = null; for (FileItem fi : fileItems) { if (!fi.isFormField()) { fileName = fi.getName(); @@ -74,6 +76,19 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { 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) { From 729ef3dd30161504e8880dfc618fd056a04ec740 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Mon, 16 Apr 2018 13:02:31 +0200 Subject: [PATCH 32/59] Bug 4371: Added placeholder to suggest fields --- .../gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java | 5 +++++ .../java/com/sap/sailing/gwt/ui/client/StringMessages.java | 1 + .../com/sap/sailing/gwt/ui/client/StringMessages.properties | 3 ++- .../sap/sailing/gwt/ui/client/StringMessages_de.properties | 3 ++- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java index 937d706c55e..cf7bbd7b847 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java @@ -1,6 +1,7 @@ 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; @@ -108,6 +109,8 @@ public class ExpeditionAllInOneImportPanel extends Composite implements Regattas 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); @@ -116,6 +119,8 @@ public class ExpeditionAllInOneImportPanel extends Composite implements Regattas 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); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index f65c1f8d190..99130dc6cae 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -2151,4 +2151,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String newExpeditionRace(); String newExpeditionCompetitor(); String selectOneCompetitorToMapTheImportedData(); + String startTypingForSuggestions(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index b34a09f3f09..57c15c0a15f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -2140,4 +2140,5 @@ 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. \ No newline at end of file +selectOneCompetitorToMapTheImportedData=Please select one competitor on the left side. The imported data will be mapped to this competitor. +startTypingForSuggestions=Start typing to get suggestions diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 695d4167616..ef58fdf40ef 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -2136,4 +2136,5 @@ 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. \ No newline at end of file +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 From 9cdb26bacab9de83fd1a6df08cf7ce1444490664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Mon, 16 Apr 2018 14:20:36 +0200 Subject: [PATCH 33/59] use i18n for allInOneImporterServlet --- .../impl/ExpeditionAllInOneImportServlet.java | 22 ++++--- .../impl/ExpeditionAllInOneImporter.java | 57 ++++++++----------- .../stringmessages/StringMessages.properties | 17 ++++++ 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java index 19859ca513a..03d0c9d94de 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java @@ -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; @@ -20,6 +22,7 @@ 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.impl.ResourceBundleStringMessagesImpl; import com.sap.sse.util.ServiceTrackerFactory; /** @@ -32,18 +35,18 @@ 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 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 ERROR_MESSAGE_REGATTA_MISSING = "No regatta name found!"; - private static final String ERROR_MESSAGE_UNKNOWN_IMPORT_MODE = "Unknown import mode!"; + private static final String STRING_MESSAGES_BASE_NAME = "stringmessages/StringMessages"; private ServiceTracker raceLogTrackingAdapterTracker; + private ResourceBundleStringMessagesImpl 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()); } /** @@ -60,6 +63,7 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { String boatClassName = null; String regattaName = null; String importModeName = null; + Locale locale = Locale.ENGLISH; for (FileItem fi : fileItems) { if (!fi.isFormField()) { fileName = fi.getName(); @@ -77,7 +81,7 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { } } if (fileItem == null) { - throw new AllinOneImportException(ERROR_MESSAGE_IMPORT_FILE_MISSING); + throw new AllinOneImportException(serverStringMessages.get(locale, "allInOneErrorImportFileMissing")); } final ImportMode importMode; if (importModeName == null) { @@ -86,19 +90,19 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { try { importMode = ImportMode.valueOf(importModeName); } catch (Exception e) { - throw new AllinOneImportException(ERROR_MESSAGE_UNKNOWN_IMPORT_MODE); + throw new AllinOneImportException(serverStringMessages.get(locale, "allInOneErrorUnknownImportMode")); } } if (importMode == ImportMode.NEW_EVENT) { if (boatClassName == null || boatClassName.isEmpty()) { - throw new AllinOneImportException(ERROR_MESSAGE_BOAT_CLASS_MISSING); + throw new AllinOneImportException(serverStringMessages.get(locale, "allInOneErrorMissingBoatClass")); } } else { if (regattaName == null || regattaName.isEmpty()) { - throw new AllinOneImportException(ERROR_MESSAGE_REGATTA_MISSING); + throw new AllinOneImportException(serverStringMessages.get(locale, "allInOneErrorMissingRegattaClass")); } } - importerResult = new ExpeditionAllInOneImporter(getService(), + importerResult = new ExpeditionAllInOneImporter(serverStringMessages, locale, getService(), raceLogTrackingAdapterTracker.getService().getAdapter(getService().getBaseDomainFactory()), getServiceFinderFactory(), getContext()).importFiles(fileName, fileItem, boatClassName, importMode, regattaName); } catch (AllinOneImportException e) { diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 429812404b7..38b4bb39917 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -12,6 +12,7 @@ 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.logging.Logger; @@ -76,6 +77,7 @@ import com.sap.sse.common.TypeBasedServiceFinderFactory; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.i18n.impl.ResourceBundleStringMessagesImpl; /** * Importer for expedition data that imports all available data for a boat: @@ -106,35 +108,18 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; * This importer is intended to be used by {@link ExpeditionAllInOneImportServlet}. */ public class ExpeditionAllInOneImporter { - private static final String ERROR_MESSAGE_INVALID_REGATTA_NAME = "Please enter a valid regatta name to proceed"; - - private static final String ERROR_MESSAGE_INVALID_IMPORTMODE = "Currently not handled ImportMode "; - - private static final String ERROR_MESSAGE_MULTI_SERIES = "There is more than one series in this regatta, cannot add race"; - - private static final String ERROR_MESSAGE_INVALID_SERIES = "There is no series in this regatta, cannot add race"; - - private static final String ERROR_MESSAGE_SPLITFLEET_NOT_SUPPORTED = "The expedition importer, cannot handle split fleet racing"; - - private static final String ERROR_MESSAGE_INVALID_RACE = "To add competitors, a race must be existing"; - - private static final String ERROR_MESSAGE_INVALID_LEADERBOARD_EVENT_LINK = "The Event for the leaderboard could not be obtained, please ensure the leaderboard is properly attached to an leaderboardgroup that is attached to an event"; - - private static final String ERROR_MESSAGE_INVALID_LEADERBOARD = "The Leaderboard could not be resolved, please ensure a leaderboard named like the regatta exists"; - - private static final String ERROR_MESSAGE_INVALID_REGATTA = "The regatta could not be resolved, please ensure the name is correct"; 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 final RacingEventService service; private final RaceLogTrackingAdapter adapter; private final TypeBasedServiceFinderFactory serviceFinderFactory; private final BundleContext context; + private ResourceBundleStringMessagesImpl serverStringMessages; + + private Locale locale; + public static class ImporterResult { final UUID eventId; final String leaderboardName, leaderboardGroupName, regattaName, raceName, raceColumnName, fleetName; @@ -176,8 +161,10 @@ public class ExpeditionAllInOneImporter { } } - public ExpeditionAllInOneImporter(final RacingEventService service, RaceLogTrackingAdapter adapter, + public ExpeditionAllInOneImporter(ResourceBundleStringMessagesImpl serverStringMessages, Locale locale, final RacingEventService service, RaceLogTrackingAdapter adapter, final TypeBasedServiceFinderFactory serviceFinderFactory, final BundleContext context) { + this.serverStringMessages = serverStringMessages; + this.locale = locale; this.service = service; this.adapter = adapter; this.serviceFinderFactory = serviceFinderFactory; @@ -202,7 +189,8 @@ 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(locale, "allInOneErrorGPSDataImportFailed")); } catch (IOException e1) { errors.addAll(jsonHolderForGpsFixImport.getErrorList()); throw new AllinOneImportException(e1, errors); @@ -216,7 +204,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(locale, "allInOneErrorSensorDataImportFailed")); } catch (IOException e1) { errors.addAll(jsonHolderForSensorFixImport.getErrorList()); throw new AllinOneImportException(e1, errors); @@ -268,18 +257,18 @@ public class ExpeditionAllInOneImporter { if (existingRegattaName != null && !existingRegattaName.isEmpty()) { final Regatta regatta = service.getRegattaByName(existingRegattaName); if (regatta == null) { - return new ImporterResult(ERROR_MESSAGE_INVALID_REGATTA); + return new ImporterResult(serverStringMessages.get(locale, "allInOneErrorInvalidData")); } final Leaderboard leaderboard = service.getLeaderboardByName(existingRegattaName); if (leaderboard == null || !(leaderboard instanceof RegattaLeaderboard)) { - return new ImporterResult(ERROR_MESSAGE_INVALID_LEADERBOARD); + return new ImporterResult(serverStringMessages.get(locale, "allInOneErrorInvalidLeaderBoard")); } final RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; final Pair foundEventAndLeaderboardGroup = findEventAndLeaderboardGroupForExistingLeaderboard(leaderboard); if (foundEventAndLeaderboardGroup == null) { - return new ImporterResult(ERROR_MESSAGE_INVALID_LEADERBOARD_EVENT_LINK); + return new ImporterResult(serverStringMessages.get(locale, "allInOneErrorInvalidLeaderBoardEventLink")); } // TODO should we extend the time range of the event to ensure that it includes the newly imported tracks' time ranges? eventId = foundEventAndLeaderboardGroup.getA().getId(); @@ -288,7 +277,7 @@ public class ExpeditionAllInOneImporter { if (importMode == ImportMode.NEW_COMPETITOR) { final Iterable raceColumns = regattaLeaderboard.getRaceColumns(); if (Util.isEmpty(raceColumns)) { - return new ImporterResult(ERROR_MESSAGE_INVALID_RACE); + return new ImporterResult(serverStringMessages.get(locale, "allInOneErrorInvalidRace")); } try { Fleet firstFleet = null; @@ -297,7 +286,7 @@ public class ExpeditionAllInOneImporter { for (RaceColumn raceColumn : raceColumns) { final Iterable fleets = raceColumn.getFleets(); if (Util.size(fleets) != 1) { - return new ImporterResult(ERROR_MESSAGE_SPLITFLEET_NOT_SUPPORTED); + return new ImporterResult(serverStringMessages.get(locale, "allInOneErrorSplitFleetNotSupported")); } final Fleet fleet = fleets.iterator().next(); DynamicTrackedRace trackedRaceForColumn = (DynamicTrackedRace) raceColumn.getTrackedRace(fleet); @@ -321,12 +310,12 @@ public class ExpeditionAllInOneImporter { } else if (importMode == ImportMode.NEW_RACE){ final Iterable seriesInRegatta = regatta.getSeries(); if (Util.isEmpty(seriesInRegatta)) { - return new ImporterResult(ERROR_MESSAGE_INVALID_SERIES); + return new ImporterResult(serverStringMessages.get(locale, "allInOneErrorInvalidSeries")); } final Series series = Util.get(seriesInRegatta, Util.size(seriesInRegatta) - 1); final Iterable fleets = series.getFleets(); if (Util.size(fleets) != 1) { - return new ImporterResult(ERROR_MESSAGE_MULTI_SERIES); + return new ImporterResult(serverStringMessages.get(locale, "allInOneErrorMultiSeries")); } final Fleet fleet = fleets.iterator().next(); fleetName = fleet.getName(); @@ -338,10 +327,10 @@ public class ExpeditionAllInOneImporter { raceColumn, fleet); trackedRaces.add(trackedRace); } else { - return new ImporterResult(ERROR_MESSAGE_INVALID_IMPORTMODE + importMode); + return new ImporterResult(serverStringMessages.get(locale, "allInOneErrorInvalidImportMode") + importMode); } } else { - return new ImporterResult(ERROR_MESSAGE_INVALID_REGATTA_NAME); + return new ImporterResult(serverStringMessages.get(locale, "allInOneErrorInvalidRegattaName")); } } @@ -515,7 +504,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(locale, "allInOneErrorBoatClassDeterminationFailed")); } } } diff --git a/java/com.sap.sailing.server/resources/stringmessages/StringMessages.properties b/java/com.sap.sailing.server/resources/stringmessages/StringMessages.properties index c67c2bf0f5e..2b977421b90 100644 --- a/java/com.sap.sailing.server/resources/stringmessages/StringMessages.properties +++ b/java/com.sap.sailing.server/resources/stringmessages/StringMessages.properties @@ -32,3 +32,20 @@ userProfile=User Profile imprint=Imprint privacy=Privacy salutation=Hallo {0}, + +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 to proceed +allInOneErrorInvalidImportMode=Currently 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 leaderboardgroup that is attached to an event +allInOneErrorInvalidLeaderBoard=The Leaderboard could not be resolved, please ensure a leaderboard named like the regatta exists +allInOneErrorSensorDataImportFailed=Failed to import sensor data! +allInOneErrorBoatClassDeterminationFailed=Failed to determine boat class! From f33ed40e6fc4dc7d33bb07623ea580dcf06b3632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Mon, 16 Apr 2018 15:28:16 +0200 Subject: [PATCH 34/59] bug4371 added messages bundle and german/english translation --- .../stringmessages/StringMessages.properties | 16 ++++++++++++++++ .../stringmessages/StringMessages_de.properties | 16 ++++++++++++++++ .../stringmessages/StringMessages_es.properties | 0 .../stringmessages/StringMessages_fr.properties | 0 .../stringmessages/StringMessages_ja.properties | 0 .../stringmessages/StringMessages_pt.properties | 0 .../stringmessages/StringMessages_ru.properties | 0 .../stringmessages/StringMessages_zh.properties | 0 .../impl/ExpeditionAllInOneImportServlet.java | 3 ++- .../impl/ExpeditionAllInOneImporter.java | 6 +++--- 10 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages.properties create mode 100644 java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_de.properties create mode 100644 java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_es.properties create mode 100644 java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_fr.properties create mode 100644 java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_ja.properties create mode 100644 java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_pt.properties create mode 100644 java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_ru.properties create mode 100644 java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_zh.properties diff --git a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages.properties b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages.properties new file mode 100644 index 00000000000..85b218c6c7b --- /dev/null +++ b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages.properties @@ -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 to proceed +allInOneErrorInvalidImportMode=Currently 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 leaderboardgroup that is attached to an event +allInOneErrorInvalidLeaderBoard=The Leaderboard could not be resolved, please ensure a leaderboard named like the regatta exists +allInOneErrorSensorDataImportFailed=Failed to import sensor data! +allInOneErrorBoatClassDeterminationFailed=Failed to determine boat class! diff --git a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_de.properties b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_de.properties new file mode 100644 index 00000000000..0c8d5eb249e --- /dev/null +++ b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_de.properties @@ -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 um fortzufahren +allInOneErrorInvalidImportMode=Derzeitig 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 keine split-fleet Rennen 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 mit den gleichen Namen wie die Regatta existiert +allInOneErrorSensorDataImportFailed=Fehler beim Import der Sensor-Daten! +allInOneErrorBoatClassDeterminationFailed=Fehler beim bestimmen der Bootsklasse diff --git a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_es.properties b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_es.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_fr.properties b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_fr.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_ja.properties b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_ja.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_pt.properties b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_pt.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_ru.properties b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_ru.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_zh.properties b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_zh.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java index 3c813f953b8..de9a854d8e2 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java @@ -22,6 +22,7 @@ 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; @@ -38,7 +39,7 @@ public class ExpeditionAllInOneImportServlet extends AbstractFileUploadServlet { private static final String STRING_MESSAGES_BASE_NAME = "stringmessages/StringMessages"; private ServiceTracker raceLogTrackingAdapterTracker; - private ResourceBundleStringMessagesImpl serverStringMessages; + private ResourceBundleStringMessages serverStringMessages; @Override public void init(ServletConfig config) throws ServletException { diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 6c27a44d69d..c48d5b38650 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -77,7 +77,7 @@ import com.sap.sse.common.TypeBasedServiceFinderFactory; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.i18n.impl.ResourceBundleStringMessagesImpl; +import com.sap.sse.i18n.ResourceBundleStringMessages; /** * Importer for expedition data that imports all available data for a boat: @@ -116,7 +116,7 @@ public class ExpeditionAllInOneImporter { private final TypeBasedServiceFinderFactory serviceFinderFactory; private final BundleContext context; - private ResourceBundleStringMessagesImpl serverStringMessages; + private ResourceBundleStringMessages serverStringMessages; private Locale uiLocale; public static class ImporterResult { @@ -160,7 +160,7 @@ public class ExpeditionAllInOneImporter { } } - public ExpeditionAllInOneImporter(ResourceBundleStringMessagesImpl serverStringMessages, Locale uiLocale, 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; From 5371590c152db3ba89214e3512805f9cd7bd7759 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Mon, 16 Apr 2018 15:44:20 +0200 Subject: [PATCH 35/59] Bug 4371: Adjusted the expedition import documentation to reflect the latest additions of implemented functionality --- wiki/howto/expeditionimport.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/wiki/howto/expeditionimport.md b/wiki/howto/expeditionimport.md index 165c378529f..3e650f9591a 100644 --- a/wiki/howto/expeditionimport.md +++ b/wiki/howto/expeditionimport.md @@ -14,9 +14,14 @@ While in "manual" mode these can all be imported separately, into an event/regat In the AdminConsole go to "Tracked races / Wind" and scroll down to the "Import full Expedition data" compartment. Choose the log file you'd like to import. It can be the ``.csv`` file or a compressed version of it, e.g., ``something.zip`` containing one or more ``.csv`` files or ``something.csv.gz`` in GZIP compression format. -Choose the boat class to which the log pertains and press the "Upload" button. Usually, web browsers display the upload progress in the status bar at the bottom of the browser window. Once the upload has finished, the server will take a few minutes to think about what you have uploaded. It will create an event named after the name of the log file with the time stamp of the upload appended, e.g., ``2017Dec15_2018-01-22T13:39:48.411``, also a leaderboard group of that name, a "regatta", a regatta leaderboard and a "race" within that regatta, representing the session to which the log belongs. Most of these names can be edited afterwards. It's just intended to give you a quick start. +There are 3 different modes for the upload you can choose of: +* Create New Event: You need to choose this mode for your first session or whenever you need an empty setup with only the new data. You need to choose the boat class to which the log pertains. During import, this mode will create an event named after the name of the log file with the time stamp of the upload appended, e.g., ``2017Dec15_2018-01-22T13:39:48.411``, also a leaderboard group of that name, a "regatta", a regatta leaderboard and a "race" within that regatta, representing the session to which the log belongs. Most of these names can be edited afterwards. It's just intended to give you a quick start. +* Add a new Competitor: You need to choose this mode in case you want to add the log of another competitor to your already imported tracks. In this case you need to select the regatta you intend to import the new track to. It is expected that the track files for several competitors cover approximately the same time range. The start and end times for generated races are automatically determined for the first uploaded log file. If you need to extend that time range afterwards, you can do that under "Connectors > Smartphone Tracking" by clicking the "Set tracking times" button for a race. +* Create a new race: You need to choose this mode to import a new distinct session (e.g. new day of trainig) into an existing regatta. In this case you need to select the regatta you intend to import the new track to. The name of the generated leaderboard column and race is determined from the uploaded file name. If the same name is already used in the given regatta, a unique timestamp is appended to ensure uniqueness of race names. -A popup should appear after a few minutes that lets you add or choose a competitor to which the data shall be associated. Either pick an existing competitor from the pool on the right by selecting one and pressing the little angular bracket pointing left ("<") or click the "Add" button at the top of the dialog to create a new competitor which is then added automatically. Press the "Save" button. +When uploading an expedition file using any of the described cases, a spinning animation will appear next to the upload button which indicates that the upload is running. This may take a while (some minutes) to finish depending on the size of the uploaded file. + +A popup should appear after a few minutes that lets you add or choose a competitor to which the data shall be associated. Either pick an existing competitor from the pool on the right by selecting one and pressing the little angular bracket pointing left ("<") or click the "Add" button at the top of the dialog to create a new competitor which is then added automatically. After adding any participating competitor, select exactly one entry in the left table to specify the competitor to whom the just uploaded log file will be associated. Press the "Save" button to accept the addition of competitors and mapping of the log file to the single selected one. After another short while another little popup dialog should be shown that offers two links: one to the overview page of the event just created, the other one navigating straight to the "race" viewer for the data just imported. As it is possible that the session recorded does not have a valid "race" start/finish date and no course defined, the session may not be listed in the event's "Races" tab under the "List Format." In this case choose "Competition Format" and your session should show up as a greyish "Planned" icon that you may click to enter the viewer (RaceBoard.html). This is where the race link from the popup will take you straight away. From f9e7f4c20fd9b4d8eabef1508c9e6c5b0a9bc657 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Mon, 16 Apr 2018 15:57:53 +0200 Subject: [PATCH 36/59] Bug 4371: Added release notes --- java/com.sap.sailing.www/release_notes_admin.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/com.sap.sailing.www/release_notes_admin.html b/java/com.sap.sailing.www/release_notes_admin.html index bfb5df1445f..e28728e354e 100755 --- a/java/com.sap.sailing.www/release_notes_admin.html +++ b/java/com.sap.sailing.www/release_notes_admin.html @@ -31,6 +31,8 @@ Any previously imported expedition tracks may be dropped and reimported to gain access to the newly introduced measures.
  • The settings dialog of the competitor charts in RaceBoard.html 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.
  • +
  • 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.
  • March 2018

    From ea28a2edd7d73a350bb9b3e5191a88478719b872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Mon, 16 Apr 2018 16:55:23 +0200 Subject: [PATCH 37/59] bug4371 removed messages from unrelated bundle --- .../stringmessages/StringMessages.properties | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/java/com.sap.sailing.server/resources/stringmessages/StringMessages.properties b/java/com.sap.sailing.server/resources/stringmessages/StringMessages.properties index 2b977421b90..c67c2bf0f5e 100644 --- a/java/com.sap.sailing.server/resources/stringmessages/StringMessages.properties +++ b/java/com.sap.sailing.server/resources/stringmessages/StringMessages.properties @@ -32,20 +32,3 @@ userProfile=User Profile imprint=Imprint privacy=Privacy salutation=Hallo {0}, - -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 to proceed -allInOneErrorInvalidImportMode=Currently 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 leaderboardgroup that is attached to an event -allInOneErrorInvalidLeaderBoard=The Leaderboard could not be resolved, please ensure a leaderboard named like the regatta exists -allInOneErrorSensorDataImportFailed=Failed to import sensor data! -allInOneErrorBoatClassDeterminationFailed=Failed to determine boat class! From 9b1b2f88b443a1cea41e55aff1e150c28f943946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Mon, 16 Apr 2018 19:01:31 +0200 Subject: [PATCH 38/59] bug4371 allow multiple races to be returned, eg for retracking them after competitor matching --- .../ExpeditionAllInOneAfterImportHandler.java | 29 ++++++++++------- .../ExpeditionAllInOneImportPanel.java | 5 +-- .../ExpeditionAllInOneImportResultDialog.java | 5 +-- .../ExpeditionDataImportResponse.java | 32 ++++++++++++------- .../race/TrackedRaceCreationResultDialog.java | 21 ++++++++---- .../impl/ExpeditionAllInOneImportServlet.java | 4 +-- .../impl/ExpeditionAllInOneImporter.java | 8 ++--- .../impl/ImportResultSerializer.java | 15 +++++++++ 8 files changed, 79 insertions(+), 40 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java index 0333303fcd8..7a175416058 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java @@ -40,30 +40,28 @@ 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 gpsFixesDeviceIDs; private List sensorFixesDeviceIDs; private final String sensorImporterType; + private List> raceEntries; + private String regattaName; public ExpeditionAllInOneAfterImportHandler(UUID eventId, String regattaName, String leaderboardName, - String leaderboardGroupName, String raceName, String raceColumnName, String fleetName, + String leaderboardGroupName, List> raceEntries, List gpsDeviceIds, List 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() { @Override @@ -228,7 +226,17 @@ public class ExpeditionAllInOneAfterImportHandler { private final void continueWithMappedDevices() { List racesToStopAndStartTrackingFor = new ArrayList<>(); - racesToStopAndStartTrackingFor.add(regattaAndRaceIdentifier); + final List> leaderboardRaceColumnFleetNames = new ArrayList<>(); + final List raceNames = new ArrayList<>(); + for(Triple 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(raceName); + } + sailingService.removeAndUntrackRaces(racesToStopAndStartTrackingFor, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -237,14 +245,13 @@ public class ExpeditionAllInOneAfterImportHandler { @Override public void onSuccess(Void result) { - final List> leaderboardRaceColumnFleetNames = new ArrayList<>(); - leaderboardRaceColumnFleetNames.add(new Triple<>(leaderboard.name, raceColumnName, fleetName)); sailingService.startRaceLogTracking(leaderboardRaceColumnFleetNames, /* trackWind */ false, /* correctWindByDeclination */ true, new AsyncCallback() { @Override public void onSuccess(Void result) { + new ExpeditionAllInOneImportResultDialog(event.id, regatta.getName(), - regattaAndRaceIdentifier.getRaceName(), leaderboard.getName(), + raceNames, leaderboard.getName(), leaderboardGroupName).show(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java index cf7bbd7b847..9879b698505 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java @@ -147,13 +147,14 @@ public class ExpeditionAllInOneImportPanel extends Composite implements Regattas formPanel.addSubmitCompleteHandler(event -> { validation.run(); busyIndicator.setBusy(false); + GWT.debugger(); 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.getRaceName(), - response.getRaceColumnName(), response.getFleetName(), response.getGpsDeviceIds(), + response.getLeaderboardName(), response.getLeaderboardGroupName(), response.getRaceEntries(), response.getGpsDeviceIds(), response.getSensorDeviceIds(), response.getSensorFixImporterType(), sailingService, errorReporter, stringMessages); regattaRefresher.fillRegattas(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportResultDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportResultDialog.java index 62ff2ffe953..065a5c7cc9a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportResultDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportResultDialog.java @@ -1,5 +1,6 @@ package com.sap.sailing.gwt.ui.adminconsole; +import java.util.List; import java.util.UUID; import com.sap.sailing.gwt.ui.client.StringMessages; @@ -7,9 +8,9 @@ import com.sap.sailing.gwt.ui.client.shared.race.TrackedRaceCreationResultDialog public class ExpeditionAllInOneImportResultDialog extends TrackedRaceCreationResultDialog { - public ExpeditionAllInOneImportResultDialog(UUID eventId, String regattaName, String raceName, + public ExpeditionAllInOneImportResultDialog(UUID eventId, String regattaName, List raceNames, String leaderboardName, String leaderboardGroupName) { super(StringMessages.INSTANCE.importFinished(), StringMessages.INSTANCE.importFinishedMessage(), eventId, - regattaName, raceName, leaderboardName, leaderboardGroupName); + regattaName, raceNames, leaderboardName, leaderboardGroupName); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/resulthandling/ExpeditionDataImportResponse.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/resulthandling/ExpeditionDataImportResponse.java index 46c7bc9e7e6..b4cecf552d1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/resulthandling/ExpeditionDataImportResponse.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/resulthandling/ExpeditionDataImportResponse.java @@ -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> getRaceEntries() { + ArrayList> 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(raceName, raceColumnName, fleetName)); + } + return raceNameRaceColumnNameFleetNameList; + } public final List getGpsDeviceIds() { return getStringList("gpsDeviceIds"); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java index e9bebd55f04..4cdc4d637fa 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java @@ -1,6 +1,8 @@ package com.sap.sailing.gwt.ui.client.shared.race; +import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.UUID; import com.google.gwt.user.client.ui.Anchor; @@ -20,7 +22,12 @@ public class TrackedRaceCreationResultDialog extends DataEntryDialog { private final VerticalPanel verticalPanel; - public TrackedRaceCreationResultDialog(String title, String message, UUID eventId, String regattaName, String raceName, + public TrackedRaceCreationResultDialog(String title, String message, UUID eventId, String regattaName, String raceNames, + String leaderboardName, String leaderboardGroupName) { + this(title, message, eventId, regattaName, Arrays.asList(new String[] { raceNames }), leaderboardName, leaderboardGroupName); + } + + public TrackedRaceCreationResultDialog(String title, String message, UUID eventId, String regattaName, List raceNames, String leaderboardName, String leaderboardGroupName) { super(title, message, StringMessages.INSTANCE.ok(), StringMessages.INSTANCE.cancel(), /* validator */ null, @@ -36,11 +43,13 @@ public class TrackedRaceCreationResultDialog extends DataEntryDialog { 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); + for(String raceName:raceNames) { + Anchor raceboardAnchor = new Anchor(StringMessages.INSTANCE.importFinishedGotoRaceboard(), + EntryPointWithSettingsLinkFactory.createRaceBoardLinkWithDefaultSettings(eventId, leaderboardName, + leaderboardGroupName, regattaName, raceName)); + raceboardAnchor.setTarget("_blank"); + verticalPanel.add(raceboardAnchor); + } if (eventId != null) { Anchor eventAnchor = new Anchor(StringMessages.INSTANCE.importFinishedGotoEvent(), diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java index de9a854d8e2..09cae128164 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImportServlet.java @@ -136,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)); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index c48d5b38650..8d6c55e0f14 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -76,6 +76,7 @@ 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; @@ -121,7 +122,8 @@ public class ExpeditionAllInOneImporter { public static class ImporterResult { final UUID eventId; - final String leaderboardName, leaderboardGroupName, regattaName, raceName, raceColumnName, fleetName; + final List> raceNameRaceColumnNameFleetnameList = new ArrayList<>(); + final String leaderboardName, leaderboardGroupName, regattaName; final List importGpsFixData, importSensorFixData; final String sensorFixImporterType; final List errorList = new ArrayList<>(); @@ -150,9 +152,7 @@ public class ExpeditionAllInOneImporter { this.leaderboardName = leaderboardName; this.leaderboardGroupName = leaderboardGroupName; this.regattaName = regattaAndRaceIdentifier.getRegattaName(); - this.raceName = regattaAndRaceIdentifier.getRaceName(); - this.raceColumnName = raceColumnName; - this.fleetName = fleetName; + raceNameRaceColumnNameFleetnameList.add(new Triple(regattaAndRaceIdentifier.getRaceName(), raceColumnName, fleetName)); this.importGpsFixData = importGpsFixData; this.importSensorFixData = importSensorFixData; this.sensorFixImporterType = sensorFixImporterType; diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ImportResultSerializer.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ImportResultSerializer.java index ed3510da237..105caea8a0c 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ImportResultSerializer.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ImportResultSerializer.java @@ -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 errorList) { return serializeList(errorList, ImportResultSerializer::serializeError); } + + public static JSONArray serializeRaceList(List> raceNameRaceColumnNameFleetnameList) { + return serializeList(raceNameRaceColumnNameFleetnameList, ImportResultSerializer::serializeRaceEntry); + } + + private static JSONObject serializeRaceEntry(Triple 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; } + + } \ No newline at end of file From 83126389790abe22c90b8e6cf85d650bbf6015a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Tue, 17 Apr 2018 09:43:36 +0200 Subject: [PATCH 39/59] bug4371 show raceColumnName, if multiple races are touched, in the linkdialog --- .../ExpeditionAllInOneImportResultDialog.java | 5 ++- .../race/TrackedRaceCreationResultDialog.java | 43 +++++++++++-------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportResultDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportResultDialog.java index 065a5c7cc9a..f3952b41c10 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportResultDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportResultDialog.java @@ -5,12 +5,13 @@ 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, List raceNames, + public ExpeditionAllInOneImportResultDialog(UUID eventId, String regattaName, List> raceEntries, String leaderboardName, String leaderboardGroupName) { super(StringMessages.INSTANCE.importFinished(), StringMessages.INSTANCE.importFinishedMessage(), eventId, - regattaName, raceNames, leaderboardName, leaderboardGroupName); + regattaName, raceEntries, leaderboardName, leaderboardGroupName); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java index 4cdc4d637fa..05ade19f6b2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java @@ -1,6 +1,6 @@ package com.sap.sailing.gwt.ui.client.shared.race; -import java.util.Arrays; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; @@ -11,26 +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 { private final VerticalPanel verticalPanel; - public TrackedRaceCreationResultDialog(String title, String message, UUID eventId, String regattaName, String raceNames, - String leaderboardName, String leaderboardGroupName) { - this(title, message, eventId, regattaName, Arrays.asList(new String[] { raceNames }), leaderboardName, leaderboardGroupName); + 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); } - - public TrackedRaceCreationResultDialog(String title, String message, UUID eventId, String regattaName, List raceNames, - String leaderboardName, String leaderboardGroupName) { - super(title, message, - StringMessages.INSTANCE.ok(), StringMessages.INSTANCE.cancel(), /* validator */ null, + + private static List> createSingleRaceList(String raceName) { + ArrayList> rv = new ArrayList<>(); + rv.add(new Pair(raceName, null)); + return rv; + } + + public TrackedRaceCreationResultDialog(String title, String message, UUID eventId, String regattaName, + List> raceNameRaceColumnName, String leaderboardName, String leaderboardGroupName) { + super(title, message, StringMessages.INSTANCE.ok(), StringMessages.INSTANCE.cancel(), /* validator */ null, new DialogCallback() { @Override public void ok(Void editedObject) { @@ -43,21 +49,24 @@ public class TrackedRaceCreationResultDialog extends DataEntryDialog { verticalPanel = new VerticalPanel(); verticalPanel.setSpacing(20); - for(String raceName:raceNames) { - Anchor raceboardAnchor = new Anchor(StringMessages.INSTANCE.importFinishedGotoRaceboard(), + boolean multiRace = raceNameRaceColumnName.size() > 1; + for (Pair raceName : raceNameRaceColumnName) { + String anchorLabel = multiRace ? StringMessages.INSTANCE.importFinishedGotoRaceboard() + raceName.getB() + : StringMessages.INSTANCE.importFinishedGotoRaceboard(); + Anchor raceboardAnchor = new Anchor(anchorLabel, EntryPointWithSettingsLinkFactory.createRaceBoardLinkWithDefaultSettings(eventId, leaderboardName, - leaderboardGroupName, regattaName, raceName)); + 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 From 5d0aded3c1f48603647fa3a93a1fc8d6998b47cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Tue, 17 Apr 2018 09:43:48 +0200 Subject: [PATCH 40/59] bug4371 show raceColumnName, if multiple races are touched, in the linkdialog --- .../adminconsole/ExpeditionAllInOneAfterImportHandler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java index 7a175416058..07c3d602ec3 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java @@ -20,6 +20,7 @@ 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; @@ -227,14 +228,14 @@ public class ExpeditionAllInOneAfterImportHandler { private final void continueWithMappedDevices() { List racesToStopAndStartTrackingFor = new ArrayList<>(); final List> leaderboardRaceColumnFleetNames = new ArrayList<>(); - final List raceNames = new ArrayList<>(); + final List> raceNames = new ArrayList<>(); for(Triple 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(raceName); + raceNames.add(new Pair(raceName, fleetName)); } sailingService.removeAndUntrackRaces(racesToStopAndStartTrackingFor, new AsyncCallback() { @@ -249,7 +250,6 @@ public class ExpeditionAllInOneAfterImportHandler { /* correctWindByDeclination */ true, new AsyncCallback() { @Override public void onSuccess(Void result) { - new ExpeditionAllInOneImportResultDialog(event.id, regatta.getName(), raceNames, leaderboard.getName(), leaderboardGroupName).show(); From 0de6631ce173b216144d53306855868b8bcbb2f3 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Tue, 17 Apr 2018 09:47:45 +0200 Subject: [PATCH 41/59] Bug 4371: In case of import for a new competitor there may be multiple affected races --- .../impl/ExpeditionAllInOneImporter.java | 55 ++++++++----------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 8d6c55e0f14..e797eb11dbb 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -34,10 +34,8 @@ 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.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; @@ -129,13 +127,13 @@ public class ExpeditionAllInOneImporter { final List errorList = new ArrayList<>(); public ImporterResult(String error) { - this(null, "", "", new RegattaNameAndRaceName("", ""), "", "", Collections.emptyList(), + this(null, "", "", "", Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), "", Collections.emptyList()); errorList.add(new ErrorImportDTO(error)); } public ImporterResult(Throwable exception, List additionalErrors) { - this(null, "", "", new RegattaNameAndRaceName("", ""), "", "", Collections.emptyList(), + this(null, "", "","", Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), "", Collections.emptyList()); errorList.add(new ErrorImportDTO(exception.getClass().getName(), exception.getMessage())); if (additionalErrors != null) { @@ -144,15 +142,16 @@ public class ExpeditionAllInOneImporter { } private ImporterResult(final UUID eventId, final String leaderboardName, String leaderboardGroupName, - final RegattaAndRaceIdentifier regattaAndRaceIdentifier, final String raceColumnName, - final String fleetName, final List importGpsFixData, - final List importSensorFixData, final String sensorFixImporterType, - List errors) { + final String regattaName, List> raceNameRaceColumnNameFleetnameList, + final List importGpsFixData, final List importSensorFixData, + final String sensorFixImporterType, List errors) { this.eventId = eventId; this.leaderboardName = leaderboardName; this.leaderboardGroupName = leaderboardGroupName; - this.regattaName = regattaAndRaceIdentifier.getRegattaName(); - raceNameRaceColumnNameFleetnameList.add(new Triple(regattaAndRaceIdentifier.getRaceName(), raceColumnName, fleetName)); + this.regattaName = regattaName; + if (raceNameRaceColumnNameFleetnameList != null) { + this.raceNameRaceColumnNameFleetnameList.addAll(raceNameRaceColumnNameFleetnameList); + } this.importGpsFixData = importGpsFixData; this.importSensorFixData = importSensorFixData; this.sensorFixImporterType = sensorFixImporterType; @@ -234,23 +233,21 @@ public class ExpeditionAllInOneImporter { final UUID eventId; final String leaderboardGroupName; final String regattaNameAndleaderboardName; - // TODO Should we return all TrackedRaces and show several RaceBoard links to the user? - final DynamicTrackedRace trackedRace; + final List> raceNameRaceColumnNameFleetnameList = new ArrayList<>(); final List trackedRaces = new ArrayList<>(); - final String fleetName; - final String raceColumnName; if (importMode == ImportMode.NEW_EVENT) { leaderboardGroupName = filenameWithDateTimeSuffix; regattaNameAndleaderboardName = filenameWithDateTimeSuffix; - raceColumnName = filename; + String raceColumnName = filename; eventId = UUID.randomUUID(); - fleetName = LeaderboardNameConstants.DEFAULT_FLEET_NAME; + String fleetName = LeaderboardNameConstants.DEFAULT_FLEET_NAME; - trackedRace = createEventStructureWithASingleRaceAndTrackIt(filenameWithSuffix, boatClassName, errors, importTimeString, filename, + 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)); } else { regattaNameAndleaderboardName = existingRegattaName; if (existingRegattaName != null && !existingRegattaName.isEmpty()) { @@ -279,9 +276,6 @@ public class ExpeditionAllInOneImporter { return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorInvalidRace")); } try { - Fleet firstFleet = null; - DynamicTrackedRace firstTrackedRace = null; - RaceColumn firstRaceColumn = null; for (RaceColumn raceColumn : raceColumns) { final Iterable fleets = raceColumn.getFleets(); if (Util.size(fleets) != 1) { @@ -293,16 +287,10 @@ public class ExpeditionAllInOneImporter { trackedRaceForColumn = trackRace(regattaLeaderboard, raceColumn, fleet); } trackedRaces.add(trackedRaceForColumn); - if (firstTrackedRace == null) { - firstTrackedRace = trackedRaceForColumn; - firstFleet = fleet; - firstRaceColumn = raceColumn; - } + raceNameRaceColumnNameFleetnameList + .add(new Triple<>(trackedRaceForColumn.getRaceIdentifier().getRaceName(), + raceColumn.getName(), fleet.getName())); } - // TODO we remember the first trackedRace for now. Should we remember all? - trackedRace = firstTrackedRace; - fleetName = firstFleet.getName(); - raceColumnName = firstRaceColumn.getName(); } catch (Exception e) { throw new AllinOneImportException(e, errors); } @@ -317,14 +305,15 @@ public class ExpeditionAllInOneImporter { return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorMultiSeries")); } final Fleet fleet = fleets.iterator().next(); - fleetName = fleet.getName(); + final String fleetName = fleet.getName(); // When uploading files with identical name, the second RaceColumn will be named with the upload time in its name - raceColumnName = regatta.getRaceColumnByName(filename) == null ? filename : filenameWithDateTimeSuffix; + final String raceColumnName = regatta.getRaceColumnByName(filename) == null ? filename : filenameWithDateTimeSuffix; final RaceColumn raceColumn = service.apply(new AddColumnToSeries(regatta.getRegattaIdentifier(), series.getName(), raceColumnName)); - trackedRace = createTrackedRaceAndSetupRaceTimes(errors, trackedRaceName, firstFixAt, lastFixAt, regatta, regattaLeaderboard, + 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); } @@ -343,7 +332,7 @@ public class ExpeditionAllInOneImporter { trackedRaces, streamsWithFilenames); return new ImporterResult(eventId, regattaNameAndleaderboardName, leaderboardGroupName, - trackedRace.getRaceIdentifier(), raceColumnName, fleetName, + regattaNameAndleaderboardName, raceNameRaceColumnNameFleetnameList, jsonHolderForGpsFixImport.getImportResult(), jsonHolderForSensorFixImport.getImportResult(), sensorFixImporterType, errors); } catch (Exception e) { From c29d0872db35a238689148df5d956ffbfac26f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Tue, 17 Apr 2018 10:24:12 +0200 Subject: [PATCH 42/59] bug4371 show raceColumn name instead of fleetName --- .../ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java index 07c3d602ec3..4aa22ae1fa2 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java @@ -235,7 +235,7 @@ public class ExpeditionAllInOneAfterImportHandler { String fleetName= race.getC(); racesToStopAndStartTrackingFor.add(new RegattaNameAndRaceName(regattaName, raceName)); leaderboardRaceColumnFleetNames.add(new Triple<>(leaderboard.name, raceColumnName, fleetName)); - raceNames.add(new Pair(raceName, fleetName)); + raceNames.add(new Pair(raceName, raceColumnName)); } sailingService.removeAndUntrackRaces(racesToStopAndStartTrackingFor, new AsyncCallback() { From 386858a6fed6b38cd8d3aa1d1d17ac623d3d7dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Tue, 17 Apr 2018 11:14:34 +0200 Subject: [PATCH 43/59] bug4371 adjusted expedition readme to use nginx webserver --- wiki/howto/expeditionimport.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wiki/howto/expeditionimport.md b/wiki/howto/expeditionimport.md index 3e650f9591a..680d35b8f66 100644 --- a/wiki/howto/expeditionimport.md +++ b/wiki/howto/expeditionimport.md @@ -33,9 +33,7 @@ The general procedure for linking a video to a race is explained [[here|wiki/how ### Local Video (no Upload Required) -First of all, you'll need a web server running locally which allows you to make a directory on your local hard disk containing your video files accessible through HTTP. [[Here|wiki/howto/setup/webserver/chrome-webserver]] is a description of how to set this up, using a little web server that runs integrated in your Chrome browser. - -More specifically, [[this section|https://wiki.sapsailing.com/wiki/howto/setup/webserver/chrome-webserver#setup-locally-hosted-360-videos_adding-a-360-video]] then explains how to link a panoramic 360° video, choosing the correct file type. +First of all, you'll need a web server running locally which allows you to make a directory on your local hard disk containing your video files accessible through HTTP. [[Here|wiki/howto/setup/webserver/nginx-webserver]] is a description of how to set this up, using a little web server that runs on all platforms. ### Uploading through AdminConsole From af71ab1c7e75dea6799c90daa6cc0b9d6ef7977e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Tue, 17 Apr 2018 11:43:03 +0200 Subject: [PATCH 44/59] bug4371 extend the event if necessary, to enclosure newly added tracks --- .../impl/ExpeditionAllInOneImporter.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index e797eb11dbb..91aa58ba0f7 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -16,6 +16,8 @@ import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import org.apache.commons.fileupload.FileItem; import org.osgi.framework.BundleContext; @@ -266,8 +268,9 @@ public class ExpeditionAllInOneImporter { if (foundEventAndLeaderboardGroup == null) { return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorInvalidLeaderBoardEventLink")); } - // TODO should we extend the time range of the event to ensure that it includes the newly imported tracks' time ranges? + eventId = foundEventAndLeaderboardGroup.getA().getId(); + ensureEventLongEnough(firstFixAt, lastFixAt, eventId); leaderboardGroupName = foundEventAndLeaderboardGroup.getB().getName(); if (importMode == ImportMode.NEW_COMPETITOR) { @@ -340,6 +343,20 @@ public class ExpeditionAllInOneImporter { } } + 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 leaderboardGroups = StreamSupport.stream(event.getLeaderboardGroups().spliterator(), false).map(t -> t.getId()).collect(Collectors.toList()); + service.updateEvent(eventId, 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 findEventAndLeaderboardGroupForExistingLeaderboard(final Leaderboard leaderboard) { for (Event event : service.getAllEvents()) { for (LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { From 1ae53ea89e215114b1a5859f8ab7b513cc92718e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Tue, 17 Apr 2018 14:06:45 +0200 Subject: [PATCH 45/59] bug4371 initial reverse geocoding of venue --- .../impl/ExpeditionAllInOneImporter.java | 66 +++++++++++++++++-- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 91aa58ba0f7..2700d1a0fab 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -15,11 +15,14 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.UUID; +import java.util.function.Consumer; +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; @@ -35,6 +38,8 @@ 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.RegattaIdentifier; import com.sap.sailing.domain.common.RegattaName; @@ -47,19 +52,24 @@ 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; @@ -72,6 +82,7 @@ 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; @@ -112,6 +123,8 @@ public class ExpeditionAllInOneImporter { private static final Logger logger = Logger.getLogger(ExpeditionAllInOneImporter.class.getName()); + private static final double VENUE_RANGE_CHECK = 10; + private final RacingEventService service; private final RaceLogTrackingAdapter adapter; private final TypeBasedServiceFinderFactory serviceFinderFactory; @@ -196,6 +209,7 @@ public class ExpeditionAllInOneImporter { throw new AllinOneImportException(e1, errors); } errors.addAll(jsonHolderForGpsFixImport.getErrorList()); + final ImportResultDTO jsonHolderForSensorFixImport = new ImportResultDTO(logger); final String sensorFixImporterType = DoubleVectorFixImporter.EXPEDITION_EXTENDED_TYPE; @@ -228,7 +242,6 @@ public class ExpeditionAllInOneImporter { lastFixAt = deviceTrackEnd; } } - final TimePoint eventStartDate = firstFixAt; final TimePoint eventEndDate = lastFixAt; @@ -243,13 +256,13 @@ public class ExpeditionAllInOneImporter { 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()) { @@ -354,7 +367,11 @@ public class ExpeditionAllInOneImporter { endDate = lastFixAt; } Iterable leaderboardGroups = StreamSupport.stream(event.getLeaderboardGroups().spliterator(), false).map(t -> t.getId()).collect(Collectors.toList()); - service.updateEvent(eventId, event.getName(), event.getDescription(), startDate, endDate, event.getVenue().getName(), event.isPublic(), leaderboardGroups, event.getOfficialWebsiteURL(), event.getBaseURL(), event.getSailorsInfoWebsiteURLs(), event.getImages(), event.getVideos(),event.getWindFinderReviewedSpotsCollectionIds()); + + 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 findEventAndLeaderboardGroupForExistingLeaderboard(final Leaderboard leaderboard) { @@ -377,8 +394,7 @@ public class ExpeditionAllInOneImporter { final UUID eventId, final String leaderboardGroupName, final String regattaNameAndleaderboardName, final String fleetName, final String raceColumnName) throws AllinOneImportException { final DynamicTrackedRace trackedRace; - // TODO guess venue based on the reverse geocoder? - final String venueName = filename; + final String eventName = filenameWithDateTimeSuffix; final String description = MessageFormat.format("Event imported from expedition file ''{0}'' on {1}", filenameWithSuffix, importTimeString); @@ -388,7 +404,7 @@ public class ExpeditionAllInOneImporter { final String seriesName = Series.DEFAULT_NAME; - final Event event = service.addEvent(eventName, description, eventStartDate, eventEndDate, venueName, true, + final Event event = service.addEvent(eventName, description, eventStartDate, eventEndDate, filename, true, eventId); final UUID courseAreaId = addDefaultCourseArea(event); @@ -409,6 +425,44 @@ public class ExpeditionAllInOneImporter { return trackedRace; } + private void updateVenueName(String filename, List list, UUID eventId) { + for (TrackImportDTO f : list) { + TrackFileImportDeviceIdentifier deviceIdentifier = TrackFileImportDeviceIdentifierImpl + .getOrCreate(f.getDevice()); + final TimePoint end = f.getRange().to(); + try { + service.getSensorFixStore().loadFixes(new Consumer() { + @Override + public void accept(GPSFix lastFix) { + Position pos = lastFix.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 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())); + } + } catch (IOException | ParseException e) { + logger.log(Level.WARNING, "Could not reverse determine location " + pos, e); + } + } + } + }, deviceIdentifier, end, end, true); + } 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(); From b21d0fb7b1a8ae7f12e96cb65b28a8acbbfc0ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Tue, 17 Apr 2018 14:27:32 +0200 Subject: [PATCH 46/59] bug4371 properly abort reversegeocoder after a venue was found --- .../impl/ExpeditionAllInOneImporter.java | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 2700d1a0fab..c18d28d373c 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -15,7 +15,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.UUID; -import java.util.function.Consumer; +import java.util.concurrent.CompletableFuture; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -431,32 +431,33 @@ public class ExpeditionAllInOneImporter { .getOrCreate(f.getDevice()); final TimePoint end = f.getRange().to(); try { - service.getSensorFixStore().loadFixes(new Consumer() { - @Override - public void accept(GPSFix lastFix) { - Position pos = lastFix.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 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())); - } - } catch (IOException | ParseException e) { - logger.log(Level.WARNING, "Could not reverse determine location " + pos, e); + final CompletableFuture 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 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); } } - }, deviceIdentifier, end, end, true); + } } catch (NoCorrespondingServiceRegisteredException | TransformationException e) { logger.log(Level.WARNING, "Could not reverse determine location", e); } From aa442bd9ab9a9470ead300f280d06c8d5756dc26 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Tue, 17 Apr 2018 15:14:08 +0200 Subject: [PATCH 47/59] Bug 4371: Improved messages --- .../main/java/com/sap/sailing/gwt/ui/client/StringMessages.java | 1 + .../com/sap/sailing/gwt/ui/client/StringMessages.properties | 1 + .../com/sap/sailing/gwt/ui/client/StringMessages_de.properties | 1 + .../ui/client/shared/race/TrackedRaceCreationResultDialog.java | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 99130dc6cae..14610f4f38b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -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); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 57c15c0a15f..12468af9e06 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -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} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index ef58fdf40ef..e3192526304 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -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} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java index 05ade19f6b2..93d9a34dada 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/race/TrackedRaceCreationResultDialog.java @@ -51,7 +51,7 @@ public class TrackedRaceCreationResultDialog extends DataEntryDialog { verticalPanel.setSpacing(20); boolean multiRace = raceNameRaceColumnName.size() > 1; for (Pair raceName : raceNameRaceColumnName) { - String anchorLabel = multiRace ? StringMessages.INSTANCE.importFinishedGotoRaceboard() + raceName.getB() + String anchorLabel = multiRace ? StringMessages.INSTANCE.importFinishedGotoRaceboardWithName(raceName.getB()) : StringMessages.INSTANCE.importFinishedGotoRaceboard(); Anchor raceboardAnchor = new Anchor(anchorLabel, EntryPointWithSettingsLinkFactory.createRaceBoardLinkWithDefaultSettings(eventId, leaderboardName, From 578509135ed88e16049a649fd86daa6130988f2f Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Tue, 17 Apr 2018 15:23:06 +0200 Subject: [PATCH 48/59] Bug 4371: Improved I18n --- .../stringmessages/StringMessages.properties | 10 +++++----- .../stringmessages/StringMessages_de.properties | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages.properties b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages.properties index 85b218c6c7b..3990a9ad3ac 100644 --- a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages.properties +++ b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages.properties @@ -4,13 +4,13 @@ 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 to proceed -allInOneErrorInvalidImportMode=Currently not handled ImportMode +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 +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 leaderboardgroup that is attached to an event -allInOneErrorInvalidLeaderBoard=The Leaderboard could not be resolved, please ensure a leaderboard named like the regatta exists +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! diff --git a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_de.properties b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_de.properties index 0c8d5eb249e..0a119dde79c 100644 --- a/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_de.properties +++ b/java/com.sap.sailing.server.gateway/resources/stringmessages/StringMessages_de.properties @@ -3,14 +3,14 @@ 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 um fortzufahren -allInOneErrorInvalidImportMode=Derzeitig nicht unterstützter Importmodus +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 keine split-fleet Rennen importieren +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 mit den gleichen Namen wie die Regatta existiert +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 +allInOneErrorBoatClassDeterminationFailed=Fehler beim Bestimmen der Bootsklasse From c84b83c99a6996691e24573c6be2de0a7f99d267 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Tue, 17 Apr 2018 15:23:20 +0200 Subject: [PATCH 49/59] Formatting change only --- .../gateway/trackfiles/impl/ExpeditionAllInOneImporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index c18d28d373c..fa880422da9 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -310,7 +310,7 @@ public class ExpeditionAllInOneImporter { } catch (Exception e) { throw new AllinOneImportException(e, errors); } - } else if (importMode == ImportMode.NEW_RACE){ + } else if (importMode == ImportMode.NEW_RACE) { final Iterable seriesInRegatta = regatta.getSeries(); if (Util.isEmpty(seriesInRegatta)) { return new ImporterResult(serverStringMessages.get(uiLocale, "allInOneErrorInvalidSeries")); From 53cd79d563a06f2f03341117559c763f93ebae3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Wed, 18 Apr 2018 08:52:00 +0200 Subject: [PATCH 50/59] bug4454 use i18n for slicing errors, allow errordialog to display the messages --- .../domain/common/ServiceException.java | 15 ++++++++++++ .../sailing/gwt/ui/client/SailingService.java | 7 ++++-- .../gwt/ui/raceboard/SliceRaceHandler.java | 5 ++-- .../gwt/ui/server/SailingServiceImpl.java | 23 ++++++++++++++----- .../stringmessages/StringMessages.properties | 5 ++++ .../StringMessages_de.properties | 5 ++++ .../StringMessages_es.properties | 0 .../StringMessages_fr.properties | 0 .../StringMessages_ja.properties | 0 .../StringMessages_pt.properties | 0 .../StringMessages_ru.properties | 0 .../StringMessages_zh.properties | 0 .../sse/gwt/client/AbstractEntryPoint.java | 5 ++++ .../sse/gwt/client/DefaultErrorReporter.java | 11 +++++++++ .../com/sap/sse/gwt/client/ErrorReporter.java | 5 +++- 15 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ServiceException.java create mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages.properties create mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_de.properties create mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_es.properties create mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_fr.properties create mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_ja.properties create mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_pt.properties create mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_ru.properties create mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_zh.properties diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ServiceException.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ServiceException.java new file mode 100644 index 00000000000..5344971b409 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ServiceException.java @@ -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); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index 65cd0fd1a68..0fd8f2c3a10 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -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,10 @@ 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 + * @throws NotFoundException */ - RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo); + RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException, NotFoundException; /** * Returns specific data needed for the slicing UI. diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SliceRaceHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SliceRaceHandler.java index de5fdc848b4..1f7fb0b95d2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SliceRaceHandler.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SliceRaceHandler.java @@ -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 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index c7502b8ba2f..0c635c29f9a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -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 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 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, NotFoundException { + Locale locale = Locale.ENGLISH; + 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 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")); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages.properties new file mode 100644 index 00000000000..0040ab67af0 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages.properties @@ -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 \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_de.properties new file mode 100644 index 00000000000..456ecd8cddf --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_de.properties @@ -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 \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_es.properties b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_es.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_fr.properties b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_fr.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_ja.properties b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_ja.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_pt.properties b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_pt.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_ru.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages_zh.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/AbstractEntryPoint.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/AbstractEntryPoint.java index b67854786a5..e18ae73cd74 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/AbstractEntryPoint.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/AbstractEntryPoint.java @@ -63,6 +63,11 @@ public abstract class AbstractEntryPoint 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) { diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/DefaultErrorReporter.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/DefaultErrorReporter.java index d32305fa23d..dab48bda285 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/DefaultErrorReporter.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/DefaultErrorReporter.java @@ -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 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() + "

    "); + errorDialogBox.center(); + dialogCloseButton.setFocus(true); + } + @Override public void reportError(String message) { errorDialogBox.setText(message); diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/ErrorReporter.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/ErrorReporter.java index fff759af1af..6ed21ab2981 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/ErrorReporter.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/ErrorReporter.java @@ -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(); + } From bb760d6d3f07e5f083d49a6f384b6cb99c3ad9fd Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 18 Apr 2018 09:30:04 +0200 Subject: [PATCH 51/59] Bug 4371: Added metadata for additional translation files --- translation_v2.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/translation_v2.json b/translation_v2.json index e9a30c0e72d..d1ea0651227 100644 --- a/translation_v2.json +++ b/translation_v2.json @@ -143,6 +143,23 @@ "pseudoLocFolderPath":"." } ] + }, + { + "collectionName":"SailingServerGateway", + "folders":[ + { + "startingFolderPath":"java/com.sap.sailing.server.gateway/resources/stringmessages", + "sourceFilters":[ + "**/StringMessages*.properties" + ], + "excludedSourceFilters":[ + "**/*_zh.properties" + ], + "xlfFolderPath":"./XLF", + "targetFolderPath":".", + "pseudoLocFolderPath":"." + } + ] } ], "defaultConfiguration":{ From 6eabdb1d671d17b4cbcdb4386466e0f43294a2eb Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 18 Apr 2018 09:35:35 +0200 Subject: [PATCH 52/59] Bug 4454: Added metadata for additional translation files --- translation_v2.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/translation_v2.json b/translation_v2.json index e9a30c0e72d..1a94cf95be0 100644 --- a/translation_v2.json +++ b/translation_v2.json @@ -143,6 +143,23 @@ "pseudoLocFolderPath":"." } ] + }, + { + "collectionName":"SailingGwtUi", + "folders":[ + { + "startingFolderPath":"java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages", + "sourceFilters":[ + "**/StringMessages*.properties" + ], + "excludedSourceFilters":[ + "**/*_zh.properties" + ], + "xlfFolderPath":"./XLF", + "targetFolderPath":".", + "pseudoLocFolderPath":"." + } + ] } ], "defaultConfiguration":{ From 9b3c2a366995f010c56c70826102256c937e5636 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 18 Apr 2018 11:05:12 +0200 Subject: [PATCH 53/59] Bug 4454: I18n improvement --- .../src/main/resources/stringmessages/StringMessages.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages.properties index 0040ab67af0..47c529b9626 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/stringmessages/StringMessages.properties @@ -1,5 +1,5 @@ slicingCannotSliceRace=Can not slice race -slicingRaceColumnAlreadyUsedThe=race column name is already used in the given regatta +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 \ No newline at end of file From 7b90a187cbc822903cc15e976764ab12c5f8e762 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 18 Apr 2018 11:08:16 +0200 Subject: [PATCH 54/59] Bug 4454: The client locale is now implicitly given to RPC services using an http header --- .../sap/sse/gwt/client/EntryPointHelper.java | 11 ++++++++++ .../servlets/ProxiedRemoteServiceServlet.java | 20 ++++++++++++++++++- .../com/sap/sse/gwt/shared/RpcConstants.java | 5 +++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 java/com.sap.sse.gwt/src/com/sap/sse/gwt/shared/RpcConstants.java diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/EntryPointHelper.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/EntryPointHelper.java index 93c26d460e0..ba340c934ec 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/EntryPointHelper.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/EntryPointHelper.java @@ -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()); + } + }); } /** diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/dispatch/servlets/ProxiedRemoteServiceServlet.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/dispatch/servlets/ProxiedRemoteServiceServlet.java index dae2518aedb..d153dd3cb33 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/dispatch/servlets/ProxiedRemoteServiceServlet.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/dispatch/servlets/ProxiedRemoteServiceServlet.java @@ -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; + } } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/shared/RpcConstants.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/shared/RpcConstants.java new file mode 100644 index 00000000000..e3fd8b4268f --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/shared/RpcConstants.java @@ -0,0 +1,5 @@ +package com.sap.sse.gwt.shared; + +public interface RpcConstants { + public static final String HEADER_LOCALE = "X-Client-Locale"; +} From 05bfc959ddc24212416ce11298dc05ef08898562 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 18 Apr 2018 11:09:06 +0200 Subject: [PATCH 55/59] Bug 4454: Using the client locale to determine error messages while slicing --- .../java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 0c635c29f9a..14f3e936de0 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -7506,7 +7506,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException, NotFoundException { - Locale locale = Locale.ENGLISH; + final Locale locale = getClientLocale(); SecurityUtils.getSubject().checkPermission(Permission.MANAGE_TRACKED_RACES.getStringPermissionForObjects(Mode.UPDATE)); if (!canSliceRace(raceIdentifier)) { From c2652e22bbaf9a510e8943d55fb52acfc98a2c81 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 18 Apr 2018 11:28:27 +0200 Subject: [PATCH 56/59] Bug 4454: Removed unused throws declaration --- .../java/com/sap/sailing/gwt/ui/client/SailingService.java | 3 +-- .../java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index 0fd8f2c3a10..15199069315 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -766,9 +766,8 @@ 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 - * @throws NotFoundException */ - RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException, NotFoundException; + RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException; /** * Returns specific data needed for the slicing UI. diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 14f3e936de0..5b5d9705b00 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -7505,7 +7505,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, - TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException, NotFoundException { + TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException { final Locale locale = getClientLocale(); SecurityUtils.getSubject().checkPermission(Permission.MANAGE_TRACKED_RACES.getStringPermissionForObjects(Mode.UPDATE)); From e3bbce0b9970709c116ea3ff5f68c988868b98df Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Wed, 18 Apr 2018 18:14:07 +0200 Subject: [PATCH 57/59] use local variable to avoid computing getRideHeight() twice redundantly Change-Id: I415b91ceb76180e3f01a5617694857aa274bec49 --- .../sailing/domain/common/dto/IncrementalLeaderboardDTO.java | 2 +- .../sap/sailing/domain/common/tracking/impl/BravoFixImpl.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) mode change 100644 => 100755 java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoFixImpl.java diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/IncrementalLeaderboardDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/IncrementalLeaderboardDTO.java index e8fd3b495bb..4fc4ca813e5 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/IncrementalLeaderboardDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/IncrementalLeaderboardDTO.java @@ -483,7 +483,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme } } } - } + } } } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoFixImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoFixImpl.java old mode 100644 new mode 100755 index d6b818a207d..88fa5443014 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoFixImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoFixImpl.java @@ -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 From 18c777a99fd3fd9e776c40fe7cad5aadf2aa6851 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 19 Apr 2018 17:24:54 +0200 Subject: [PATCH 58/59] adjusted SwissTiming connector to accomodate UUIDs for mark devices and competitors Change-Id: Ieaca20de4eacbbc5c64e218fb557045f2590e6f6 --- .../impl/DomainObjectFactoryImpl.java | 7 +- .../domain/base/SharedDomainFactory.java | 2 + .../base/impl/SharedDomainFactoryImpl.java | 3 +- .../SwissTimingConnectivityParamsHandler.java | 10 +- .../classes/messages/CCGMessage.java | 9 +- .../services/MessageFileServiceImpl.java | 8 +- .../test/SailMasterConnectivityTest.java | 10 +- .../swisstimingadapter/test/ui/EditCCG.java | 18 ++-- .../domain/swisstimingadapter/Competitor.java | 2 +- .../swisstimingadapter/DomainFactory.java | 7 +- .../domain/swisstimingadapter/Fix.java | 4 +- .../domain/swisstimingadapter/Mark.java | 4 +- .../SwissTimingRaceTracker.java | 4 - .../impl/AbstractCompetitor.java | 2 +- .../impl/CompetitorWithID.java | 20 ++-- .../impl/CompetitorWithoutID.java | 2 +- .../impl/DomainFactoryImpl.java | 51 +++++----- .../swisstimingadapter/impl/FixImpl.java | 12 ++- .../swisstimingadapter/impl/MarkImpl.java | 23 +++-- .../impl/SailMasterConnectorImpl.java | 92 ++++++++++--------- .../impl/SwissTimingAdapterImpl.java | 1 - .../impl/SwissTimingRaceTrackerImpl.java | 52 +++-------- .../impl/TMDMessageQueue.java | 24 ++--- .../SwissTimingReplayToDomainAdapter.java | 11 ++- .../coursedata/impl/MarkDeserializer.java | 4 +- .../impl/BoatJsonDeserializer.java | 3 +- .../impl/CompetitorJsonDeserializer.java | 3 +- ...CompetitorWithBoatRefJsonDeserializer.java | 3 +- .../impl/CourseAreaJsonDeserializer.java | 3 +- .../gateway/deserialization/impl/Helpers.java | 18 ---- .../impl/LegacyBoatJsonDeserializer.java | 3 +- ...itorWithContainedBoatJsonDeserializer.java | 3 +- .../impl/BaseRaceLogEventDeserializer.java | 3 +- ...LogFinishPositioningEventDeserializer.java | 3 +- .../impl/RaceLogRevokeEventDeserializer.java | 4 +- ...ionIdentifierWithGPSFixesDeserializer.java | 3 +- .../jaxrs/api/LeaderboardsResource.java | 5 +- .../SailingServer (No Proxy).launch | 2 +- .../src/com/sap/sse/common/Util.java | 9 ++ .../src/com/sap/sse/util/impl/UUIDHelper.java | 23 +++++ .../positioning/app/util/DatabaseHelper.java | 4 +- 41 files changed, 242 insertions(+), 232 deletions(-) create mode 100755 java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/UUIDHelper.java diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 3d31846f72b..12e38ac33f6 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -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 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()); @@ -2044,7 +2045,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 +2093,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, diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java index a83ac5f1c39..2ef5b4568c3 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java @@ -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); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java index 15b3b480a10..b66705f16ac 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java @@ -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); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingConnectivityParamsHandler.java b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingConnectivityParamsHandler.java index ab6ed2b6ee9..a034257ea2b 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingConnectivityParamsHandler.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingConnectivityParamsHandler.java @@ -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; } diff --git a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/messages/CCGMessage.java b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/messages/CCGMessage.java index e5d46b993cb..3423c47c3c4 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/messages/CCGMessage.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/messages/CCGMessage.java @@ -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; } - } diff --git a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/services/MessageFileServiceImpl.java b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/services/MessageFileServiceImpl.java index 79545285a45..bfca426a65a 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/services/MessageFileServiceImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/services/MessageFileServiceImpl.java @@ -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 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); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/SailMasterConnectivityTest.java b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/SailMasterConnectivityTest.java index 225e62ec0c0..1d9b007362f 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/SailMasterConnectivityTest.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/SailMasterConnectivityTest.java @@ -239,11 +239,11 @@ public class SailMasterConnectivityTest { Iterator 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()); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/ui/EditCCG.java b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/ui/EditCCG.java index 71439a37081..a56b11a339f 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/ui/EditCCG.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/ui/EditCCG.java @@ -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 devices = new ArrayList(); - devices.add(jSailNumber1.getText()); - if (jRadioButton2.isSelected()) - devices.add(jSailNumber2.getText()); - marks.add(new MarkWithDesc(jMarkDescription.getText(), Integer.parseInt(jMarkIndex.getText()),devices)); + List 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 devices) { - super(description, index, devices, /* markType */ null); + public MarkWithDesc(String description, int index, Iterable deviceIds) { + super(description, index, deviceIds, /* markType */ null); } @Override public String toString(){ - return "Mark " + getIndex() + ": " + getDescription() + getDevices(); + return "Mark " + getIndex() + ": " + getDescription() + getDeviceIds(); } } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Competitor.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Competitor.java index 7663c4a98f1..aec126b1390 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Competitor.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Competitor.java @@ -11,5 +11,5 @@ public interface Competitor { String getName(); - String getID(); + String getIdAsString(); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/DomainFactory.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/DomainFactory.java index bd8494217ce..b8036a8adc0 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/DomainFactory.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/DomainFactory.java @@ -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 createCompetitorWithID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, BoatClass boatClass); - Pair createCompetitorWithoutID(String boatID, String threeLetterIOCCode, String name, String raceId, BoatClass boatClass); + Pair 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 devices, MarkType markType); + ControlPoint getOrCreateControlPoint(String description, Iterable deviceIds, MarkType markType); RaceDefinition createRaceDefinition(Regatta regatta, String swissTimingRaceID, Map competitorsAndBoats, List courseDefinition, String raceName, String raceIdForRaceDefinition); diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Fix.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Fix.java index 5798359d9e8..b93a17267a0 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Fix.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Fix.java @@ -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(); diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Mark.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Mark.java index b4c1a52be60..b0b69077cea 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Mark.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/Mark.java @@ -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 getDevices(); + Iterable getDeviceIds(); MarkType getMarkType(); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingRaceTracker.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingRaceTracker.java index f363a6f6767..43676f79d84 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingRaceTracker.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingRaceTracker.java @@ -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 getID(); - - Competitor getCompetitorByBoatIDAndRaceIDOrBoatClass(String boatID, String raceID, BoatClass boatClass); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/AbstractCompetitor.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/AbstractCompetitor.java index ebdc3727922..87add21a119 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/AbstractCompetitor.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/AbstractCompetitor.java @@ -29,7 +29,7 @@ public abstract class AbstractCompetitor implements Competitor { return name; } - public String getID() { + public String getIdAsString() { return null; } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/CompetitorWithID.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/CompetitorWithID.java index a90b0d09e91..b0c51a2f174 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/CompetitorWithID.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/CompetitorWithID.java @@ -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 crew; - public CompetitorWithID(String id, String boatID, String threeLetterIOCCode, String name, List crew) { + public CompetitorWithID(String idAsString, String boatID, String threeLetterIOCCode, String name, List 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() + "]"; } } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/CompetitorWithoutID.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/CompetitorWithoutID.java index 7caf332d0ef..aac7e9229a8 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/CompetitorWithoutID.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/CompetitorWithoutID.java @@ -10,7 +10,7 @@ public class CompetitorWithoutID extends AbstractCompetitor { } @Override - public String getID() { + public String getIdAsString() { return null; } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index 5a76ba306ed..5554aaf2e82 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -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 raceIDToRegattaCache; - private final Map, ControlPoint> controlPointCache; + private final Map, ControlPoint> controlPointCache; private final Map 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(); - controlPointCache = new HashMap, ControlPoint>(); + controlPointCache = new HashMap<>(); raceTypeByID = new HashMap(); for (OlympicRaceCode olympicRaceCode : OlympicRaceCode.values()) { @@ -121,7 +123,8 @@ public class DomainFactoryImpl implements DomainFactory { @Override public Pair 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 teamMembers = new ArrayList(); 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(domainCompetitor, domainCompetitor.getBoat()); @@ -266,8 +269,8 @@ public class DomainFactoryImpl implements DomainFactory { private Map createCompetitorsAndBoats(StartList startList, String raceId, BoatClass boatClass) { Map result = new LinkedHashMap<>(); for (com.sap.sailing.domain.swisstimingadapter.Competitor swissTimingCompetitor : startList.getCompetitors()) { - Pair domainCompetitorAndBoat; - if (swissTimingCompetitor.getID() != null) { + Pair 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 waypoints = new ArrayList(); 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 devices, MarkType markType) { + public ControlPoint getOrCreateControlPoint(String description, Iterable 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 markNameIter = devices.iterator(); - String left = markNameIter.next(); - String right = markNameIter.next(); - result = baseDomainFactory.createControlPointWithTwoMarks(getOrCreateMark(left), getOrCreateMark(right), left + "/" + right); + Iterator 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> newDomainControlPoints = new ArrayList>(); 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); diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/FixImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/FixImpl.java index ace8f0dc2f2..dd47dc5f5fe 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/FixImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/FixImpl.java @@ -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 diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/MarkImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/MarkImpl.java index 0c8bf7f67f8..cee6b852deb 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/MarkImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/MarkImpl.java @@ -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 devices; + private final Iterable deviceIds; private final MarkType markType; - public MarkImpl(String description, int index, Iterable devices, MarkType markType) { + public MarkImpl(String description, int index, Iterable devices, MarkType markType) { super(); this.description = description; this.index = index; this.markType = markType; - ArrayList l = new ArrayList(); - for (String device : devices) { + List 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 getDevices() { - return devices; + public Iterable 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(); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java index 37052b21d9c..56e4fd3544e 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java @@ -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> markIndicesRanksAndTimesSinceStartInMilliseconds = new ArrayList>(); 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 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); diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingAdapterImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingAdapterImpl.java index d43f6119d75..462b90ca2fe 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingAdapterImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingAdapterImpl.java @@ -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; diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java index 003d34330d6..0a1bd9d05d6 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java @@ -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 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> 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); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/TMDMessageQueue.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/TMDMessageQueue.java index 4e9fc74febc..27e98e4c74c 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/TMDMessageQueue.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/TMDMessageQueue.java @@ -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> markIndicesRanksAndTimesSinceStartInMilliseconds; - public TMDMessageContents(String raceID, String boatID, + public TMDMessageContents(String raceID, String competitorIdAsString, List> 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> 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 markIndexRankAndTimeSinceStartInMilliseconds : getMarkIndicesRanksAndTimesSinceStartInMilliseconds()) { @@ -82,8 +83,8 @@ public class TMDMessageQueue { queuedMessages = new HashSet<>(); } - public synchronized void enqueue(String raceID, String boatID, List> markIndicesRanksAndTimesSinceStartInMilliseconds) { - final TMDMessageContents message = new TMDMessageContents(raceID, boatID, markIndicesRanksAndTimesSinceStartInMilliseconds); + public synchronized void enqueue(String raceID, String competitorIdAsString, List> 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 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(); } diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java index 63f048a03a8..19433f1bd40 100755 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java @@ -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 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 markNames = new ArrayList<>(); - markNames.add(id1.trim()); + final List 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<>(); } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/MarkDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/MarkDeserializer.java index 88ad0dda98f..9d99769ccee 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/MarkDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/MarkDeserializer.java @@ -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 { @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); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java index 7b4afd4ff12..907fc4abb41 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java @@ -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 { private static final Logger logger = Logger.getLogger(BoatJsonDeserializer.class.getName()); @@ -63,7 +64,7 @@ public class BoatJsonDeserializer implements JsonDeserializer { 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; } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java index c938fcc927d..5cb2f2c57df 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java @@ -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 { private final CompetitorFactory competitorWithBoatFactory; @@ -52,7 +53,7 @@ public class CompetitorJsonDeserializer implements JsonDeserializer 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); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatRefJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatRefJsonDeserializer.java index 965691e5f5f..4eb21182692 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatRefJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatRefJsonDeserializer.java @@ -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); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CourseAreaJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CourseAreaJsonDeserializer.java index 5169d219a67..131af1fe5df 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CourseAreaJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CourseAreaJsonDeserializer.java @@ -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 { @@ -24,7 +25,7 @@ public class CourseAreaJsonDeserializer implements JsonDeserializer 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); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/Helpers.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/Helpers.java index 58ca5cd2fa2..c0d8f41977c 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/Helpers.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/Helpers.java @@ -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; - } - } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyBoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyBoatJsonDeserializer.java index 120db7ee34a..d6f4ac5a998 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyBoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyBoatJsonDeserializer.java @@ -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 { private final BoatClassJsonDeserializer boatClassDeserializer; @@ -41,7 +42,7 @@ public class LegacyBoatJsonDeserializer implements JsonDeserializer 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); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyCompetitorWithContainedBoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyCompetitorWithContainedBoatJsonDeserializer.java index bf7e1d34e28..755662d8b47 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyCompetitorWithContainedBoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyCompetitorWithContainedBoatJsonDeserializer.java @@ -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 { 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); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/BaseRaceLogEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/BaseRaceLogEventDeserializer.java index c25ee1f69e5..83654bd4ac6 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/BaseRaceLogEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/BaseRaceLogEventDeserializer.java @@ -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 { @@ -55,7 +56,7 @@ public abstract class BaseRaceLogEventDeserializer implements JsonDeserializer 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 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); diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/DeviceAndSessionIdentifierWithGPSFixesDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/DeviceAndSessionIdentifierWithGPSFixesDeserializer.java index 530321f95db..ad01ae65ad2 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/DeviceAndSessionIdentifierWithGPSFixesDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/DeviceAndSessionIdentifierWithGPSFixesDeserializer.java @@ -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>> { @@ -41,7 +42,7 @@ implements JsonDeserializer fixes = new ArrayList(); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java index 66cb2ce9010..9e603d6aacc 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java @@ -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); diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy).launch b/java/com.sap.sailing.server/SailingServer (No Proxy).launch index 9c666ad1841..9b5c1476411 100644 --- a/java/com.sap.sailing.server/SailingServer (No Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy).launch @@ -22,7 +22,7 @@ - + diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/Util.java b/java/com.sap.sse.common/src/com/sap/sse/common/Util.java index cfed9472a17..1952e22665b 100755 --- a/java/com.sap.sse.common/src/com/sap/sse/common/Util.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/Util.java @@ -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 strings) { StringBuilder result = new StringBuilder(); boolean first = true; diff --git a/java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/UUIDHelper.java b/java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/UUIDHelper.java new file mode 100755 index 00000000000..2e6b0ad379a --- /dev/null +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/UUIDHelper.java @@ -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; + } +} diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/DatabaseHelper.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/DatabaseHelper.java index a07fc1adb2e..3dc23deecaf 100755 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/DatabaseHelper.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/DatabaseHelper.java @@ -29,7 +29,7 @@ import com.sap.sailing.android.shared.data.CheckinUrlInfo; import com.sap.sailing.android.shared.data.LeaderboardInfo; import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl; -import com.sap.sailing.server.gateway.deserialization.impl.Helpers; +import com.sap.sse.util.impl.UUIDHelper; public class DatabaseHelper { @@ -84,7 +84,7 @@ public class DatabaseHelper { while (!mc.isAfterLast()) { final String markName = mc.getString((mc.getColumnIndex(Mark.MARK_NAME))); final String markIdAsString = mc.getString(mc.getColumnIndex(Mark.MARK_ID)); - final Serializable markId = Helpers.tryUuidConversion(markIdAsString); + final Serializable markId = UUIDHelper.tryUuidConversion(markIdAsString); MarkInfo markInfo = new MarkInfo(markId, markName, mc.getString((mc.getColumnIndex(Mark.MARK_CLASS_NAME))), checkinDigest); From aa8d6ea8a2bf2e159e6ba08fca31ca0ee508d70a Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 19 Apr 2018 20:50:28 +0200 Subject: [PATCH 59/59] removed redundant null check Change-Id: Ifd325b8fc86c0de969c2d03812c633af9add1b86 --- .../domain/persistence/impl/DomainObjectFactoryImpl.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 12e38ac33f6..31112f8e53c 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -1652,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...");