From 69c319138b33c1eef34cbf102377d1ff4ab2a1d2 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Tue, 12 Jun 2018 21:55:02 +0200 Subject: [PATCH 001/292] Adjusted getSpeedWithBearingSteps() to return steps with time points which ALWAYS correspond to non-raw fixes --- .../sailing/domain/tracking/GPSFixTrack.java | 12 ++-- .../domain/tracking/impl/GPSFixTrackImpl.java | 59 +++++-------------- 2 files changed, 21 insertions(+), 50 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSFixTrack.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSFixTrack.java index a91c230a693..4e2674fd8ac 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSFixTrack.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSFixTrack.java @@ -175,11 +175,13 @@ public interface GPSFixTrack extends MappedTra void resumeValidityCaching(); /** - * Gets a list of bearings between the provided time range (inclusive the boundaries). The bearings are retrieved by - * means of {@link GPSFixTrack#getEstimatedSpeed(TimePoint)}. The first and last bearing steps will be always - * sampled at provided {@code fromTimePoint} and {@code toTimePoint}, whereas the steps between are sampled at time - * points of non-raw GPS fixes. The idea of this concept is to produce at least two bearing steps as result, in - * order to provide the caller at least a {@code totalCourseChangeAngleInDegrees > 0} between the given time range. + * Gets a list of speed with bearing steps considering the provided time range. The bearings are retrieved by means + * of {@link GPSFixTrack#getEstimatedSpeed(TimePoint)}. The steps are sampled at time points of non-raw GPS fixes. + * When there is no non-raw fix contained at {@code fromTimePoint}, the time point of the first step will be the + * time point of the first non-raw fix before {@code fromTimePoint}. Analogously, when there is no non-raw fix + * contained at {@code toTimePoint}, the last step's time point will be the first non-raw fix after + * {@code toTimePoint}. The idea of this concept is to produce at least two steps as part of the result, in order to + * provide the caller at least a {@code |totalCourseChangeAngleInDegrees > 0|} between the given time range. * * @param fromTimePoint * The from time point (inclusive) for resulting bearing steps diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java index b50674511a1..ab0e6249971 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java @@ -1171,20 +1171,13 @@ public abstract class GPSFixTrackImpl extends Bearing lastCourse = null; TimePoint lastTimePoint = null; double lastCourseChangeAngleInDegrees = 0; - TimePoint fixTimePointAfterToTimePoint = null; try { lockForRead(); - TimePoint timePoint = fromTimePoint; - for (Iterator iterator = getFixesIterator(fromTimePoint, false); iterator - .hasNext(); timePoint = iterator.next().getTimePoint()) { - if (timePoint == null) { - continue; - } - if (timePoint.after(toTimePoint)) { - fixTimePointAfterToTimePoint = timePoint; - timePoint = toTimePoint; - } - SpeedWithBearing estimatedSpeed = getEstimatedSpeed(timePoint); + FixType firstFix = getLastFixAtOrBefore(fromTimePoint); + TimePoint currentTimePoint = firstFix == null ? fromTimePoint : firstFix.getTimePoint(); + for (Iterator iterator = getFixesIterator(currentTimePoint, true); iterator + .hasNext(); currentTimePoint = iterator.next().getTimePoint()) { + SpeedWithBearing estimatedSpeed = getEstimatedSpeed(currentTimePoint); if (estimatedSpeed != null) { Bearing course = estimatedSpeed.getBearing(); /* @@ -1195,44 +1188,20 @@ public abstract class GPSFixTrackImpl extends double courseChangeAngleInDegrees = lastCourse == null ? 0 : lastCourse.getDifferenceTo(course, new DegreeBearingImpl(lastCourseChangeAngleInDegrees)) .getDegrees(); + double turningRateInDegreesPerSecond = lastTimePoint == null ? 0 + : Math.abs(courseChangeAngleInDegrees + / lastTimePoint.until(currentTimePoint).asSeconds()); - // Fix distorted turning rate due to inappropriate interpolation of getEstimatedSpeed() at first - // and last step - double courseChangeInDegreesForTurningRateCalculation = courseChangeAngleInDegrees; - Duration durationBetweenStepsForTurningRateCalculation = lastTimePoint == null ? null - : lastTimePoint.until(timePoint); - if (fromTimePoint.equals(lastTimePoint)) { - FixType firstFix = getLastFixAtOrBefore(fromTimePoint); - if (firstFix != null && !firstFix.getTimePoint().equals(fromTimePoint)) { - SpeedWithBearing firstFixEstimatedSpeed = getEstimatedSpeed(firstFix.getTimePoint()); - if (firstFixEstimatedSpeed != null) { - durationBetweenStepsForTurningRateCalculation = firstFix.getTimePoint() - .until(timePoint); - courseChangeInDegreesForTurningRateCalculation = courseChangeAngleInDegrees - + firstFixEstimatedSpeed.getBearing().getDifferenceTo(lastCourse).getDegrees(); - } - } - } else if (fixTimePointAfterToTimePoint != null && lastCourse != null) { - SpeedWithBearing lastFixEstimatedSpeed = getEstimatedSpeed(fixTimePointAfterToTimePoint); - if (lastFixEstimatedSpeed != null) { - durationBetweenStepsForTurningRateCalculation = lastTimePoint == null ? null - : lastTimePoint.until(fixTimePointAfterToTimePoint); - courseChangeInDegreesForTurningRateCalculation = courseChangeAngleInDegrees + estimatedSpeed - .getBearing().getDifferenceTo(lastFixEstimatedSpeed.getBearing()).getDegrees(); - } - } - - double turningRateInDegreesPerSecond = durationBetweenStepsForTurningRateCalculation == null ? 0 - : Math.abs(courseChangeInDegreesForTurningRateCalculation - / durationBetweenStepsForTurningRateCalculation.asSeconds()); - - speedWithBearingSteps.add(new SpeedWithBearingStepImpl(timePoint, estimatedSpeed, + speedWithBearingSteps.add(new SpeedWithBearingStepImpl(currentTimePoint, estimatedSpeed, courseChangeAngleInDegrees, turningRateInDegreesPerSecond)); + if (currentTimePoint.after(toTimePoint)) { + break; + } lastCourse = course; lastCourseChangeAngleInDegrees = courseChangeAngleInDegrees; - lastTimePoint = timePoint; + lastTimePoint = currentTimePoint; } - if (!timePoint.before(toTimePoint)) { + if (!currentTimePoint.before(toTimePoint)) { break; } } From 2167182d81c338ad352dafcee01930e0e2dbf1de Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Tue, 12 Jun 2018 23:26:31 +0200 Subject: [PATCH 002/292] Improved maneuver splitting at mark passing time points --- .../impl/ManeuverDetectorImpl.java | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java index 0a32506111d..a7080e68424 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java @@ -990,19 +990,50 @@ public class ManeuverDetectorImpl implements ManeuverDetector { SpeedWithBearingStepsIterable speedWithBearingSteps, TimePoint timePoint) { List stepsBefore = new ArrayList<>(); List stepsAfter = new ArrayList<>(); + SpeedWithBearingStep lastEntry = null; for (SpeedWithBearingStep entry : speedWithBearingSteps) { if (!entry.getTimePoint().after(timePoint)) { - if (stepsBefore.isEmpty()) { - // First bearing step supposed to have 0 as course change as - // it does not have any previous steps with bearings to compute bearing difference. - // If the condition is not met, the existing code which uses ManeuverBearingStep class will break. - entry = new SpeedWithBearingStepImpl(entry.getTimePoint(), entry.getSpeedWithBearing(), 0.0, 0.0); - } stepsBefore.add(entry); } if (!entry.getTimePoint().before(timePoint)) { if (stepsAfter.isEmpty()) { - entry = new SpeedWithBearingStepImpl(entry.getTimePoint(), entry.getSpeedWithBearing(), 0.0, 0.0); + // First step supposed to have 0 as course change as it does not have any previous steps to compute + // bearing difference. If the condition is not met, the existing code which uses + // SpeedWithBearingStepsIterable class will break. + if (lastEntry != null && lastEntry.getTimePoint().before(timePoint)) { + // If there is not any step located at the splitting time point, we need to retrieve the + // interpolated speed with bearing at time point in order to produce boundary step for both step + // sets at time point. If we will not do it, the course change between the steps split by + // splitting time point will be lost. + SpeedWithBearing speedWithBearing = track.getEstimatedSpeed(timePoint); + if (speedWithBearing != null) { + double courseChangeAngleInDegrees = lastEntry.getSpeedWithBearing().getBearing() + .getDifferenceTo(speedWithBearing.getBearing(), + new DegreeBearingImpl(lastEntry.getCourseChangeInDegrees())) + .getDegrees(); + double turningRateInDegreesPerSecond = Math.abs( + courseChangeAngleInDegrees / lastEntry.getTimePoint().until(timePoint).asSeconds()); + SpeedWithBearingStep lastStepBefore = new SpeedWithBearingStepImpl(timePoint, + speedWithBearing, courseChangeAngleInDegrees, turningRateInDegreesPerSecond); + stepsBefore.add(lastStepBefore); + SpeedWithBearingStep firstStepAfter = new SpeedWithBearingStepImpl(timePoint, + speedWithBearing, 0.0, 0.0); + stepsAfter.add(firstStepAfter); + courseChangeAngleInDegrees = firstStepAfter.getSpeedWithBearing().getBearing() + .getDifferenceTo(speedWithBearing.getBearing(), + new DegreeBearingImpl(firstStepAfter.getCourseChangeInDegrees())) + .getDegrees(); + turningRateInDegreesPerSecond = Math.abs( + courseChangeAngleInDegrees / timePoint.until(entry.getTimePoint()).asSeconds()); + entry = new SpeedWithBearingStepImpl(entry.getTimePoint(), entry.getSpeedWithBearing(), + courseChangeAngleInDegrees, turningRateInDegreesPerSecond); + } + + } + if (stepsAfter.isEmpty()) { + entry = new SpeedWithBearingStepImpl(entry.getTimePoint(), entry.getSpeedWithBearing(), 0.0, + 0.0); + } } stepsAfter.add(entry); } From 9f1f400236852f9a9f1fd8d81c3cc543b406b4da Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 15 Jun 2018 11:15:30 +0200 Subject: [PATCH 003/292] bug4614: created a sortable column that takes a signed value for speed change and maneuverloss in ManeuverTablePanel.java --- .../racemap/maneuver/ManeuverTablePanel.java | 90 +++++++++++++++++-- 1 file changed, 82 insertions(+), 8 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java index 35c94d9fa89..706446d3333 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java @@ -148,27 +148,30 @@ public class ManeuverTablePanel extends AbstractCompositeComponent createSortableMinMaxColumn( +/** + * Creates a sortable column with the absolute value. + * Whereas {@link #createSortableMinMaxColumn()} creates a sortable column with signed values. + */ + private SortableColumn createSortableAbsMinMaxColumn( Function extractor, String title, String unit) { final SortableColumn col = new AbstractSortableColumnWithMinMax( new TextCell(), SortingOrder.ASCENDING) { @@ -236,6 +239,77 @@ public class ManeuverTablePanel extends AbstractCompositeComponent createSortableMinMaxColumn( + Function extractor, String title, String unit) { + final SortableColumn col = new AbstractSortableColumnWithMinMax( + new TextCell(), SortingOrder.ASCENDING) { + final InvertibleComparator comparator = new InvertibleComparatorAdapter() { + @Override + public int compare(ManeuverTableData o1, ManeuverTableData o2) { + Double o1v = extractor.apply(o1); + Double o2v = extractor.apply(o2); + if (o1v == null && o2v == null) { + return 0; + } + if (o1v == null && o2v != null) { + return -1; + } + if (o1v != null && o2v == null) { + return 1; + } + return Double.compare(o1v, o2v); + } + }; + final HasStringAndDoubleValue dataProvider = new HasStringAndDoubleValue() { + @Override + public String getStringValueToRender(ManeuverTableData row) { + Double value = extractor.apply(row); + if (value == null) { + return null; + } + return towDigitAccuracy.format(value); + } + + @Override + public Double getDoubleValue(ManeuverTableData row) { + Double value = extractor.apply(row); + return value == null ? null : value; + } + }; + + final MinMaxRenderer renderer = new MinMaxRenderer(dataProvider, comparator); + + @Override + public InvertibleComparator getComparator() { + return comparator; + } + + @Override + public void render(Context context, ManeuverTableData object, SafeHtmlBuilder sb) { + renderer.render(context, object, title, sb); + } + + @Override + public Header getHeader() { + return new TextHeader(title + " [" + unit + "]"); + } + + @Override + public String getValue(ManeuverTableData object) { + return dataProvider.getStringValueToRender(object); + } + + @Override + public void updateMinMax() { + renderer.updateMinMax(maneuverCellTable.getDataProvider().getList()); + } + }; + col.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); + return col; + } private SortableColumn createManeuverTypeColumn() { return new SortableColumn(new TextCell(), SortingOrder.ASCENDING) { From 46578905d4273ed33a4fd81a82c62bc60d2eaf9a Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Sun, 17 Jun 2018 13:50:31 +0200 Subject: [PATCH 004/292] Refined stable course analysis --- .../impl/ManeuverDetectorImpl.java | 31 +++---------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java index a7080e68424..a05eae5ec19 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java @@ -72,13 +72,6 @@ public class ManeuverDetectorImpl implements ManeuverDetector { */ private static final double MIN_ANGULAR_VELOCITY_FOR_MAIN_CURVE_BOUNDARIES_IN_DEGREES_PER_SECOND = 0.2; - /** - * Defines the course change limit toward opposite direction related to the direction of maneuver main curve. If - * speed maxima or stable bearing analysis produce a curve extension which exceeds this limit, the extension gets - * rejected. - */ - private static final double MAX_COURSE_CHANGE_TOWARD_MANEUVER_OPPOSITE_DIRECTION_FOR_CURVE_EXTENSION_IN_DEGREES = 15.0; - /** * Tracked race whose tracks are being processed for maneuver detection. */ @@ -1387,25 +1380,11 @@ public class ManeuverDetectorImpl implements ManeuverDetector { if (isCourseChangeLimitExceededForCurveExtension(maneuverMainCurveDetails, maneuverStart)) { maneuverStart = null; } - TimePoint stableBearingAnalysisUntil = maneuverStart == null ? maneuverMainCurveDetails.getTimePointBefore() - : maneuverStart.getExtensionTimePoint(); + // Stable course analysis is considered as not necessary for preparation phase of maneuver because no + // oversteering is usually performed before maneuver Speed lowestSpeed = maneuverStart == null ? null : maneuverStart.getLowestSpeedWithinExtensionArea(); double courseChangeSinceManeuverMainCurveInDegrees = maneuverStart == null ? 0 : maneuverStart.getCourseChangeInDegreesWithinExtensionArea(); - stepsToAnalyze = getSpeedWithBearingStepsWithinTimeRange(stepsToAnalyze, earliestTimePointForSpeedTrendAnalysis, - stableBearingAnalysisUntil); - ManeuverCurveBoundaryExtension stableBearingExtension = findStableBearingWithMaxAbsCourseChangeSpeed( - stepsToAnalyze, true, MAX_ABS_COURSE_CHANGE_IN_DEGREES_PER_SECOND_FOR_STABLE_BEARING_ANALYSIS); - if (stableBearingExtension != null - && !isCourseChangeLimitExceededForCurveExtension(maneuverMainCurveDetails, stableBearingExtension)) { - maneuverStart = stableBearingExtension; - courseChangeSinceManeuverMainCurveInDegrees += stableBearingExtension - .getCourseChangeInDegreesWithinExtensionArea(); - if (lowestSpeed == null - || lowestSpeed.compareTo(stableBearingExtension.getLowestSpeedWithinExtensionArea()) > 0) { - lowestSpeed = stableBearingExtension.getLowestSpeedWithinExtensionArea(); - } - } return maneuverStart != null ? new ManeuverCurveBoundaryExtension(maneuverStart.getExtensionTimePoint(), maneuverStart.getSpeedWithBearingAtExtensionTimePoint(), @@ -1422,10 +1401,8 @@ public class ManeuverDetectorImpl implements ManeuverDetector { if (curveBoundaryExtension == null) { return false; } - return curveBoundaryExtension.getCourseChangeInDegreesWithinExtensionArea() - * maneuverMainCurveDetails.getDirectionChangeInDegrees() < 0 - && Math.abs(curveBoundaryExtension - .getCourseChangeInDegreesWithinExtensionArea()) > MAX_COURSE_CHANGE_TOWARD_MANEUVER_OPPOSITE_DIRECTION_FOR_CURVE_EXTENSION_IN_DEGREES; + return Math.abs(curveBoundaryExtension.getCourseChangeInDegreesWithinExtensionArea()) > Math + .abs(curveBoundaryExtension.getCourseChangeInDegreesWithinExtensionArea()) / 2.0; } /** From d9f857d31c48e967c9326f639906415a7d094348 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Mon, 18 Jun 2018 00:23:22 +0200 Subject: [PATCH 005/292] Fixed double occurence of the first speed with bearing step --- .../com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java index ab0e6249971..f4266d5e422 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java @@ -1175,7 +1175,7 @@ public abstract class GPSFixTrackImpl extends lockForRead(); FixType firstFix = getLastFixAtOrBefore(fromTimePoint); TimePoint currentTimePoint = firstFix == null ? fromTimePoint : firstFix.getTimePoint(); - for (Iterator iterator = getFixesIterator(currentTimePoint, true); iterator + for (Iterator iterator = getFixesIterator(currentTimePoint, false); iterator .hasNext(); currentTimePoint = iterator.next().getTimePoint()) { SpeedWithBearing estimatedSpeed = getEstimatedSpeed(currentTimePoint); if (estimatedSpeed != null) { From 87475ae406549cd290239c2933cc4f2aa872f8c0 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Mon, 18 Jun 2018 00:24:27 +0200 Subject: [PATCH 006/292] Added handling for mark-passing set with finish-line passing only --- .../maneuverdetection/impl/ManeuverDetectorImpl.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java index a05eae5ec19..2d5f7d4a5ae 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java @@ -534,7 +534,13 @@ public class ManeuverDetectorImpl implements ManeuverDetector { } } if (latestRawFixTimePoint != null) { - return new TrackTimeInfo(earliestTrackRecord, latestTrackRecord, latestRawFixTimePoint); + if(!earliestTrackRecord.equals(latestTrackRecord)) { + return new TrackTimeInfo(earliestTrackRecord, latestTrackRecord, latestRawFixTimePoint); + } + GPSFixMoving firstRawFix = track.getFirstRawFix(); + if(firstRawFix != null) { + return new TrackTimeInfo(firstRawFix.getTimePoint(), latestRawFixTimePoint, latestRawFixTimePoint); + } } } } From 51a44ee08211d01b50b44202c15c834cbf125b95 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Mon, 18 Jun 2018 16:30:57 +0200 Subject: [PATCH 007/292] Changed max turning rate threshold for stable course analysis to 1 --- .../maneuverdetection/impl/ManeuverDetectorImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java index 2d5f7d4a5ae..f248d9dbeae 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java @@ -64,7 +64,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * Defines the maximal absolute course change velocity in degrees per second that shall be regarded as a stable * course. */ - private static final double MAX_ABS_COURSE_CHANGE_IN_DEGREES_PER_SECOND_FOR_STABLE_BEARING_ANALYSIS = 2; + private static final double MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS = 1; /** * Defines the absolute course change in degrees between bearing steps to ignore in order to shorten the @@ -1302,7 +1302,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * approximate the beginning time point of the maneuver, the speed maximum is determined throughout forward in time * iteration of speed steps starting from time point of main curve beginning. From the determined speed maximum, the * iteration continues until the point, when the bearing changes occur only with a maximum of - * {@value #MAX_ABS_COURSE_CHANGE_IN_DEGREES_PER_SECOND_FOR_STABLE_BEARING_ANALYSIS} degrees per second, which is + * {@value #MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS} degrees per second, which is * regarded as a stable course. The exiting time point of maneuver is approximated analogously by speed maximum * determination throughout backward in time iteration of speed steps starting from time of main curve end, followed * by a search for a point with stable course. @@ -1354,7 +1354,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * determined, the course changes get analyzed starting from {@code t'} until {@code (t -} * {@link BoatClass#getApproximateManeuverDurationInMilliseconds() approx. maneuver duration}{@code )} in order to * locate the point where the bearing starts to change with a rate of maximal - * {@value #MAX_ABS_COURSE_CHANGE_IN_DEGREES_PER_SECOND_FOR_STABLE_BEARING_ANALYSIS} degrees per second, which is + * {@value #MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS} degrees per second, which is * regarded as a stable course. * * @param maneuverMainCurveDetails @@ -1423,7 +1423,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * determined, the course changes get analyzed starting from {@code t'} until {@code (t +} * {@link BoatClass#getApproximateManeuverDurationInMilliseconds() approx. maneuver duration} {@code * 3)} in order * to locate the point where the bearing starts to change with a rate of maximal - * {@value #MAX_ABS_COURSE_CHANGE_IN_DEGREES_PER_SECOND_FOR_STABLE_BEARING_ANALYSIS} degrees per second, which is + * {@value #MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS} degrees per second, which is * regarded as a stable course. * * @param maneuverMainCurveDetails @@ -1464,7 +1464,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector { stepsToAnalyze = getSpeedWithBearingStepsWithinTimeRange(stepsToAnalyze, stableBearingAnalysisFrom, latestTimePointForSpeedTrendAnalysis); ManeuverCurveBoundaryExtension stableBearingExtension = findStableBearingWithMaxAbsCourseChangeSpeed( - stepsToAnalyze, false, MAX_ABS_COURSE_CHANGE_IN_DEGREES_PER_SECOND_FOR_STABLE_BEARING_ANALYSIS); + stepsToAnalyze, false, MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS); if (stableBearingExtension != null && !isCourseChangeLimitExceededForCurveExtension(maneuverMainCurveDetails, stableBearingExtension)) { maneuverEnd = stableBearingExtension; From 6370b242fb1802e3e07fb87831ebb76354c39314 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Mon, 18 Jun 2018 17:56:22 +0200 Subject: [PATCH 008/292] Reduced course change limit for maneuver section extension --- .../domain/maneuverdetection/impl/ManeuverDetectorImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java index f248d9dbeae..6572f25f378 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java @@ -1408,7 +1408,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector { return false; } return Math.abs(curveBoundaryExtension.getCourseChangeInDegreesWithinExtensionArea()) > Math - .abs(curveBoundaryExtension.getCourseChangeInDegreesWithinExtensionArea()) / 2.0; + .abs(curveBoundaryExtension.getCourseChangeInDegreesWithinExtensionArea()) / 3.0; } /** From 69fe7755ca2e93fa1fa45677465493f3489996a3 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 3 Jul 2018 12:05:22 +0200 Subject: [PATCH 009/292] code formatting Change-Id: If53e49429cbabba1c0a452b3cb409f1a34b48862 --- .../racemap/maneuver/ManeuverTablePanel.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java index 706446d3333..ff330995cea 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java @@ -167,10 +167,11 @@ public class ManeuverTablePanel extends AbstractCompositeComponent createSortableAbsMinMaxColumn( Function extractor, String title, String unit) { final SortableColumn col = new AbstractSortableColumnWithMinMax( @@ -239,6 +240,7 @@ public class ManeuverTablePanel extends AbstractCompositeComponent createManeuverTypeColumn() { return new SortableColumn(new TextCell(), SortingOrder.ASCENDING) { - @Override public InvertibleComparator getComparator() { return new InvertibleComparatorAdapter() { @@ -343,7 +344,6 @@ public class ManeuverTablePanel extends AbstractCompositeComponent col = new SortableColumn( new DateCell(DateTimeFormat.getFormat(PredefinedFormat.TIME_LONG)), SortingOrder.ASCENDING) { @Override @@ -371,7 +371,6 @@ public class ManeuverTablePanel extends AbstractCompositeComponent column = new SortableColumn( new AbstractCell() { @Override @@ -406,9 +405,7 @@ public class ManeuverTablePanel extends AbstractCompositeComponent(new TextCell(), SortingOrder.ASCENDING) { - @Override public InvertibleComparator getComparator() { return comparator; From 6a07cd743871d49cd269ce5b4b6d68a20fca6ae4 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 3 Jul 2018 12:35:36 +0200 Subject: [PATCH 010/292] bug4614: introduced SortableMinMaxColumn to factor out the commonalities of columns sorted by absolute and real value Change-Id: I10f0efbb1e63e694e4575b1322124cd8041e82db --- .../racemap/maneuver/ManeuverTablePanel.java | 139 +----------------- .../maneuver/SortableMinMaxColumn.java | 94 ++++++++++++ 2 files changed, 96 insertions(+), 137 deletions(-) create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/SortableMinMaxColumn.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java index ff330995cea..2d233399dbf 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java @@ -9,11 +9,9 @@ import java.util.function.Function; import java.util.function.Supplier; import com.google.gwt.cell.client.AbstractCell; -import com.google.gwt.cell.client.Cell.Context; import com.google.gwt.cell.client.DateCell; import com.google.gwt.cell.client.TextCell; import com.google.gwt.core.shared.GWT; -import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.i18n.shared.DateTimeFormat; import com.google.gwt.i18n.shared.DateTimeFormat.PredefinedFormat; import com.google.gwt.safehtml.shared.SafeHtmlBuilder; @@ -42,14 +40,11 @@ import com.sap.sailing.gwt.ui.actions.GetManeuversForCompetitorsAction; import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener; import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider; import com.sap.sailing.gwt.ui.client.ManeuverTypeFormatter; -import com.sap.sailing.gwt.ui.client.NumberFormatterFactory; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.controls.AbstractSortableColumnWithMinMax; import com.sap.sailing.gwt.ui.client.shared.controls.SortableColumn; -import com.sap.sailing.gwt.ui.leaderboard.HasStringAndDoubleValue; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel.LeaderBoardStyle; -import com.sap.sailing.gwt.ui.leaderboard.MinMaxRenderer; import com.sap.sailing.gwt.ui.leaderboard.SortedCellTableWithStylableHeaders; import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sse.common.TimeRange; @@ -82,8 +77,6 @@ public class ManeuverTablePanel extends AbstractCompositeComponent maneuverCellTable; @@ -174,71 +167,7 @@ public class ManeuverTablePanel extends AbstractCompositeComponent createSortableAbsMinMaxColumn( Function extractor, String title, String unit) { - final SortableColumn col = new AbstractSortableColumnWithMinMax( - new TextCell(), SortingOrder.ASCENDING) { - final InvertibleComparator comparatorWithAbs = new InvertibleComparatorAdapter() { - @Override - public int compare(ManeuverTableData o1, ManeuverTableData o2) { - Double o1v = extractor.apply(o1); - Double o2v = extractor.apply(o2); - if (o1v == null && o2v == null) { - return 0; - } - if (o1v == null && o2v != null) { - return -1; - } - if (o1v != null && o2v == null) { - return 1; - } - return Double.compare(Math.abs(o1v), Math.abs(o2v)); - } - }; - final HasStringAndDoubleValue dataProvider = new HasStringAndDoubleValue() { - @Override - public String getStringValueToRender(ManeuverTableData row) { - Double value = extractor.apply(row); - if (value == null) { - return null; - } - return towDigitAccuracy.format(value); - } - - @Override - public Double getDoubleValue(ManeuverTableData row) { - Double value = extractor.apply(row); - return value == null ? null : Math.abs(value); - } - }; - - final MinMaxRenderer renderer = new MinMaxRenderer(dataProvider, comparatorWithAbs); - - @Override - public InvertibleComparator getComparator() { - return comparatorWithAbs; - } - - @Override - public void render(Context context, ManeuverTableData object, SafeHtmlBuilder sb) { - renderer.render(context, object, title, sb); - } - - @Override - public Header getHeader() { - return new TextHeader(title + " [" + unit + "]"); - } - - @Override - public String getValue(ManeuverTableData object) { - return dataProvider.getStringValueToRender(object); - } - - @Override - public void updateMinMax() { - renderer.updateMinMax(maneuverCellTable.getDataProvider().getList()); - } - }; - col.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); - return col; + return new SortableMinMaxColumn(extractor, title, unit, maneuverCellTable.getDataProvider(), /* absolute */ true); } /** @@ -246,71 +175,7 @@ public class ManeuverTablePanel extends AbstractCompositeComponent createSortableMinMaxColumn( Function extractor, String title, String unit) { - final SortableColumn col = new AbstractSortableColumnWithMinMax( - new TextCell(), SortingOrder.ASCENDING) { - final InvertibleComparator comparator = new InvertibleComparatorAdapter() { - @Override - public int compare(ManeuverTableData o1, ManeuverTableData o2) { - Double o1v = extractor.apply(o1); - Double o2v = extractor.apply(o2); - if (o1v == null && o2v == null) { - return 0; - } - if (o1v == null && o2v != null) { - return -1; - } - if (o1v != null && o2v == null) { - return 1; - } - return Double.compare(o1v, o2v); - } - }; - final HasStringAndDoubleValue dataProvider = new HasStringAndDoubleValue() { - @Override - public String getStringValueToRender(ManeuverTableData row) { - Double value = extractor.apply(row); - if (value == null) { - return null; - } - return towDigitAccuracy.format(value); - } - - @Override - public Double getDoubleValue(ManeuverTableData row) { - Double value = extractor.apply(row); - return value == null ? null : value; - } - }; - - final MinMaxRenderer renderer = new MinMaxRenderer(dataProvider, comparator); - - @Override - public InvertibleComparator getComparator() { - return comparator; - } - - @Override - public void render(Context context, ManeuverTableData object, SafeHtmlBuilder sb) { - renderer.render(context, object, title, sb); - } - - @Override - public Header getHeader() { - return new TextHeader(title + " [" + unit + "]"); - } - - @Override - public String getValue(ManeuverTableData object) { - return dataProvider.getStringValueToRender(object); - } - - @Override - public void updateMinMax() { - renderer.updateMinMax(maneuverCellTable.getDataProvider().getList()); - } - }; - col.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); - return col; + return new SortableMinMaxColumn(extractor, title, unit, maneuverCellTable.getDataProvider(), /* absolute */ false); } private SortableColumn createManeuverTypeColumn() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/SortableMinMaxColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/SortableMinMaxColumn.java new file mode 100755 index 00000000000..b6c5d146cff --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/SortableMinMaxColumn.java @@ -0,0 +1,94 @@ +package com.sap.sailing.gwt.ui.client.shared.racemap.maneuver; + +import java.util.Comparator; +import java.util.function.Function; + +import com.google.gwt.cell.client.Cell.Context; +import com.google.gwt.cell.client.TextCell; +import com.google.gwt.i18n.client.NumberFormat; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.user.cellview.client.Header; +import com.google.gwt.user.cellview.client.TextHeader; +import com.google.gwt.user.client.ui.HasHorizontalAlignment; +import com.google.gwt.view.client.ListDataProvider; +import com.sap.sailing.domain.common.InvertibleComparator; +import com.sap.sailing.domain.common.SortingOrder; +import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter; +import com.sap.sailing.gwt.ui.client.NumberFormatterFactory; +import com.sap.sailing.gwt.ui.client.shared.controls.AbstractSortableColumnWithMinMax; +import com.sap.sailing.gwt.ui.leaderboard.HasStringAndDoubleValue; +import com.sap.sailing.gwt.ui.leaderboard.MinMaxRenderer; + +public class SortableMinMaxColumn extends AbstractSortableColumnWithMinMax { + private final static NumberFormat TWO_DIGIT_ACCURACY = NumberFormatterFactory.getDecimalFormat(2); + private final String title; + private final String unit; + + final InvertibleComparator comparator; + + final HasStringAndDoubleValue dataProvider; + + final MinMaxRenderer renderer; + + final ListDataProvider maneuverTableListDataProvider; + + public SortableMinMaxColumn(final Function extractor, String title, String unit, + ListDataProvider maneuverTableListDataProvider, boolean absolute) { + super(new TextCell(), SortingOrder.ASCENDING); + this.title = title; + this.unit = unit; + this.maneuverTableListDataProvider = maneuverTableListDataProvider; + this.comparator = new InvertibleComparatorAdapter() { + @Override + public int compare(ManeuverTableData o1, ManeuverTableData o2) { + Double o1v = extractor.apply(o1); + Double o2v = extractor.apply(o2); + return Comparator.nullsFirst((Double v1, Double v2)->Double.compare(absolute?Math.abs(v1):v1, absolute?Math.abs(v2):v2)).compare(o1v, o2v); + } + }; + this.dataProvider = new HasStringAndDoubleValue() { + @Override + public String getStringValueToRender(ManeuverTableData row) { + Double value = extractor.apply(row); + if (value == null) { + return null; + } + return TWO_DIGIT_ACCURACY.format(value); + } + + @Override + public Double getDoubleValue(ManeuverTableData row) { + Double value = extractor.apply(row); + return value == null ? null : value; + } + }; + + this.renderer = new MinMaxRenderer(dataProvider, comparator); + this.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); + } + + @Override + public InvertibleComparator getComparator() { + return comparator; + } + + @Override + public void render(Context context, ManeuverTableData object, SafeHtmlBuilder sb) { + renderer.render(context, object, title, sb); + } + + @Override + public Header getHeader() { + return new TextHeader(title + " [" + unit + "]"); + } + + @Override + public String getValue(ManeuverTableData object) { + return dataProvider.getStringValueToRender(object); + } + + @Override + public void updateMinMax() { + renderer.updateMinMax(maneuverTableListDataProvider.getList()); + } +} \ No newline at end of file From c6e90300c251e1ef2d107e0fc550d1476fad0b37 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Thu, 5 Jul 2018 06:45:30 +0200 Subject: [PATCH 011/292] Added maneuver detection implementation for extremely low GPS sampling rates --- ...eWithEstimationDataRetrievalProcessor.java | 6 +- .../maneuverdetection/ManeuverDetector.java | 46 -- ...uverDetectorWithEstimationDataSupport.java | 61 ++ .../impl/AbstractManeuverDetectorImpl.java | 155 ++++++ ...owGPSSamplingRateManeuverDetectorImpl.java | 156 ++++++ .../impl/ManeuverDetectorImpl.java | 526 ++---------------- ...ithEstimationDataSupportDecoratorImpl.java | 404 ++++++++++++++ .../sap/sailing/domain/tracking/Maneuver.java | 2 +- ...neuverWithCoarseGrainedBoundariesImpl.java | 37 ++ .../domain/tracking/impl/TrackedRaceImpl.java | 20 +- ...urvesWithEstimationDataJsonSerializer.java | 6 +- 11 files changed, 873 insertions(+), 546 deletions(-) create mode 100644 java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/ManeuverDetectorWithEstimationDataSupport.java create mode 100644 java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/AbstractManeuverDetectorImpl.java create mode 100644 java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/LowGPSSamplingRateManeuverDetectorImpl.java create mode 100644 java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java create mode 100644 java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/ManeuverWithCoarseGrainedBoundariesImpl.java diff --git a/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/CompleteManeuverCurveWithEstimationDataRetrievalProcessor.java b/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/CompleteManeuverCurveWithEstimationDataRetrievalProcessor.java index f11191a86e7..f05bdf58be0 100644 --- a/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/CompleteManeuverCurveWithEstimationDataRetrievalProcessor.java +++ b/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/CompleteManeuverCurveWithEstimationDataRetrievalProcessor.java @@ -11,8 +11,9 @@ import com.sap.sailing.datamining.impl.data.CompleteManeuverCurveWithEstimationD import com.sap.sailing.datamining.shared.ManeuverSettings; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.maneuverdetection.CompleteManeuverCurveWithEstimationData; -import com.sap.sailing.domain.maneuverdetection.ManeuverDetector; +import com.sap.sailing.domain.maneuverdetection.ManeuverDetectorWithEstimationDataSupport; import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorImpl; +import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorWithEstimationDataSupportDecoratorImpl; import com.sap.sailing.domain.tracking.CompleteManeuverCurve; import com.sap.sailing.domain.tracking.Maneuver; import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries; @@ -45,7 +46,8 @@ public class CompleteManeuverCurveWithEstimationDataRetrievalProcessor extends List result = new ArrayList<>(); TrackedRace trackedRace = element.getTrackedRaceContext().getTrackedRace(); Competitor competitor = element.getCompetitor(); - ManeuverDetector maneuverDetector = new ManeuverDetectorImpl(trackedRace, competitor); + ManeuverDetectorWithEstimationDataSupport maneuverDetector = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl( + new ManeuverDetectorImpl(trackedRace, competitor)); Iterable maneuvers = trackedRace.getManeuvers(competitor, false); Iterable maneuverCurves = maneuverDetector.getCompleteManeuverCurves(maneuvers); Iterable maneuversWithEstimationData = maneuverDetector diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/ManeuverDetector.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/ManeuverDetector.java index b31f723b038..dc7a9118502 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/ManeuverDetector.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/ManeuverDetector.java @@ -36,50 +36,4 @@ public interface ManeuverDetector { */ List detectManeuvers(); - /** - * Derives maneuvers from the provided {@code maneuverCurves}. Since the provided complete maneuver curves already - * include the calculated boundaries of each complete maneuvering spot, this method operates in a very - * performance-efficient manner. - * - * @param maneuverCurves - * The maneuver curves from which the maneuvers shall be derived - * @return The maneuvers derived from the provided maneuver curves. The list gets empty, if the provided maneuver - * curves list is also empty. - */ - List detectManeuvers(Iterable maneuverCurves); - - /** - * Detects the complete maneuver curves performed within a GPS-track of the competitor associated with this - * {@link ManeuverDetector}-instance. In contrast to maneuvers determined by {@link #detectManeuvers()}, the - * complete maneuver curves are not subject to any splitting logic for maneuvers with multiple "tacking" and - * "jibing". See {@link ManeuverDetector} description for more info regarding the detection strategy. - * - * @return an empty list if no maneuver spots were detected, otherwise the list with detected maneuver curves. - * @see CompleteManeuverCurve - * @see ManeuverDetector - */ - List detectCompleteManeuverCurves(); - - /** - * Parses {@link CompleteManeuverCurve}-instances from provided {@link Maneuver}-instances. This method performs - * significantly faster than {@link #detectCompleteManeuverCurves()}. - * - * @param maneuvers - * The maneuvers to parse into complete maneuver curves - * @return an empty list if provided maneuvers list is empty, otherwise the list with complete maneuver curves - * derived from provided maneuvers. - * @see CompleteManeuverCurve - * @see Maneuver - */ - List getCompleteManeuverCurves(Iterable maneuvers); - - /** - * Converts provided {@link CompleteManeuverCurve}-instances into - * {@link CompleteManeuverCurveWithEstimationData}-instances. For this, additional information to - * {@code maneuverCurves} is computed. This computation is regarded as complex as the computation within - * {@link #detectManeuvers()}. - */ - List getCompleteManeuverCurvesWithEstimationData( - Iterable maneuverCurves); - } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/ManeuverDetectorWithEstimationDataSupport.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/ManeuverDetectorWithEstimationDataSupport.java new file mode 100644 index 00000000000..3724d130b25 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/ManeuverDetectorWithEstimationDataSupport.java @@ -0,0 +1,61 @@ +package com.sap.sailing.domain.maneuverdetection; + +import java.util.List; + +import com.sap.sailing.domain.tracking.CompleteManeuverCurve; +import com.sap.sailing.domain.tracking.Maneuver; + +/** + * A maneuver detector which additional support for management of estimation data for wind estimation. + * + * @author Vladislav Chumak (D069712) + * @see ManeuverDetector + * + */ +public interface ManeuverDetectorWithEstimationDataSupport extends ManeuverDetector { + /** + * Derives maneuvers from the provided {@code maneuverCurves}. Since the provided complete maneuver curves already + * include the calculated boundaries of each complete maneuvering spot, this method operates in a very + * performance-efficient manner. + * + * @param maneuverCurves + * The maneuver curves from which the maneuvers shall be derived + * @return The maneuvers derived from the provided maneuver curves. The list gets empty, if the provided maneuver + * curves list is also empty. + */ + List detectManeuvers(Iterable maneuverCurves); + + /** + * Detects the complete maneuver curves performed within a GPS-track of the competitor associated with this + * {@link ManeuverDetector}-instance. In contrast to maneuvers determined by {@link #detectManeuvers()}, the + * complete maneuver curves are not subject to any splitting logic for maneuvers with multiple "tacking" and + * "jibing". See {@link ManeuverDetector} description for more info regarding the detection strategy. + * + * @return an empty list if no maneuver spots were detected, otherwise the list with detected maneuver curves. + * @see CompleteManeuverCurve + * @see ManeuverDetector + */ + List detectCompleteManeuverCurves(); + + /** + * Parses {@link CompleteManeuverCurve}-instances from provided {@link Maneuver}-instances. This method performs + * significantly faster than {@link #detectCompleteManeuverCurves()}. + * + * @param maneuvers + * The maneuvers to parse into complete maneuver curves + * @return an empty list if provided maneuvers list is empty, otherwise the list with complete maneuver curves + * derived from provided maneuvers. + * @see CompleteManeuverCurve + * @see Maneuver + */ + List getCompleteManeuverCurves(Iterable maneuvers); + + /** + * Converts provided {@link CompleteManeuverCurve}-instances into + * {@link CompleteManeuverCurveWithEstimationData}-instances. For this, additional information to + * {@code maneuverCurves} is computed. This computation is regarded as complex as the computation within + * {@link #detectManeuvers()}. + */ + List getCompleteManeuverCurvesWithEstimationData( + Iterable maneuverCurves); +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/AbstractManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/AbstractManeuverDetectorImpl.java new file mode 100644 index 00000000000..a5d63b7e908 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/AbstractManeuverDetectorImpl.java @@ -0,0 +1,155 @@ +package com.sap.sailing.domain.maneuverdetection.impl; + +import java.util.NavigableSet; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.common.BearingChangeAnalyzer; +import com.sap.sailing.domain.common.NauticalSide; +import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.maneuverdetection.ManeuverDetector; +import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries; +import com.sap.sailing.domain.tracking.MarkPassing; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sse.common.Bearing; +import com.sap.sse.common.Duration; +import com.sap.sse.common.TimePoint; + +public abstract class AbstractManeuverDetectorImpl implements ManeuverDetector { + + /** + * Tracked race whose tracks are being processed for maneuver detection. + */ + protected final TrackedRace trackedRace; + + /** + * The competitor, whose maneuvers are being discovered + */ + protected final Competitor competitor; + + /** + * The track of competitor + */ + protected final GPSFixTrack track; + + /** + * Constructs maneuver detector which is supposed to be used for maneuver detection within the provided tracked race + * for provided competitor. + * + * @param trackedRace + * The tracked race whose maneuvers are supposed to be detected + * @param competitor + * The competitor, whose maneuvers shall be discovered + */ + public AbstractManeuverDetectorImpl(TrackedRace trackedRace, Competitor competitor) { + this.trackedRace = trackedRace; + this.competitor = competitor; + this.track = trackedRace != null ? trackedRace.getTrack(competitor) : null; + } + + /** + * Gets track's start time point, end time point and the time point of last raw fix. + * + * @return {@code null} when there are no appropriate fixes contained within the analyzed track + */ + public TrackTimeInfo getTrackTimeInfo() { + NavigableSet markPassings = trackedRace.getMarkPassings(competitor); + TimePoint earliestTrackRecord = null; + TimePoint latestRawFixTimePoint = null; + MarkPassing crossedFinishLine = null; + // getLastWaypoint() will wait for a read lock on the course; do this outside the synchronized block to avoid + // deadlocks + final Waypoint lastWaypoint = trackedRace.getRace().getCourse().getLastWaypoint(); + if (lastWaypoint != null) { + trackedRace.lockForRead(markPassings); + try { + if (markPassings != null && !markPassings.isEmpty()) { + earliestTrackRecord = markPassings.iterator().next().getTimePoint(); + crossedFinishLine = trackedRace.getMarkPassing(competitor, lastWaypoint); + } + } finally { + trackedRace.unlockAfterRead(markPassings); + } + } + if (earliestTrackRecord == null) { + GPSFixMoving firstRawFix = track.getFirstRawFix(); + if (firstRawFix != null) { + earliestTrackRecord = firstRawFix.getTimePoint(); + } + } + if (earliestTrackRecord != null) { + TimePoint latestTrackRecord; + if (crossedFinishLine != null) { + latestTrackRecord = crossedFinishLine.getTimePoint(); + } else { + final GPSFixMoving lastRawFix = track.getLastRawFix(); + if (lastRawFix != null) { + latestTrackRecord = lastRawFix.getTimePoint(); + latestRawFixTimePoint = latestTrackRecord; + } else { + latestTrackRecord = null; + } + } + if (latestTrackRecord != null) { + if (latestRawFixTimePoint == null) { + final GPSFixMoving lastRawFix = track.getLastRawFix(); + if (lastRawFix != null) { + latestRawFixTimePoint = lastRawFix.getTimePoint(); + } + } + if (latestRawFixTimePoint != null) { + if (!earliestTrackRecord.equals(latestTrackRecord)) { + return new TrackTimeInfo(earliestTrackRecord, latestTrackRecord, latestRawFixTimePoint); + } + GPSFixMoving firstRawFix = track.getFirstRawFix(); + if (firstRawFix != null) { + return new TrackTimeInfo(firstRawFix.getTimePoint(), latestRawFixTimePoint, + latestRawFixTimePoint); + } + } + } + } + return null; + } + + /** + * Gets the number of cases, when the boats bow was headed through the wind coming from behind. + */ + protected int getNumberOfJibes(ManeuverCurveBoundaries maneuverBoundaries, Wind wind) { + BearingChangeAnalyzer bearingChangeAnalyzer = BearingChangeAnalyzer.INSTANCE; + int numberOfJibes = wind == null ? 0 + : bearingChangeAnalyzer.didPass(maneuverBoundaries.getSpeedWithBearingBefore().getBearing(), + maneuverBoundaries.getDirectionChangeInDegrees(), + maneuverBoundaries.getSpeedWithBearingAfter().getBearing(), wind.getBearing()); + return numberOfJibes; + } + + /** + * Gets the number of cases, when the boats bow was headed through the wind coming from the front. + */ + protected int getNumberOfTacks(ManeuverCurveBoundaries maneuverBoundaries, Wind wind) { + BearingChangeAnalyzer bearingChangeAnalyzer = BearingChangeAnalyzer.INSTANCE; + int numberOfTacks = wind == null ? 0 + : bearingChangeAnalyzer.didPass(maneuverBoundaries.getSpeedWithBearingBefore().getBearing(), + maneuverBoundaries.getDirectionChangeInDegrees(), + maneuverBoundaries.getSpeedWithBearingAfter().getBearing(), wind.getFrom()); + return numberOfTacks; + } + + /** + * Maps the provided {@code courseChangeInDegrees} from {@link Bearing} to {@link NauticalSide}. + */ + protected NauticalSide getDirectionOfCourseChange(double courseChangeInDegrees) { + return courseChangeInDegrees < 0 ? NauticalSide.PORT : NauticalSide.STARBOARD; + } + + /** + * Gets the approximated duration of the maneuver main curve considering the boat class of the competitor. + */ + protected Duration getApproximateManeuverDuration() { + return trackedRace.getRace().getBoatOfCompetitor(competitor).getBoatClass().getApproximateManeuverDuration(); + } + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/LowGPSSamplingRateManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/LowGPSSamplingRateManeuverDetectorImpl.java new file mode 100644 index 00000000000..7396d284474 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/LowGPSSamplingRateManeuverDetectorImpl.java @@ -0,0 +1,156 @@ +package com.sap.sailing.domain.maneuverdetection.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.CourseChange; +import com.sap.sailing.domain.common.ManeuverType; +import com.sap.sailing.domain.common.NoWindException; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.SpeedWithBearing; +import com.sap.sailing.domain.common.Tack; +import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.maneuverdetection.ApproximatedFixesCalculator; +import com.sap.sailing.domain.maneuverdetection.ManeuverDetector; +import com.sap.sailing.domain.tracking.Maneuver; +import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.impl.ManeuverCurveBoundariesImpl; +import com.sap.sailing.domain.tracking.impl.ManeuverWithCoarseGrainedBoundariesImpl; +import com.sap.sse.common.Bearing; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; + +/** + * Maneuver detector implementation for GPS tracks with extremely low sampling rate such as 1 fix per 30 seconds. + * + * @author Vladislav Chumak (D069712) + * + */ +public class LowGPSSamplingRateManeuverDetectorImpl extends AbstractManeuverDetectorImpl implements ManeuverDetector { + + public LowGPSSamplingRateManeuverDetectorImpl(TrackedRace trackedRace, Competitor competitor) { + super(trackedRace, competitor); + } + + /** + * Tries to detect maneuvers on the competitor's track based on a number of approximating fixes. The + * fixes contain bearing information, but this is not the bearing leading to the next approximation fix but the + * bearing the boat had at the time of the approximating fix which is taken from the original track. + *

+ * + * The time period assumed for a maneuver duration is taken from the + * {@link BoatClass#getApproximateManeuverDurationInMilliseconds() boat class}. If no maneuver is detected, an empty + * list is returned. Maneuvers can only be expected to be detected if at least three fixes are provided in + * approximatedFixesToAnalyze. For the inner approximating fixes (all except the first and the last + * approximating fix), their course changes according to the approximated path (and not the underlying actual + * tracked fixes) are computed. Subsequent course changes to the same direction are then grouped. Those in closer + * timely distance than {@link #getApproximateManeuverDurationInMilliseconds()} (including single course changes + * that have no surrounding other course changes to group) are grouped into one {@link Maneuver}. + * + * @param ignoreMarkPassings + * When true, no {@link ManeuverType#MARK_PASSING} maneuvers will be identified, and the + * fact that a mark passing would split up what else may be a penalty circle is ignored. This is helpful + * for recursive calls, e.g., after identifying a tack and a jibe around a mark passing and trying to + * identify for the time before and after the mark passing which maneuvers exist on which side of the + * passing. + * @param earliestManeuverStart + * maneuver start will not be before this time point; if a maneuver is found whose time point is at or + * after this time point, no matter how close it is, its start regarding speed and course into the + * maneuver and the leg before the maneuver is not taken from an earlier time point, even if half the + * maneuver duration before the maneuver time point were before this time point. + * @param latestManeuverEnd + * maneuver end will not be after this time point; if a maneuver is found whose time point is at or + * before this time point, no matter how close it is, its end regarding speed and course out of the + * maneuver and the leg after the maneuver is not taken from a later time point, even if half the + * maneuver duration after the maneuver time point were after this time point. + * + * @return an empty list if no maneuver is detected for competitor between from and + * to, or else the list of maneuvers detected. + */ + @Override + public List detectManeuvers() { + List result = new ArrayList<>(); + TrackTimeInfo startAndEndTimePoints = getTrackTimeInfo(); + if (startAndEndTimePoints != null) { + ApproximatedFixesCalculator approximatedFixesCalculator = new ApproximatedFixesCalculatorImpl(trackedRace, + competitor); + Iterable approximatedFixes = approximatedFixesCalculator.approximate( + startAndEndTimePoints.getTrackStartTimePoint(), startAndEndTimePoints.getTrackEndTimePoint()); + if (Util.size(approximatedFixes) > 2) { + Iterator approximationPointsIter = approximatedFixes.iterator(); + GPSFixMoving previous = approximationPointsIter.next(); + GPSFixMoving current = approximationPointsIter.next(); + // the bearings in these variables are between approximation points + do { + GPSFixMoving next = approximationPointsIter.next(); + SpeedWithBearing speedWithBearingOnApproximationFromPreviousToCurrent = previous + .getSpeedAndBearingRequiredToReach(current); + SpeedWithBearing speedWithBearingOnApproximationFromCurrentToNext = current + .getSpeedAndBearingRequiredToReach(next); + CourseChange courseChange = speedWithBearingOnApproximationFromPreviousToCurrent + .getCourseChangeRequiredToReach(speedWithBearingOnApproximationFromCurrentToNext); + speedWithBearingOnApproximationFromPreviousToCurrent = speedWithBearingOnApproximationFromCurrentToNext; + Maneuver maneuver = createManeuverFromGroupOfCourseChanges(competitor, + speedWithBearingOnApproximationFromPreviousToCurrent, current, + speedWithBearingOnApproximationFromCurrentToNext, courseChange.getCourseChangeInDegrees()); + result.add(maneuver); + previous = current; + current = next; + } while (approximationPointsIter.hasNext()); + } + } + return result; + } + + private Maneuver createManeuverFromGroupOfCourseChanges(Competitor competitor, + SpeedWithBearing speedWithBearingOnApproximationAtBeginning, GPSFixMoving currentFix, + SpeedWithBearing speedWithBearingOnApproximationAtEnd, double totalCourseChangeInDegrees) { + TimePoint maneuverTimePoint = currentFix.getTimePoint(); + Position maneuverPosition = currentFix.getPosition(); + final Wind wind = trackedRace.getWind(maneuverPosition, maneuverTimePoint); + Tack tackAfterManeuver = null; + try { + tackAfterManeuver = wind == null ? null + : trackedRace.getTack(maneuverPosition, maneuverTimePoint, + speedWithBearingOnApproximationAtEnd.getBearing()); + } catch (NoWindException e) { + } + ManeuverType maneuverType; + ManeuverCurveBoundaries maneuverCurve = new ManeuverCurveBoundariesImpl( + maneuverTimePoint.minus(getApproximateManeuverDuration().divide(2)), + maneuverTimePoint.plus(getApproximateManeuverDuration().times(3.0)), + speedWithBearingOnApproximationAtBeginning, speedWithBearingOnApproximationAtEnd, + totalCourseChangeInDegrees, + speedWithBearingOnApproximationAtBeginning.compareTo(speedWithBearingOnApproximationAtBeginning) < 0 + ? speedWithBearingOnApproximationAtBeginning : speedWithBearingOnApproximationAtEnd); + + if (wind != null) { + if (getNumberOfTacks(maneuverCurve, wind) > 0) { + maneuverType = ManeuverType.TACK; + } else if (getNumberOfJibes(maneuverCurve, wind) > 0) { + maneuverType = ManeuverType.JIBE; + } else { + // heading up or bearing away + Bearing windBearing = wind.getBearing(); + Bearing toWindBeforeManeuver = windBearing + .getDifferenceTo(speedWithBearingOnApproximationAtBeginning.getBearing()); + Bearing toWindAfterManeuver = windBearing + .getDifferenceTo(speedWithBearingOnApproximationAtEnd.getBearing()); + maneuverType = Math.abs(toWindBeforeManeuver.getDegrees()) < Math.abs(toWindAfterManeuver.getDegrees()) + ? ManeuverType.HEAD_UP : ManeuverType.BEAR_AWAY; + } + } else { + // no wind information; marking as UNKNOWN + maneuverType = ManeuverType.UNKNOWN; + } + Maneuver maneuver = new ManeuverWithCoarseGrainedBoundariesImpl(maneuverType, tackAfterManeuver, + maneuverPosition, maneuverTimePoint, maneuverCurve); + return maneuver; + } + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java index 6572f25f378..e7d32f9abb1 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java @@ -5,10 +5,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.NavigableSet; import java.util.function.Predicate; import java.util.logging.Logger; -import java.util.stream.Collectors; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -21,12 +19,9 @@ import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.Tack; import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.maneuverdetection.CompleteManeuverCurveWithEstimationData; -import com.sap.sailing.domain.maneuverdetection.ManeuverCurveWithUnstableCourseAndSpeedWithEstimationData; +import com.sap.sailing.domain.maneuverdetection.ApproximatedFixesCalculator; import com.sap.sailing.domain.maneuverdetection.ManeuverDetector; -import com.sap.sailing.domain.maneuverdetection.ManeuverMainCurveWithEstimationData; import com.sap.sailing.domain.tracking.CompleteManeuverCurve; import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.Maneuver; @@ -56,7 +51,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; * @see ManeuverDetector * */ -public class ManeuverDetectorImpl implements ManeuverDetector { +public class ManeuverDetectorImpl extends AbstractManeuverDetectorImpl { private static final Logger logger = Logger.getLogger(ManeuverDetectorImpl.class.getName()); @@ -72,28 +67,11 @@ public class ManeuverDetectorImpl implements ManeuverDetector { */ private static final double MIN_ANGULAR_VELOCITY_FOR_MAIN_CURVE_BOUNDARIES_IN_DEGREES_PER_SECOND = 0.2; - /** - * Tracked race whose tracks are being processed for maneuver detection. - */ - protected final TrackedRace trackedRace; - - /** - * The competitor, whose maneuvers are being discovered - */ - protected final Competitor competitor; - - /** - * The track of competitor - */ - protected final GPSFixTrack track; - /** * Constructor for unit tests only. */ public ManeuverDetectorImpl() { - trackedRace = null; - competitor = null; - track = null; + super(null, null); } /** @@ -106,9 +84,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * The competitor, whose maneuvers shall be discovered */ public ManeuverDetectorImpl(TrackedRace trackedRace, Competitor competitor) { - this.trackedRace = trackedRace; - this.competitor = competitor; - this.track = trackedRace.getTrack(competitor); + super(trackedRace, competitor); } @Override @@ -116,355 +92,6 @@ public class ManeuverDetectorImpl implements ManeuverDetector { return getAllManeuversFromManeuverSpots(detectManeuverSpots()); } - @Override - public List detectManeuvers(Iterable maneuverCurves) { - List maneuvers = new ArrayList<>(); - for (CompleteManeuverCurve maneuverCurve : maneuverCurves) { - TimePoint maneuverTimePoint = maneuverCurve.getMainCurveBoundaries().getTimePoint(); - Position maneuverPosition = track.getEstimatedPosition(maneuverTimePoint, /* extrapolate */false); - Wind wind = trackedRace.getWind(maneuverPosition, maneuverTimePoint); - maneuvers.addAll(determineManeuversFromManeuverCurve(maneuverCurve.getMainCurveBoundaries(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries(), wind, - maneuverCurve.getMarkPassing())); - } - return maneuvers; - } - - @Override - public List detectCompleteManeuverCurves() { - List maneuverSpots = detectManeuverSpots(); - return maneuverSpots.stream().filter(maneuverSpot -> maneuverSpot.getManeuverCurve() != null) - .map(maneuverSpot -> maneuverSpot.getManeuverCurve()).collect(Collectors.toList()); - } - - @Override - public List getCompleteManeuverCurves(Iterable maneuvers) { - List result = new ArrayList<>(); - CompleteManeuverCurve curveToAdd = null; - boolean previousManeuverCouldBelongToSameCurve = false; - Maneuver previousManeuver = null; - for (Maneuver maneuver : maneuvers) { - boolean maneuverCouldBelongToSameCurve = maneuver.getType() == ManeuverType.PENALTY_CIRCLE - || maneuver.isMarkPassing() - && (maneuver.getType() == ManeuverType.TACK || maneuver.getType() == ManeuverType.JIBE); - if (previousManeuverCouldBelongToSameCurve && maneuverCouldBelongToSameCurve - && previousManeuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter() - .equals(maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore()) - && previousManeuver.getToSide() == maneuver.getToSide()) { - curveToAdd = extendCompleteManeuverCurveWithManeuver(curveToAdd, maneuver); - } else { - if (curveToAdd != null) { - result.add(curveToAdd); - } - curveToAdd = convertManeuverToCompleteManeuverCurve(maneuver); - } - previousManeuver = maneuver; - previousManeuverCouldBelongToSameCurve = maneuverCouldBelongToSameCurve; - } - if (curveToAdd != null) { - result.add(curveToAdd); - } - return result; - } - - /** - * Converts the provided maneuver into {@link CompleteManeuverCurve}. The boundaries of provided maneuver are reused - * for the resulting complete maneuver curve. - * - * @see CompleteManeuverCurve - * @see Maneuver - */ - private CompleteManeuverCurve convertManeuverToCompleteManeuverCurve(Maneuver maneuver) { - ManeuverMainCurveDetailsWithBearingSteps mainCurveBoundaries = new ManeuverMainCurveDetailsWithBearingSteps( - maneuver.getMainCurveBoundaries().getTimePointBefore(), - maneuver.getMainCurveBoundaries().getTimePointAfter(), maneuver.getTimePoint(), - maneuver.getMainCurveBoundaries().getSpeedWithBearingBefore(), - maneuver.getMainCurveBoundaries().getSpeedWithBearingAfter(), - maneuver.getMainCurveBoundaries().getDirectionChangeInDegrees(), - maneuver.getMaxTurningRateInDegreesPerSecond(), maneuver.getMainCurveBoundaries().getLowestSpeed(), - getSpeedWithBearingSteps(maneuver.getMainCurveBoundaries().getTimePointBefore(), - maneuver.getMainCurveBoundaries().getTimePointAfter())); - return new CompleteManeuverCurveImpl(mainCurveBoundaries, - maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries(), maneuver.getMarkPassing()); - } - - /** - * Extends the end of provided maneuver curve with the end of provided maneuver. For this, the curve boundaries with - * unstable course and speed are merged by appending, whereas the maneuver main curve gets recalculated completely - * from scratch. The additional attributes such as, direction change and lowest speed get adjusted accordingly. - */ - private CompleteManeuverCurve extendCompleteManeuverCurveWithManeuver(CompleteManeuverCurve maneuverCurve, - Maneuver maneuver) { - ManeuverMainCurveDetailsWithBearingSteps mainCurveDetails = computeManeuverMainCurveDetails( - maneuverCurve.getMainCurveBoundaries().getTimePointBefore(), - maneuver.getMainCurveBoundaries().getTimePointAfter(), maneuver.getToSide()); - if (mainCurveDetails == null) { - return maneuverCurve; - } - ManeuverCurveBoundaries maneuverCurveWithStableSpeedAndCourseBoundaries = new ManeuverCurveBoundariesImpl( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), - maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingBefore(), - maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingAfter(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getDirectionChangeInDegrees() - + maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getDirectionChangeInDegrees(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getLowestSpeed() - .compareTo(maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getLowestSpeed()) > 0 - ? maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getLowestSpeed() - : maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getLowestSpeed()); - return new CompleteManeuverCurveImpl(mainCurveDetails, maneuverCurveWithStableSpeedAndCourseBoundaries, - maneuverCurve.getMarkPassing() == null ? maneuver.getMarkPassing() : maneuverCurve.getMarkPassing()); - } - - @Override - public List getCompleteManeuverCurvesWithEstimationData( - Iterable maneuverCurves) { - List result = new ArrayList<>(); - - CompleteManeuverCurve previousManeuverCurve = null; - CompleteManeuverCurve currentManeuverCurve = null; - for (CompleteManeuverCurve nextManeuverCurve : maneuverCurves) { - if (currentManeuverCurve != null) { - CompleteManeuverCurveWithEstimationData maneuverCurveWithEstimationData = calculateCompleteManeuverCurveWithEstimationData( - currentManeuverCurve, previousManeuverCurve, nextManeuverCurve); - result.add(maneuverCurveWithEstimationData); - } - previousManeuverCurve = currentManeuverCurve; - currentManeuverCurve = nextManeuverCurve; - } - if (currentManeuverCurve != null) { - CompleteManeuverCurveWithEstimationData maneuverCurveWithEstimationData = calculateCompleteManeuverCurveWithEstimationData( - currentManeuverCurve, previousManeuverCurve, null); - result.add(maneuverCurveWithEstimationData); - } - return result; - } - - /** - * Calculates a {@link CompleteManeuverCurveWithEstimationData}-instance for the provided {@code maneuverCurve}. The - * computation of additional information required by {@link CompleteManeuverCurveWithEstimationData} is regarded as - * computationally-intensive. - */ - private CompleteManeuverCurveWithEstimationData calculateCompleteManeuverCurveWithEstimationData( - CompleteManeuverCurve maneuverCurve, CompleteManeuverCurve previousManeuverCurve, - CompleteManeuverCurve nextManeuverCurve) { - Bearing courseAtMaxTurningRate = null; - SpeedWithBearingStep stepWithLowestSpeed = null; - SpeedWithBearingStep stepWithHighestSpeed = null; - SpeedWithBearingStep stepWithMaxTurningRate = null; - SpeedWithBearingStep previousStep = null; - for (SpeedWithBearingStep step : maneuverCurve.getMainCurveBoundaries().getSpeedWithBearingSteps()) { - if (stepWithLowestSpeed == null - || stepWithLowestSpeed.getSpeedWithBearing().compareTo(step.getSpeedWithBearing()) > 0) { - stepWithLowestSpeed = step; - } - if (stepWithHighestSpeed == null - || stepWithHighestSpeed.getSpeedWithBearing().compareTo(step.getSpeedWithBearing()) < 0) { - stepWithHighestSpeed = step; - } - if (previousStep != null && (stepWithMaxTurningRate == null || stepWithMaxTurningRate - .getTurningRateInDegreesPerSecond() < step.getTurningRateInDegreesPerSecond())) { - stepWithMaxTurningRate = step; - courseAtMaxTurningRate = previousStep.getSpeedWithBearing().getBearing() - .add(new DegreeBearingImpl(step.getCourseChangeInDegrees() / 2)); - } - previousStep = step; - } - int gpsFixCountWithinMainCurve = 0; - int gpsFixCountWithinWholeCurve = 0; - int gpsFixesCountFromPreviousManeuver = 0; - int gpsFixesCountToNextManeuver = 0; - try { - track.lockForRead(); - boolean considerPreviousManeuver = previousManeuverCurve != null && previousManeuverCurve - .getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter() - .before(maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore()); - boolean considerNextManeuver = nextManeuverCurve != null && nextManeuverCurve - .getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore() - .after(maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter()); - for (GPSFixMoving fix : track.getFixes( - considerPreviousManeuver - ? previousManeuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries() - .getTimePointAfter() - : maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), - !considerPreviousManeuver, - considerNextManeuver - ? nextManeuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries() - .getTimePointBefore() - : maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), - !considerNextManeuver)) { - if (fix.getTimePoint().before( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore())) { - ++gpsFixesCountFromPreviousManeuver; - } else if (fix.getTimePoint().after( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter())) { - ++gpsFixesCountToNextManeuver; - } else { - if (!fix.getTimePoint().before(maneuverCurve.getMainCurveBoundaries().getTimePointBefore()) - && !fix.getTimePoint().after(maneuverCurve.getMainCurveBoundaries().getTimePointAfter())) { - ++gpsFixCountWithinMainCurve; - } - ++gpsFixCountWithinWholeCurve; - } - } - } finally { - track.unlockAfterRead(); - } - - ManeuverLoss projectedManeuverLoss = getManeuverLoss(maneuverCurve.getMainCurveBoundaries()); - Distance distanceSailedIfNotManeuvering = maneuverCurve.getMainCurveBoundaries().getSpeedWithBearingBefore() - .travel(maneuverCurve.getMainCurveBoundaries().getDuration()); - Distance distanceSailedWithinManeuver = track.getDistanceTraveled( - maneuverCurve.getMainCurveBoundaries().getTimePointBefore(), - maneuverCurve.getMainCurveBoundaries().getTimePointAfter()); - Duration longestGpsFixIntervalBetweenTwoFixes = track.getLongestIntervalBetweenTwoFixes( - maneuverCurve.getMainCurveBoundaries().getTimePointBefore(), - maneuverCurve.getMainCurveBoundaries().getTimePointAfter()); - ManeuverMainCurveWithEstimationData mainCurve = new ManeuverMainCurveWithEstimationDataImpl( - maneuverCurve.getMainCurveBoundaries().getTimePointBefore(), - maneuverCurve.getMainCurveBoundaries().getTimePointAfter(), - maneuverCurve.getMainCurveBoundaries().getSpeedWithBearingBefore(), - maneuverCurve.getMainCurveBoundaries().getSpeedWithBearingAfter(), - maneuverCurve.getMainCurveBoundaries().getDirectionChangeInDegrees(), - stepWithLowestSpeed.getSpeedWithBearing(), stepWithLowestSpeed.getTimePoint(), - stepWithHighestSpeed.getSpeedWithBearing(), stepWithHighestSpeed.getTimePoint(), - maneuverCurve.getMainCurveBoundaries().getTimePoint(), - maneuverCurve.getMainCurveBoundaries().getMaxTurningRateInDegreesPerSecond(), courseAtMaxTurningRate, - distanceSailedWithinManeuver, projectedManeuverLoss.getDistanceSailed(), distanceSailedIfNotManeuvering, - projectedManeuverLoss.getDistanceSailedIfNotManeuvering(), - Math.abs(maneuverCurve.getMainCurveBoundaries().getDirectionChangeInDegrees()) - / maneuverCurve.getMainCurveBoundaries().getDuration().asSeconds(), - gpsFixCountWithinMainCurve, longestGpsFixIntervalBetweenTwoFixes); - projectedManeuverLoss = getManeuverLoss(maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries()); - distanceSailedIfNotManeuvering = maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries() - .getSpeedWithBearingBefore() - .travel(maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getDuration()); - distanceSailedWithinManeuver = track.getDistanceTraveled( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter()); - longestGpsFixIntervalBetweenTwoFixes = track.getLongestIntervalBetweenTwoFixes( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter()); - TrackTimeInfo trackTimeInfo = previousManeuverCurve == null || nextManeuverCurve == null ? getTrackTimeInfo() - : null; - Pair durationAndAvgSpeedWithBearingBefore = calculateDurationAndAvgSpeedWithBearingBetweenTimePoints( - previousManeuverCurve == null ? trackTimeInfo.getTrackStartTimePoint() - : previousManeuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries() - .getTimePointAfter(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore()); - Pair durationAndAvgSpeedWithBearingAfter = calculateDurationAndAvgSpeedWithBearingBetweenTimePoints( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), - nextManeuverCurve == null ? trackTimeInfo.getTrackEndTimePoint() - : nextManeuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore()); - Duration intervalBetweenLastFixOfCurveAndNextFix = Duration.NULL; - GPSFixMoving lastManeuverFix = track.getLastFixAtOrBefore( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter()); - if (lastManeuverFix != null) { - GPSFixMoving firstFixAfterLastManeuverFix = track.getFirstFixAfter(lastManeuverFix.getTimePoint()); - if (firstFixAfterLastManeuverFix != null) { - intervalBetweenLastFixOfCurveAndNextFix = lastManeuverFix.getTimePoint() - .until(firstFixAfterLastManeuverFix.getTimePoint()); - } - } - Duration intervalBetweenFirstFixOfCurveAndPreviousFix = Duration.NULL; - GPSFixMoving firstManeuverFix = track.getFirstFixAtOrAfter( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore()); - if (firstManeuverFix != null) { - GPSFixMoving lastFixBeforeFirstManeuverFix = track.getLastFixBefore(firstManeuverFix.getTimePoint()); - if (lastFixBeforeFirstManeuverFix != null) { - intervalBetweenFirstFixOfCurveAndPreviousFix = lastFixBeforeFirstManeuverFix.getTimePoint() - .until(firstManeuverFix.getTimePoint()); - } - } - ManeuverCurveWithUnstableCourseAndSpeedWithEstimationData curveWithUnstableCourseAndSpeed = new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataImpl( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingBefore(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingAfter(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getDirectionChangeInDegrees(), - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getLowestSpeed(), - durationAndAvgSpeedWithBearingBefore.getB(), durationAndAvgSpeedWithBearingBefore.getA(), - gpsFixesCountFromPreviousManeuver, durationAndAvgSpeedWithBearingAfter.getB(), - durationAndAvgSpeedWithBearingAfter.getA(), gpsFixesCountToNextManeuver, distanceSailedWithinManeuver, - projectedManeuverLoss.getDistanceSailed(), distanceSailedIfNotManeuvering, - projectedManeuverLoss.getDistanceSailedIfNotManeuvering(), gpsFixCountWithinWholeCurve, - longestGpsFixIntervalBetweenTwoFixes, intervalBetweenLastFixOfCurveAndNextFix, - intervalBetweenFirstFixOfCurveAndPreviousFix); - TimePoint maneuverTimePoint = maneuverCurve.getMainCurveBoundaries().getTimePoint(); - Position maneuverPosition = track.getEstimatedPosition(maneuverTimePoint, /* extrapolate */false); - Wind wind = trackedRace.getWind(maneuverPosition, maneuverTimePoint); - int numberOfJibes = getNumberOfJibes(mainCurve, wind); - int numberOfTacks = getNumberOfTacks(mainCurve, wind); - boolean maneuverStartsByRunningAwayFromWind = (mainCurve.getSpeedWithBearingBefore().getBearing().getDegrees() - - 180) * mainCurve.getDirectionChangeInDegrees() < 0; - Bearing relativeBearingToNextMarkPassingBeforeManeuver = getRelativeBearingToNextMark( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), maneuverCurve - .getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingBefore().getBearing()); - Bearing relativeBearingToNextMarkPassingAfterManeuver = getRelativeBearingToNextMark( - maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), maneuverCurve - .getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingAfter().getBearing()); - return new CompleteManeuverCurveWithEstimationDataImpl(maneuverPosition, mainCurve, - curveWithUnstableCourseAndSpeed, wind, numberOfTacks, numberOfJibes, - maneuverStartsByRunningAwayFromWind, relativeBearingToNextMarkPassingBeforeManeuver, - relativeBearingToNextMarkPassingAfterManeuver, maneuverCurve.isMarkPassing()); - } - - /** - * Calculates the duration and avg speed with avg course based on the competitor's track within the provided time - * range. - */ - private Pair calculateDurationAndAvgSpeedWithBearingBetweenTimePoints(TimePoint from, - TimePoint to) { - Duration duration = from.until(to); - Position fromPosition = track.getEstimatedPosition(from, false); - Position toPosition = track.getEstimatedPosition(to, false); - Distance distance = fromPosition.getDistance(toPosition); - Bearing bearing = fromPosition.getBearingGreatCircle(toPosition); - Speed speed = distance.inTime(Math.abs(duration.asMillis())); - SpeedWithBearing avgSpeedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), bearing); - return new Pair<>(duration, avgSpeedWithBearing); - } - - /** - * Gets the relative bearing of the next mark from the boat's position and course at {@code timePoint}. The relative - * bearing is calculated by absolute bearing of next mark from the boat's position minus the boat's course. - */ - private Bearing getRelativeBearingToNextMark(TimePoint timePoint, Bearing boatCourse) { - Bearing result = null; - TrackedLegOfCompetitor legAfter = trackedRace.getTrackedLeg(competitor, timePoint); - if (legAfter != null && legAfter.getLeg().getTo() != null) { - Position nextMarkPosition = trackedRace.getApproximatePosition(legAfter.getLeg().getTo(), timePoint); - Position maneuverEndPosition = track.getEstimatedPosition(timePoint, false); - Bearing absoluteBearing = maneuverEndPosition.getBearingGreatCircle(nextMarkPosition); - result = absoluteBearing.getDifferenceTo(boatCourse); - } - return result; - } - - /** - * Gets the number of cases, when the boats bow was headed through the wind coming from behind. - */ - private int getNumberOfJibes(ManeuverCurveBoundaries maneuverBoundaries, Wind wind) { - BearingChangeAnalyzer bearingChangeAnalyzer = BearingChangeAnalyzer.INSTANCE; - int numberOfJibes = wind == null ? 0 - : bearingChangeAnalyzer.didPass(maneuverBoundaries.getSpeedWithBearingBefore().getBearing(), - maneuverBoundaries.getDirectionChangeInDegrees(), - maneuverBoundaries.getSpeedWithBearingAfter().getBearing(), wind.getBearing()); - return numberOfJibes; - } - - /** - * Gets the number of cases, when the boats bow was headed through the wind coming from the front. - */ - private int getNumberOfTacks(ManeuverCurveBoundaries maneuverBoundaries, Wind wind) { - BearingChangeAnalyzer bearingChangeAnalyzer = BearingChangeAnalyzer.INSTANCE; - int numberOfTacks = wind == null ? 0 - : bearingChangeAnalyzer.didPass(maneuverBoundaries.getSpeedWithBearingBefore().getBearing(), - maneuverBoundaries.getDirectionChangeInDegrees(), - maneuverBoundaries.getSpeedWithBearingAfter().getBearing(), wind.getFrom()); - return numberOfTacks; - } - /** * Detects maneuver spots performed within a GPS-track of the competitor associated with this * {@link ManeuverDetector}-instance. See {@link ManeuverDetector} description for more info regarding the detection @@ -483,70 +110,6 @@ public class ManeuverDetectorImpl implements ManeuverDetector { return Collections.emptyList(); } - /** - * Gets track's start time point, end time point and the time point of last raw fix. - * - * @return {@code null} when there are no appropriate fixes contained within the analyzed track - */ - public TrackTimeInfo getTrackTimeInfo() { - NavigableSet markPassings = trackedRace.getMarkPassings(competitor); - TimePoint earliestTrackRecord = null; - TimePoint latestRawFixTimePoint = null; - MarkPassing crossedFinishLine = null; - // getLastWaypoint() will wait for a read lock on the course; do this outside the synchronized block to avoid - // deadlocks - final Waypoint lastWaypoint = trackedRace.getRace().getCourse().getLastWaypoint(); - if (lastWaypoint != null) { - trackedRace.lockForRead(markPassings); - try { - if (markPassings != null && !markPassings.isEmpty()) { - earliestTrackRecord = markPassings.iterator().next().getTimePoint(); - crossedFinishLine = trackedRace.getMarkPassing(competitor, lastWaypoint); - } - } finally { - trackedRace.unlockAfterRead(markPassings); - } - } - if (earliestTrackRecord == null) { - GPSFixMoving firstRawFix = track.getFirstRawFix(); - if (firstRawFix != null) { - earliestTrackRecord = firstRawFix.getTimePoint(); - } - } - if (earliestTrackRecord != null) { - TimePoint latestTrackRecord; - if (crossedFinishLine != null) { - latestTrackRecord = crossedFinishLine.getTimePoint(); - } else { - final GPSFixMoving lastRawFix = track.getLastRawFix(); - if (lastRawFix != null) { - latestTrackRecord = lastRawFix.getTimePoint(); - latestRawFixTimePoint = latestTrackRecord; - } else { - latestTrackRecord = null; - } - } - if (latestTrackRecord != null) { - if (latestRawFixTimePoint == null) { - final GPSFixMoving lastRawFix = track.getLastRawFix(); - if (lastRawFix != null) { - latestRawFixTimePoint = lastRawFix.getTimePoint(); - } - } - if (latestRawFixTimePoint != null) { - if(!earliestTrackRecord.equals(latestTrackRecord)) { - return new TrackTimeInfo(earliestTrackRecord, latestTrackRecord, latestRawFixTimePoint); - } - GPSFixMoving firstRawFix = track.getFirstRawFix(); - if(firstRawFix != null) { - return new TrackTimeInfo(firstRawFix.getTimePoint(), latestRawFixTimePoint, latestRawFixTimePoint); - } - } - } - } - return null; - } - /** * Detects the maneuver spots with corresponding maneuvers within provided time frame. See step 1ff. in * {@link ManeuverDetector} description. @@ -566,12 +129,11 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * to, or else the list of maneuver spots with corresponding maneuvers detected. */ protected List detectManeuvers(TimePoint earliestManeuverStart, TimePoint latestManeuverEnd) { - return detectManeuvers( - trackedRace.approximate(competitor, - trackedRace.getRace().getBoatOfCompetitor(competitor).getBoatClass() - .getMaximumDistanceForCourseApproximation(), - earliestManeuverStart, latestManeuverEnd), - earliestManeuverStart, latestManeuverEnd); + ApproximatedFixesCalculator approximatedFixesCalculator = new ApproximatedFixesCalculatorImpl(trackedRace, + competitor); + Iterable approximatedFixes = approximatedFixesCalculator.approximate(earliestManeuverStart, + latestManeuverEnd); + return detectManeuvers(approximatedFixes, earliestManeuverStart, latestManeuverEnd); } /** @@ -621,13 +183,6 @@ public class ManeuverDetectorImpl implements ManeuverDetector { } - /** - * Maps the provided {@code courseChangeInDegrees} from {@link Bearing} to {@link NauticalSide}. - */ - protected NauticalSide getDirectionOfCourseChange(double courseChangeInDegrees) { - return courseChangeInDegrees < 0 ? NauticalSide.PORT : NauticalSide.STARBOARD; - } - /** * Checks whether {@code currentFix} can be grouped together with the previous fixes in order to be regarded as a * single maneuver spot. For this, the {@code newCourseChangeDirection must match the direction of provided @@ -660,6 +215,16 @@ public class ManeuverDetectorImpl implements ManeuverDetector { return true; } + protected List getAllManeuversFromManeuverSpots(List maneuverSpots) { + List maneuvers = new ArrayList<>(); + for (ManeuverSpot maneuverSpot : maneuverSpots) { + for (Maneuver maneuver : maneuverSpot.getManeuvers()) { + maneuvers.add(maneuver); + } + } + return maneuvers; + } + /** * Determines course change direction around the provided {@code fix} by means of * {@link #getSpeedWithBearingSteps(TimePoint, TimePoint)}. The course change analysis considers fixes within @@ -894,14 +459,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector { } else { Pair mainCurves = splitManeuverMainCurveByTimePoint( maneuverMainCurveDetails, firstPenaltyCircleCompletedAt); - if (mainCurves.getA() == null || mainCurves.getB() == null) { - // This should really not happen! - logger.warning( - "Maneuver detection has failed to process penalty circle maneuver correctly, because refinedPenaltyMainCurveDetails computation returned null. Race-Id: " - + trackedRace.getRace().getId() + ", Competitor: " + competitor.getName() - + ", Time point before maneuver: " - + maneuverUnstableCourseAndSpeedBoundaries.getTimePointBefore()); - } else { + if (mainCurves.getA() != null && mainCurves.getB() != null) { maneuversAlreadyAdded = true; Pair maneuverUnstableCourseAndSpeedBoundariesPair = splitManeuverCurveWithStableSpeedAndCourseByTimePoint( maneuverUnstableCourseAndSpeedBoundaries, mainCurves.getA(), mainCurves.getB(), @@ -1155,7 +713,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * distance" is compared to the competitor's actual position at that time. This distance is returned as the result * of this method. */ - private ManeuverLoss getManeuverLoss(ManeuverCurveBoundaries maneuverBoundaries) { + protected ManeuverLoss getManeuverLoss(ManeuverCurveBoundaries maneuverBoundaries) { final GPSFixTrack track = trackedRace.getTrack(competitor); SpeedWithBearing speedWhenSpeedStartedToDrop = maneuverBoundaries.getSpeedWithBearingBefore(); SpeedWithBearing speedAfterManeuver = maneuverBoundaries.getSpeedWithBearingAfter(); @@ -1192,16 +750,6 @@ public class ManeuverDetectorImpl implements ManeuverDetector { return approximateManeuverDuration.divide(2); } - protected List getAllManeuversFromManeuverSpots(List maneuverSpots) { - List maneuvers = new ArrayList<>(); - for (ManeuverSpot maneuverSpot : maneuverSpots) { - for (Maneuver maneuver : maneuverSpot.getManeuvers()) { - maneuvers.add(maneuver); - } - } - return maneuvers; - } - /** * Starting at timePointBeforeManeuver, and assuming that the group of * approximatedFixesAndCourseChanges contains at least a tack and a jibe, finds the approximated fix's @@ -1252,6 +800,9 @@ public class ManeuverDetectorImpl implements ManeuverDetector { } } } + if(result == null) { + System.out.println("a"); + } return result; } @@ -1271,8 +822,8 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * The target course change direction for the main curve to determine * @return The details of the maneuver main curve */ - private ManeuverMainCurveDetailsWithBearingSteps computeManeuverMainCurveDetails(TimePoint timePointBeforeManeuver, - TimePoint timePointAfterManeuver, NauticalSide maneuverDirection) { + protected ManeuverMainCurveDetailsWithBearingSteps computeManeuverMainCurveDetails( + TimePoint timePointBeforeManeuver, TimePoint timePointAfterManeuver, NauticalSide maneuverDirection) { SpeedWithBearingStepsIterable stepsToAnalyze = getSpeedWithBearingSteps(timePointBeforeManeuver, timePointAfterManeuver); ManeuverMainCurveDetailsWithBearingSteps maneuverMainCurveDetails = computeManeuverMainCurve(stepsToAnalyze, @@ -1285,7 +836,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * the steps, performance costy call to {@link GPSFixTrack#getSpeedWithBearingSteps(TimePoint, TimePoint, Duration)} * is made. */ - private SpeedWithBearingStepsIterable getSpeedWithBearingSteps(TimePoint timePointBeforeManeuver, + protected SpeedWithBearingStepsIterable getSpeedWithBearingSteps(TimePoint timePointBeforeManeuver, TimePoint timePointAfterManeuver) { SpeedWithBearingStepsIterable stepsToAnalyze = track.getSpeedWithBearingSteps(timePointBeforeManeuver, timePointAfterManeuver); @@ -1302,10 +853,10 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * approximate the beginning time point of the maneuver, the speed maximum is determined throughout forward in time * iteration of speed steps starting from time point of main curve beginning. From the determined speed maximum, the * iteration continues until the point, when the bearing changes occur only with a maximum of - * {@value #MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS} degrees per second, which is - * regarded as a stable course. The exiting time point of maneuver is approximated analogously by speed maximum - * determination throughout backward in time iteration of speed steps starting from time of main curve end, followed - * by a search for a point with stable course. + * {@value #MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS} degrees per second, which is regarded as + * a stable course. The exiting time point of maneuver is approximated analogously by speed maximum determination + * throughout backward in time iteration of speed steps starting from time of main curve end, followed by a search + * for a point with stable course. * * @param maneuverMainCurveDetails * The details of the main curve, ideally computed by @@ -1354,8 +905,8 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * determined, the course changes get analyzed starting from {@code t'} until {@code (t -} * {@link BoatClass#getApproximateManeuverDurationInMilliseconds() approx. maneuver duration}{@code )} in order to * locate the point where the bearing starts to change with a rate of maximal - * {@value #MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS} degrees per second, which is - * regarded as a stable course. + * {@value #MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS} degrees per second, which is regarded as + * a stable course. * * @param maneuverMainCurveDetails * The details of the main curve, ideally computed by @@ -1423,8 +974,8 @@ public class ManeuverDetectorImpl implements ManeuverDetector { * determined, the course changes get analyzed starting from {@code t'} until {@code (t +} * {@link BoatClass#getApproximateManeuverDurationInMilliseconds() approx. maneuver duration} {@code * 3)} in order * to locate the point where the bearing starts to change with a rate of maximal - * {@value #MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS} degrees per second, which is - * regarded as a stable course. + * {@value #MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS} degrees per second, which is regarded as + * a stable course. * * @param maneuverMainCurveDetails * The details of the main curve, ideally computed by @@ -1776,11 +1327,4 @@ public class ManeuverDetectorImpl implements ManeuverDetector { return new SpeedWithBearingStepsIterable(maneuverBearingSteps); } - /** - * Gets the approximated duration of the maneuver main curve considering the boat class of the competitor. - */ - protected Duration getApproximateManeuverDuration() { - return trackedRace.getRace().getBoatOfCompetitor(competitor).getBoatClass().getApproximateManeuverDuration(); - } - } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java new file mode 100644 index 00000000000..689df4a4736 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java @@ -0,0 +1,404 @@ +package com.sap.sailing.domain.maneuverdetection.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.common.ManeuverType; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.SpeedWithBearing; +import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.maneuverdetection.CompleteManeuverCurveWithEstimationData; +import com.sap.sailing.domain.maneuverdetection.ManeuverCurveWithUnstableCourseAndSpeedWithEstimationData; +import com.sap.sailing.domain.maneuverdetection.ManeuverDetector; +import com.sap.sailing.domain.maneuverdetection.ManeuverDetectorWithEstimationDataSupport; +import com.sap.sailing.domain.maneuverdetection.ManeuverMainCurveWithEstimationData; +import com.sap.sailing.domain.tracking.CompleteManeuverCurve; +import com.sap.sailing.domain.tracking.Maneuver; +import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries; +import com.sap.sailing.domain.tracking.SpeedWithBearingStep; +import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; +import com.sap.sailing.domain.tracking.impl.CompleteManeuverCurveImpl; +import com.sap.sailing.domain.tracking.impl.ManeuverCurveBoundariesImpl; +import com.sap.sailing.domain.tracking.impl.NonCachingMarkPositionAtTimePointCache; +import com.sap.sse.common.Bearing; +import com.sap.sse.common.Distance; +import com.sap.sse.common.Duration; +import com.sap.sse.common.Speed; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.impl.DegreeBearingImpl; + +/** + * A decorator which adds support for management of estimation data for wind estimation to an existing maneuver detector + * implementation. + * + * @author Vladislav Chumak (D069712) + * @see ManeuverDetector + * + */ +public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl + implements ManeuverDetectorWithEstimationDataSupport { + + private ManeuverDetectorImpl maneuverDetector; + + public ManeuverDetectorWithEstimationDataSupportDecoratorImpl(ManeuverDetectorImpl maneuverDetector) { + this.maneuverDetector = maneuverDetector; + } + + @Override + public List detectManeuvers() { + return maneuverDetector.detectManeuvers(); + } + + @Override + public List detectManeuvers(Iterable maneuverCurves) { + List maneuvers = new ArrayList<>(); + for (CompleteManeuverCurve maneuverCurve : maneuverCurves) { + TimePoint maneuverTimePoint = maneuverCurve.getMainCurveBoundaries().getTimePoint(); + Position maneuverPosition = maneuverDetector.track.getEstimatedPosition(maneuverTimePoint, + /* extrapolate */false); + Wind wind = maneuverDetector.trackedRace.getWind(maneuverPosition, maneuverTimePoint); + maneuvers + .addAll(maneuverDetector.determineManeuversFromManeuverCurve(maneuverCurve.getMainCurveBoundaries(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries(), wind, + maneuverCurve.getMarkPassing())); + } + return maneuvers; + } + + @Override + public List detectCompleteManeuverCurves() { + List maneuverSpots = maneuverDetector.detectManeuverSpots(); + return maneuverSpots.stream().filter(maneuverSpot -> maneuverSpot.getManeuverCurve() != null) + .map(maneuverSpot -> maneuverSpot.getManeuverCurve()).collect(Collectors.toList()); + } + + @Override + public List getCompleteManeuverCurves(Iterable maneuvers) { + List result = new ArrayList<>(); + CompleteManeuverCurve curveToAdd = null; + boolean previousManeuverCouldBelongToSameCurve = false; + Maneuver previousManeuver = null; + for (Maneuver maneuver : maneuvers) { + boolean maneuverCouldBelongToSameCurve = maneuver.getType() == ManeuverType.PENALTY_CIRCLE + || maneuver.isMarkPassing() + && (maneuver.getType() == ManeuverType.TACK || maneuver.getType() == ManeuverType.JIBE); + if (previousManeuverCouldBelongToSameCurve && maneuverCouldBelongToSameCurve + && previousManeuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter() + .equals(maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore()) + && previousManeuver.getToSide() == maneuver.getToSide()) { + curveToAdd = extendCompleteManeuverCurveWithManeuver(curveToAdd, maneuver); + } else { + if (curveToAdd != null) { + result.add(curveToAdd); + } + curveToAdd = convertManeuverToCompleteManeuverCurve(maneuver); + } + previousManeuver = maneuver; + previousManeuverCouldBelongToSameCurve = maneuverCouldBelongToSameCurve; + } + if (curveToAdd != null) { + result.add(curveToAdd); + } + return result; + } + + /** + * Converts the provided maneuver into {@link CompleteManeuverCurve}. The boundaries of provided maneuver are reused + * for the resulting complete maneuver curve. + * + * @see CompleteManeuverCurve + * @see Maneuver + */ + private CompleteManeuverCurve convertManeuverToCompleteManeuverCurve(Maneuver maneuver) { + ManeuverMainCurveDetailsWithBearingSteps mainCurveBoundaries = new ManeuverMainCurveDetailsWithBearingSteps( + maneuver.getMainCurveBoundaries().getTimePointBefore(), + maneuver.getMainCurveBoundaries().getTimePointAfter(), maneuver.getTimePoint(), + maneuver.getMainCurveBoundaries().getSpeedWithBearingBefore(), + maneuver.getMainCurveBoundaries().getSpeedWithBearingAfter(), + maneuver.getMainCurveBoundaries().getDirectionChangeInDegrees(), + maneuver.getMaxTurningRateInDegreesPerSecond(), maneuver.getMainCurveBoundaries().getLowestSpeed(), + maneuverDetector.getSpeedWithBearingSteps(maneuver.getMainCurveBoundaries().getTimePointBefore(), + maneuver.getMainCurveBoundaries().getTimePointAfter())); + return new CompleteManeuverCurveImpl(mainCurveBoundaries, + maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries(), maneuver.getMarkPassing()); + } + + /** + * Extends the end of provided maneuver curve with the end of provided maneuver. For this, the curve boundaries with + * unstable course and speed are merged by appending, whereas the maneuver main curve gets recalculated completely + * from scratch. The additional attributes such as, direction change and lowest speed get adjusted accordingly. + */ + private CompleteManeuverCurve extendCompleteManeuverCurveWithManeuver(CompleteManeuverCurve maneuverCurve, + Maneuver maneuver) { + ManeuverMainCurveDetailsWithBearingSteps mainCurveDetails = maneuverDetector.computeManeuverMainCurveDetails( + maneuverCurve.getMainCurveBoundaries().getTimePointBefore(), + maneuver.getMainCurveBoundaries().getTimePointAfter(), maneuver.getToSide()); + if (mainCurveDetails == null) { + return maneuverCurve; + } + ManeuverCurveBoundaries maneuverCurveWithStableSpeedAndCourseBoundaries = new ManeuverCurveBoundariesImpl( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), + maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingBefore(), + maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingAfter(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getDirectionChangeInDegrees() + + maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getDirectionChangeInDegrees(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getLowestSpeed() + .compareTo(maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getLowestSpeed()) > 0 + ? maneuver.getManeuverCurveWithStableSpeedAndCourseBoundaries().getLowestSpeed() + : maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getLowestSpeed()); + return new CompleteManeuverCurveImpl(mainCurveDetails, maneuverCurveWithStableSpeedAndCourseBoundaries, + maneuverCurve.getMarkPassing() == null ? maneuver.getMarkPassing() : maneuverCurve.getMarkPassing()); + } + + @Override + public List getCompleteManeuverCurvesWithEstimationData( + Iterable maneuverCurves) { + List result = new ArrayList<>(); + + CompleteManeuverCurve previousManeuverCurve = null; + CompleteManeuverCurve currentManeuverCurve = null; + for (CompleteManeuverCurve nextManeuverCurve : maneuverCurves) { + if (currentManeuverCurve != null) { + CompleteManeuverCurveWithEstimationData maneuverCurveWithEstimationData = calculateCompleteManeuverCurveWithEstimationData( + currentManeuverCurve, previousManeuverCurve, nextManeuverCurve); + result.add(maneuverCurveWithEstimationData); + } + previousManeuverCurve = currentManeuverCurve; + currentManeuverCurve = nextManeuverCurve; + } + if (currentManeuverCurve != null) { + CompleteManeuverCurveWithEstimationData maneuverCurveWithEstimationData = calculateCompleteManeuverCurveWithEstimationData( + currentManeuverCurve, previousManeuverCurve, null); + result.add(maneuverCurveWithEstimationData); + } + return result; + } + + /** + * Calculates a {@link CompleteManeuverCurveWithEstimationData}-instance for the provided {@code maneuverCurve}. The + * computation of additional information required by {@link CompleteManeuverCurveWithEstimationData} is regarded as + * computationally-intensive. + */ + private CompleteManeuverCurveWithEstimationData calculateCompleteManeuverCurveWithEstimationData( + CompleteManeuverCurve maneuverCurve, CompleteManeuverCurve previousManeuverCurve, + CompleteManeuverCurve nextManeuverCurve) { + Bearing courseAtMaxTurningRate = null; + SpeedWithBearingStep stepWithLowestSpeed = null; + SpeedWithBearingStep stepWithHighestSpeed = null; + SpeedWithBearingStep stepWithMaxTurningRate = null; + SpeedWithBearingStep previousStep = null; + for (SpeedWithBearingStep step : maneuverCurve.getMainCurveBoundaries().getSpeedWithBearingSteps()) { + if (stepWithLowestSpeed == null + || stepWithLowestSpeed.getSpeedWithBearing().compareTo(step.getSpeedWithBearing()) > 0) { + stepWithLowestSpeed = step; + } + if (stepWithHighestSpeed == null + || stepWithHighestSpeed.getSpeedWithBearing().compareTo(step.getSpeedWithBearing()) < 0) { + stepWithHighestSpeed = step; + } + if (previousStep != null && (stepWithMaxTurningRate == null || stepWithMaxTurningRate + .getTurningRateInDegreesPerSecond() < step.getTurningRateInDegreesPerSecond())) { + stepWithMaxTurningRate = step; + courseAtMaxTurningRate = previousStep.getSpeedWithBearing().getBearing() + .add(new DegreeBearingImpl(step.getCourseChangeInDegrees() / 2)); + } + previousStep = step; + } + int gpsFixCountWithinMainCurve = 0; + int gpsFixCountWithinWholeCurve = 0; + int gpsFixesCountFromPreviousManeuver = 0; + int gpsFixesCountToNextManeuver = 0; + try { + maneuverDetector.track.lockForRead(); + boolean considerPreviousManeuver = previousManeuverCurve != null && previousManeuverCurve + .getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter() + .before(maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore()); + boolean considerNextManeuver = nextManeuverCurve != null && nextManeuverCurve + .getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore() + .after(maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter()); + for (GPSFixMoving fix : maneuverDetector.track.getFixes( + considerPreviousManeuver + ? previousManeuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries() + .getTimePointAfter() + : maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), + !considerPreviousManeuver, + considerNextManeuver + ? nextManeuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries() + .getTimePointBefore() + : maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), + !considerNextManeuver)) { + if (fix.getTimePoint().before( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore())) { + ++gpsFixesCountFromPreviousManeuver; + } else if (fix.getTimePoint().after( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter())) { + ++gpsFixesCountToNextManeuver; + } else { + if (!fix.getTimePoint().before(maneuverCurve.getMainCurveBoundaries().getTimePointBefore()) + && !fix.getTimePoint().after(maneuverCurve.getMainCurveBoundaries().getTimePointAfter())) { + ++gpsFixCountWithinMainCurve; + } + ++gpsFixCountWithinWholeCurve; + } + } + } finally { + maneuverDetector.track.unlockAfterRead(); + } + + ManeuverLoss projectedManeuverLoss = maneuverDetector.getManeuverLoss(maneuverCurve.getMainCurveBoundaries()); + Distance distanceSailedIfNotManeuvering = maneuverCurve.getMainCurveBoundaries().getSpeedWithBearingBefore() + .travel(maneuverCurve.getMainCurveBoundaries().getDuration()); + Distance distanceSailedWithinManeuver = maneuverDetector.track.getDistanceTraveled( + maneuverCurve.getMainCurveBoundaries().getTimePointBefore(), + maneuverCurve.getMainCurveBoundaries().getTimePointAfter()); + Duration longestGpsFixIntervalBetweenTwoFixes = maneuverDetector.track.getLongestIntervalBetweenTwoFixes( + maneuverCurve.getMainCurveBoundaries().getTimePointBefore(), + maneuverCurve.getMainCurveBoundaries().getTimePointAfter()); + ManeuverMainCurveWithEstimationData mainCurve = new ManeuverMainCurveWithEstimationDataImpl( + maneuverCurve.getMainCurveBoundaries().getTimePointBefore(), + maneuverCurve.getMainCurveBoundaries().getTimePointAfter(), + maneuverCurve.getMainCurveBoundaries().getSpeedWithBearingBefore(), + maneuverCurve.getMainCurveBoundaries().getSpeedWithBearingAfter(), + maneuverCurve.getMainCurveBoundaries().getDirectionChangeInDegrees(), + stepWithLowestSpeed.getSpeedWithBearing(), stepWithLowestSpeed.getTimePoint(), + stepWithHighestSpeed.getSpeedWithBearing(), stepWithHighestSpeed.getTimePoint(), + maneuverCurve.getMainCurveBoundaries().getTimePoint(), + maneuverCurve.getMainCurveBoundaries().getMaxTurningRateInDegreesPerSecond(), courseAtMaxTurningRate, + distanceSailedWithinManeuver, projectedManeuverLoss.getDistanceSailed(), distanceSailedIfNotManeuvering, + projectedManeuverLoss.getDistanceSailedIfNotManeuvering(), + Math.abs(maneuverCurve.getMainCurveBoundaries().getDirectionChangeInDegrees()) + / maneuverCurve.getMainCurveBoundaries().getDuration().asSeconds(), + gpsFixCountWithinMainCurve, longestGpsFixIntervalBetweenTwoFixes); + projectedManeuverLoss = maneuverDetector + .getManeuverLoss(maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries()); + distanceSailedIfNotManeuvering = maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries() + .getSpeedWithBearingBefore() + .travel(maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getDuration()); + distanceSailedWithinManeuver = maneuverDetector.track.getDistanceTraveled( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter()); + longestGpsFixIntervalBetweenTwoFixes = maneuverDetector.track.getLongestIntervalBetweenTwoFixes( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter()); + TrackTimeInfo trackTimeInfo = previousManeuverCurve == null || nextManeuverCurve == null + ? maneuverDetector.getTrackTimeInfo() : null; + Pair durationAndAvgSpeedWithBearingBefore = calculateDurationAndAvgSpeedWithBearingBetweenTimePoints( + previousManeuverCurve == null ? trackTimeInfo.getTrackStartTimePoint() + : previousManeuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries() + .getTimePointAfter(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore()); + Pair durationAndAvgSpeedWithBearingAfter = calculateDurationAndAvgSpeedWithBearingBetweenTimePoints( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), + nextManeuverCurve == null ? trackTimeInfo.getTrackEndTimePoint() + : nextManeuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore()); + Duration intervalBetweenLastFixOfCurveAndNextFix = Duration.NULL; + GPSFixMoving lastManeuverFix = maneuverDetector.track.getLastFixAtOrBefore( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter()); + if (lastManeuverFix != null) { + GPSFixMoving firstFixAfterLastManeuverFix = maneuverDetector.track + .getFirstFixAfter(lastManeuverFix.getTimePoint()); + if (firstFixAfterLastManeuverFix != null) { + intervalBetweenLastFixOfCurveAndNextFix = lastManeuverFix.getTimePoint() + .until(firstFixAfterLastManeuverFix.getTimePoint()); + } + } + Duration intervalBetweenFirstFixOfCurveAndPreviousFix = Duration.NULL; + GPSFixMoving firstManeuverFix = maneuverDetector.track.getFirstFixAtOrAfter( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore()); + if (firstManeuverFix != null) { + GPSFixMoving lastFixBeforeFirstManeuverFix = maneuverDetector.track + .getLastFixBefore(firstManeuverFix.getTimePoint()); + if (lastFixBeforeFirstManeuverFix != null) { + intervalBetweenFirstFixOfCurveAndPreviousFix = lastFixBeforeFirstManeuverFix.getTimePoint() + .until(firstManeuverFix.getTimePoint()); + } + } + ManeuverCurveWithUnstableCourseAndSpeedWithEstimationData curveWithUnstableCourseAndSpeed = new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataImpl( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingBefore(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingAfter(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getDirectionChangeInDegrees(), + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getLowestSpeed(), + durationAndAvgSpeedWithBearingBefore.getB(), durationAndAvgSpeedWithBearingBefore.getA(), + gpsFixesCountFromPreviousManeuver, durationAndAvgSpeedWithBearingAfter.getB(), + durationAndAvgSpeedWithBearingAfter.getA(), gpsFixesCountToNextManeuver, distanceSailedWithinManeuver, + projectedManeuverLoss.getDistanceSailed(), distanceSailedIfNotManeuvering, + projectedManeuverLoss.getDistanceSailedIfNotManeuvering(), gpsFixCountWithinWholeCurve, + longestGpsFixIntervalBetweenTwoFixes, intervalBetweenLastFixOfCurveAndNextFix, + intervalBetweenFirstFixOfCurveAndPreviousFix); + TimePoint maneuverTimePoint = maneuverCurve.getMainCurveBoundaries().getTimePoint(); + Position maneuverPosition = maneuverDetector.track.getEstimatedPosition(maneuverTimePoint, + /* extrapolate */false); + Wind wind = maneuverDetector.trackedRace.getWind(maneuverPosition, maneuverTimePoint); + int numberOfJibes = maneuverDetector.getNumberOfJibes(mainCurve, wind); + int numberOfTacks = maneuverDetector.getNumberOfTacks(mainCurve, wind); + boolean maneuverStartsByRunningAwayFromWind = (mainCurve.getSpeedWithBearingBefore().getBearing().getDegrees() + - 180) * mainCurve.getDirectionChangeInDegrees() < 0; + Bearing relativeBearingToNextMarkPassingBeforeManeuver = getRelativeBearingToNextMark( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointBefore(), maneuverCurve + .getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingBefore().getBearing()); + Bearing relativeBearingToNextMarkPassingAfterManeuver = getRelativeBearingToNextMark( + maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), maneuverCurve + .getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingAfter().getBearing()); + return new CompleteManeuverCurveWithEstimationDataImpl(maneuverPosition, mainCurve, + curveWithUnstableCourseAndSpeed, wind, numberOfTacks, numberOfJibes, + maneuverStartsByRunningAwayFromWind, relativeBearingToNextMarkPassingBeforeManeuver, + relativeBearingToNextMarkPassingAfterManeuver, maneuverCurve.isMarkPassing()); + } + + /** + * Calculates the duration and avg speed with avg course based on the competitor's track within the provided time + * range. + */ + private Pair calculateDurationAndAvgSpeedWithBearingBetweenTimePoints(TimePoint from, + TimePoint to) { + Duration duration = from.until(to); + Position fromPosition = maneuverDetector.track.getEstimatedPosition(from, false); + Position toPosition = maneuverDetector.track.getEstimatedPosition(to, false); + Distance distance = fromPosition.getDistance(toPosition); + Bearing bearing = fromPosition.getBearingGreatCircle(toPosition); + Speed speed = distance.inTime(Math.abs(duration.asMillis())); + SpeedWithBearing avgSpeedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), bearing); + return new Pair<>(duration, avgSpeedWithBearing); + } + + /** + * Gets the relative bearing of the next mark from the boat's position and course at {@code timePoint}. The relative + * bearing is calculated by absolute bearing of next mark from the boat's position minus the boat's course. + */ + private Bearing getRelativeBearingToNextMark(TimePoint timePoint, Bearing boatCourse) { + NonCachingMarkPositionAtTimePointCache markPositionAtTimePointCache = new NonCachingMarkPositionAtTimePointCache( + maneuverDetector.trackedRace, timePoint); + Bearing result = null; + TrackedLegOfCompetitor legAfter = maneuverDetector.trackedRace.getTrackedLeg(maneuverDetector.competitor, + timePoint); + if (legAfter != null && legAfter.getLeg().getTo() != null) { + Waypoint nextWaypoint = legAfter.getLeg().getTo(); + for (Mark mark : nextWaypoint.getMarks()) { + Position nextMarkPosition = markPositionAtTimePointCache.getEstimatedPosition(mark); + Position maneuverEndPosition = maneuverDetector.track.getEstimatedPosition(timePoint, false); + Bearing absoluteBearing = maneuverEndPosition.getBearingGreatCircle(nextMarkPosition); + Bearing resultCandidate = absoluteBearing.getDifferenceTo(boatCourse); + if (result == null) { + result = resultCandidate; + } else if (Math.signum(result.getDegrees()) != Math.signum(resultCandidate.getDegrees())) { + result = new DegreeBearingImpl(0); + break; + } else if (Math.abs(result.getDegrees()) > Math.abs(resultCandidate.getDegrees())) { + result = resultCandidate; + } + + } + } + return result; + } + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Maneuver.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Maneuver.java index 7011612e984..0bc4bdb5b2c 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Maneuver.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Maneuver.java @@ -174,5 +174,5 @@ public interface Maneuver extends GPSFix { */ @Statistic(messageKey = "AvgTurningRateInDegreesPerSecond", resultDecimals = 4) double getAvgTurningRateInDegreesPerSecond(); - + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/ManeuverWithCoarseGrainedBoundariesImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/ManeuverWithCoarseGrainedBoundariesImpl.java new file mode 100644 index 00000000000..328e073e972 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/ManeuverWithCoarseGrainedBoundariesImpl.java @@ -0,0 +1,37 @@ +package com.sap.sailing.domain.tracking.impl; + +import com.sap.sailing.domain.common.ManeuverType; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.Tack; +import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries; +import com.sap.sse.common.TimePoint; + +/** + * Maneuver implementation which were detected on tracks with extremely low GPS-sampling rate. The implementation + * suggests to ignore the following attributes: + *

    + *
  • Maneuver loss
  • + *
  • Max. and Avg. Turning rate
  • + *
  • Time point before and after of all maneuver boundaries
  • + *
  • Lowest speed within all maneuver boundaries
  • + *
+ * However, to provide capability with existing code, the attributes are filled with values. + * + * @author Vladislav Chumak (D069712) + * + */ +public class ManeuverWithCoarseGrainedBoundariesImpl extends ManeuverImpl { + + private static final long serialVersionUID = -381990329349665889L; + + public ManeuverWithCoarseGrainedBoundariesImpl(ManeuverType type, Tack newTack, Position position, + TimePoint timePoint, ManeuverCurveBoundaries maneuverBoundaries) { + super(type, newTack, position, null, timePoint, maneuverBoundaries, maneuverBoundaries, Math.abs(maneuverBoundaries.getDirectionChangeInDegrees()), null); + } + + @Override + public ManeuverCurveBoundaries getManeuverBoundaries() { + return getMainCurveBoundaries(); + } + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index d80b0c45e6a..2760bf877ca 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -113,6 +113,7 @@ import com.sap.sailing.domain.maneuverdetection.IncrementalManeuverDetector; import com.sap.sailing.domain.maneuverdetection.ManeuverDetector; import com.sap.sailing.domain.maneuverdetection.ShortTimeAfterLastHitCache; import com.sap.sailing.domain.maneuverdetection.impl.IncrementalManeuverDetectorImpl; +import com.sap.sailing.domain.maneuverdetection.impl.LowGPSSamplingRateManeuverDetectorImpl; import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator; import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; import com.sap.sailing.domain.polars.PolarDataService; @@ -701,10 +702,21 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl @Override public List computeCacheUpdate(Competitor competitor, EmptyUpdateInterval updateInterval) throws NoWindException { - IncrementalManeuverDetector maneuverDetector = maneuverDetectorPerCompetitorCache - .getValue(competitor); - List maneuvers = computeManeuvers(competitor, maneuverDetector); - return maneuvers; + Duration averageIntervalBetweenRawFixes = getTrack(competitor) + .getAverageIntervalBetweenRawFixes(); + if (averageIntervalBetweenRawFixes != null) { + ManeuverDetector maneuverDetector; + if (averageIntervalBetweenRawFixes.asSeconds() >= 30) { + maneuverDetector = new LowGPSSamplingRateManeuverDetectorImpl(TrackedRaceImpl.this, + competitor); + } else { + maneuverDetector = maneuverDetectorPerCompetitorCache.getValue(competitor); + } + List maneuvers = computeManeuvers(competitor, maneuverDetector); + return maneuvers; + } else { + return Collections.emptyList(); + } } }, /* nameForLocks */"Maneuver cache for race " + getRace().getName()); } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java index 9a0def79beb..b155633069e 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java @@ -6,8 +6,9 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.maneuverdetection.CompleteManeuverCurveWithEstimationData; -import com.sap.sailing.domain.maneuverdetection.ManeuverDetector; +import com.sap.sailing.domain.maneuverdetection.ManeuverDetectorWithEstimationDataSupport; import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorImpl; +import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorWithEstimationDataSupportDecoratorImpl; import com.sap.sailing.domain.maneuverdetection.impl.TrackTimeInfo; import com.sap.sailing.domain.tracking.CompleteManeuverCurve; import com.sap.sailing.domain.tracking.GPSFixTrack; @@ -82,7 +83,8 @@ public class CompleteManeuverCurvesWithEstimationDataJsonSerializer extends Abst private Iterable getCompleteManeuverCurvesWithEstimationData( TrackedRace trackedRace, Competitor competitor) { Iterable maneuvers = trackedRace.getManeuvers(competitor, false); - ManeuverDetector maneuverDetector = new ManeuverDetectorImpl(trackedRace, competitor); + ManeuverDetectorWithEstimationDataSupport maneuverDetector = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl( + new ManeuverDetectorImpl(trackedRace, competitor)); Iterable maneuversWithEstimationData = null; try { Iterable maneuverCurves = maneuverDetector.getCompleteManeuverCurves(maneuvers); From b34d97e89e20da3f5e494af59b9ec3214c0277bc Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Thu, 5 Jul 2018 06:57:30 +0200 Subject: [PATCH 012/292] Removed outdated javadoc --- ...owGPSSamplingRateManeuverDetectorImpl.java | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/LowGPSSamplingRateManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/LowGPSSamplingRateManeuverDetectorImpl.java index 7396d284474..26de57c6b24 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/LowGPSSamplingRateManeuverDetectorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/LowGPSSamplingRateManeuverDetectorImpl.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.CourseChange; import com.sap.sailing.domain.common.ManeuverType; @@ -37,41 +36,6 @@ public class LowGPSSamplingRateManeuverDetectorImpl extends AbstractManeuverDete super(trackedRace, competitor); } - /** - * Tries to detect maneuvers on the competitor's track based on a number of approximating fixes. The - * fixes contain bearing information, but this is not the bearing leading to the next approximation fix but the - * bearing the boat had at the time of the approximating fix which is taken from the original track. - *

- * - * The time period assumed for a maneuver duration is taken from the - * {@link BoatClass#getApproximateManeuverDurationInMilliseconds() boat class}. If no maneuver is detected, an empty - * list is returned. Maneuvers can only be expected to be detected if at least three fixes are provided in - * approximatedFixesToAnalyze. For the inner approximating fixes (all except the first and the last - * approximating fix), their course changes according to the approximated path (and not the underlying actual - * tracked fixes) are computed. Subsequent course changes to the same direction are then grouped. Those in closer - * timely distance than {@link #getApproximateManeuverDurationInMilliseconds()} (including single course changes - * that have no surrounding other course changes to group) are grouped into one {@link Maneuver}. - * - * @param ignoreMarkPassings - * When true, no {@link ManeuverType#MARK_PASSING} maneuvers will be identified, and the - * fact that a mark passing would split up what else may be a penalty circle is ignored. This is helpful - * for recursive calls, e.g., after identifying a tack and a jibe around a mark passing and trying to - * identify for the time before and after the mark passing which maneuvers exist on which side of the - * passing. - * @param earliestManeuverStart - * maneuver start will not be before this time point; if a maneuver is found whose time point is at or - * after this time point, no matter how close it is, its start regarding speed and course into the - * maneuver and the leg before the maneuver is not taken from an earlier time point, even if half the - * maneuver duration before the maneuver time point were before this time point. - * @param latestManeuverEnd - * maneuver end will not be after this time point; if a maneuver is found whose time point is at or - * before this time point, no matter how close it is, its end regarding speed and course out of the - * maneuver and the leg after the maneuver is not taken from a later time point, even if half the - * maneuver duration after the maneuver time point were after this time point. - * - * @return an empty list if no maneuver is detected for competitor between from and - * to, or else the list of maneuvers detected. - */ @Override public List detectManeuvers() { List result = new ArrayList<>(); From 2774989686a87cbea4c95fa4228932718084c046 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Thu, 5 Jul 2018 10:52:05 +0200 Subject: [PATCH 013/292] Added polar feature to exported estimation data + corrected polars bugs --- ...eWithEstimationDataRetrievalProcessor.java | 3 +- ...mpleteManeuverCurveWithEstimationData.java | 7 ++ ...teManeuverCurveWithEstimationDataImpl.java | 26 ++++++- ...ithEstimationDataSupportDecoratorImpl.java | 76 ++++++++++++++++++- .../domain/polars/PolarDataService.java | 8 ++ .../jaxrs/api/test/PolarDataResourceTest.java | 2 +- .../polars/impl/PolarDataServiceImpl.java | 23 ++++-- .../mining/AngleAndSpeedRegression.java | 3 +- ...nDataSerializationDeserializationTest.java | 22 +++++- ...rveWithEstimationDataJsonDeserializer.java | 16 +++- ...CurveWithEstimationDataJsonSerializer.java | 9 +++ ...urvesWithEstimationDataJsonSerializer.java | 17 ++++- .../gateway/jaxrs/api/RegattasResource.java | 2 +- 13 files changed, 193 insertions(+), 21 deletions(-) diff --git a/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/CompleteManeuverCurveWithEstimationDataRetrievalProcessor.java b/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/CompleteManeuverCurveWithEstimationDataRetrievalProcessor.java index f05bdf58be0..eff334d61f5 100644 --- a/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/CompleteManeuverCurveWithEstimationDataRetrievalProcessor.java +++ b/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/CompleteManeuverCurveWithEstimationDataRetrievalProcessor.java @@ -47,7 +47,8 @@ public class CompleteManeuverCurveWithEstimationDataRetrievalProcessor extends TrackedRace trackedRace = element.getTrackedRaceContext().getTrackedRace(); Competitor competitor = element.getCompetitor(); ManeuverDetectorWithEstimationDataSupport maneuverDetector = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl( - new ManeuverDetectorImpl(trackedRace, competitor)); + new ManeuverDetectorImpl(trackedRace, competitor), + element.getTrackedRaceContext().getLeaderboardContext().getPolarDataService()); Iterable maneuvers = trackedRace.getManeuvers(competitor, false); Iterable maneuverCurves = maneuverDetector.getCompleteManeuverCurves(maneuvers); Iterable maneuversWithEstimationData = maneuverDetector diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/CompleteManeuverCurveWithEstimationData.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/CompleteManeuverCurveWithEstimationData.java index bd41ca3d81a..9738718cca4 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/CompleteManeuverCurveWithEstimationData.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/CompleteManeuverCurveWithEstimationData.java @@ -5,6 +5,7 @@ import com.sap.sailing.domain.common.Positioned; import com.sap.sailing.domain.common.Wind; import com.sap.sailing.domain.tracking.CompleteManeuverCurve; import com.sap.sse.common.Bearing; +import com.sap.sse.common.Distance; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Timed; import com.sap.sse.datamining.annotations.Connector; @@ -96,6 +97,12 @@ public interface CompleteManeuverCurveWithEstimationData extends Timed, Position * boundaries, the boundaries of the curve with unstable course and speed are used. */ Bearing getRelativeBearingToNextMarkAfterManeuver(); + + Distance getDistanceToClosestMark(); + + Double getDeviationOfManeuverAngleFromTargetTackAngleInDegrees(); + + Double getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees(); /** * Gets whether a mark was crossed within the maneuver curve. diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/CompleteManeuverCurveWithEstimationDataImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/CompleteManeuverCurveWithEstimationDataImpl.java index 38ac9040bbc..89c43715903 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/CompleteManeuverCurveWithEstimationDataImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/CompleteManeuverCurveWithEstimationDataImpl.java @@ -6,6 +6,7 @@ import com.sap.sailing.domain.maneuverdetection.CompleteManeuverCurveWithEstimat import com.sap.sailing.domain.maneuverdetection.ManeuverCurveWithUnstableCourseAndSpeedWithEstimationData; import com.sap.sailing.domain.maneuverdetection.ManeuverMainCurveWithEstimationData; import com.sap.sse.common.Bearing; +import com.sap.sse.common.Distance; /** * @@ -24,13 +25,16 @@ public class CompleteManeuverCurveWithEstimationDataImpl implements CompleteMane private final Bearing relativeBearingToNextMarkBeforeManeuver; private final Bearing relativeBearingToNextMarkAfterManeuver; private final boolean markPassing; - private Position position; + private final Position position; + private final Distance distanceToClosestMark; + private final Double deviationOfManeuverAngleFromTargetTackAngleInDegrees; + private final Double deviationOfManeuverAngleFromTargetJibeAngleInDegrees; public CompleteManeuverCurveWithEstimationDataImpl(Position position, ManeuverMainCurveWithEstimationData mainCurve, ManeuverCurveWithUnstableCourseAndSpeedWithEstimationData curveWithUnstableCourseAndSpeed, Wind wind, int tackingCount, int jibingCount, boolean maneuverStartsByRunningAwayFromWind, Bearing relativeBearingToNextMarkBeforeManeuver, Bearing relativeBearingToNextMarkAfterManeuver, - boolean markPassing) { + boolean markPassing, Distance distanceToClosestMark, Double deviationOfManeuverAngleFromTargetTackAngleInDegrees, Double deviationOfManeuverAngleFromTargetJibeAngleInDegrees) { this.position = position; this.mainCurve = mainCurve; this.curveWithUnstableCourseAndSpeed = curveWithUnstableCourseAndSpeed; @@ -41,6 +45,9 @@ public class CompleteManeuverCurveWithEstimationDataImpl implements CompleteMane this.relativeBearingToNextMarkBeforeManeuver = relativeBearingToNextMarkBeforeManeuver; this.relativeBearingToNextMarkAfterManeuver = relativeBearingToNextMarkAfterManeuver; this.markPassing = markPassing; + this.distanceToClosestMark = distanceToClosestMark; + this.deviationOfManeuverAngleFromTargetTackAngleInDegrees = deviationOfManeuverAngleFromTargetTackAngleInDegrees; + this.deviationOfManeuverAngleFromTargetJibeAngleInDegrees = deviationOfManeuverAngleFromTargetJibeAngleInDegrees; } @Override @@ -92,5 +99,20 @@ public class CompleteManeuverCurveWithEstimationDataImpl implements CompleteMane public Position getPosition() { return position; } + + @Override + public Distance getDistanceToClosestMark() { + return distanceToClosestMark; + } + + @Override + public Double getDeviationOfManeuverAngleFromTargetTackAngleInDegrees() { + return deviationOfManeuverAngleFromTargetTackAngleInDegrees; + } + + @Override + public Double getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees() { + return deviationOfManeuverAngleFromTargetJibeAngleInDegrees; + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java index 689df4a4736..1281b2f14f3 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java @@ -4,7 +4,9 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.ManeuverType; import com.sap.sailing.domain.common.Position; @@ -17,6 +19,7 @@ import com.sap.sailing.domain.maneuverdetection.ManeuverCurveWithUnstableCourseA import com.sap.sailing.domain.maneuverdetection.ManeuverDetector; import com.sap.sailing.domain.maneuverdetection.ManeuverDetectorWithEstimationDataSupport; import com.sap.sailing.domain.maneuverdetection.ManeuverMainCurveWithEstimationData; +import com.sap.sailing.domain.polars.PolarDataService; import com.sap.sailing.domain.tracking.CompleteManeuverCurve; import com.sap.sailing.domain.tracking.Maneuver; import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries; @@ -44,10 +47,13 @@ import com.sap.sse.common.impl.DegreeBearingImpl; public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl implements ManeuverDetectorWithEstimationDataSupport { - private ManeuverDetectorImpl maneuverDetector; + private final ManeuverDetectorImpl maneuverDetector; + private final PolarDataService polarDataService; - public ManeuverDetectorWithEstimationDataSupportDecoratorImpl(ManeuverDetectorImpl maneuverDetector) { + public ManeuverDetectorWithEstimationDataSupportDecoratorImpl(ManeuverDetectorImpl maneuverDetector, + PolarDataService polarDataService) { this.maneuverDetector = maneuverDetector; + this.polarDataService = polarDataService; } @Override @@ -348,10 +354,72 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl Bearing relativeBearingToNextMarkPassingAfterManeuver = getRelativeBearingToNextMark( maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries().getTimePointAfter(), maneuverCurve .getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingAfter().getBearing()); + BoatClass boatClass = maneuverDetector.trackedRace.getRace().getBoatOfCompetitor(maneuverDetector.competitor) + .getBoatClass(); + Double deviationFromTackAngle = null; + Double deviationFromJibeAngle = null; + Speed boatSpeed = curveWithUnstableCourseAndSpeed.getSpeedWithBearingBefore() + .compareTo(curveWithUnstableCourseAndSpeed.getSpeedWithBearingAfter()) < 0 + ? curveWithUnstableCourseAndSpeed.getSpeedWithBearingBefore() + : curveWithUnstableCourseAndSpeed.getSpeedWithBearingAfter(); + if (polarDataService.getAllBoatClassesWithPolarSheetsAvailable().contains(boatClass)) { + SpeedWithBearingWithConfidence closestTackTwa = polarDataService.getClosestTwaTws(ManeuverType.TACK, + boatSpeed, curveWithUnstableCourseAndSpeed.getDirectionChangeInDegrees(), boatClass); + SpeedWithBearingWithConfidence closestJibeTwa = polarDataService.getClosestTwaTws(ManeuverType.JIBE, + boatSpeed, curveWithUnstableCourseAndSpeed.getDirectionChangeInDegrees(), boatClass); + if (closestTackTwa != null) { + deviationFromTackAngle = polarDataService.getManeuverAngleInDegreesFromTwa( + closestTackTwa.getObject().getBearing().getDegrees(), ManeuverType.TACK); + } + if (closestJibeTwa != null) { + deviationFromJibeAngle = polarDataService.getManeuverAngleInDegreesFromTwa( + closestJibeTwa.getObject().getBearing().getDegrees(), ManeuverType.JIBE); + } + } + Distance closestDistanceToMark = getClosestDistanceToMark(mainCurve.getTimePointOfMaxTurningRate()); + return new CompleteManeuverCurveWithEstimationDataImpl(maneuverPosition, mainCurve, curveWithUnstableCourseAndSpeed, wind, numberOfTacks, numberOfJibes, maneuverStartsByRunningAwayFromWind, relativeBearingToNextMarkPassingBeforeManeuver, - relativeBearingToNextMarkPassingAfterManeuver, maneuverCurve.isMarkPassing()); + relativeBearingToNextMarkPassingAfterManeuver, maneuverCurve.isMarkPassing(), closestDistanceToMark, + deviationFromTackAngle, deviationFromJibeAngle); + } + + private Distance getClosestDistanceToMark(TimePoint timePoint) { + NonCachingMarkPositionAtTimePointCache markPositionAtTimePointCache = new NonCachingMarkPositionAtTimePointCache( + maneuverDetector.trackedRace, timePoint); + Distance result = null; + TrackedLegOfCompetitor legAfter = maneuverDetector.trackedRace.getTrackedLeg(maneuverDetector.competitor, + timePoint); + if (legAfter != null) { + Position maneuverPosition = maneuverDetector.track.getEstimatedPosition(timePoint, false); + if (legAfter.getLeg().getTo() != null) { + result = getClosestDistanceToMarkInternal(markPositionAtTimePointCache, legAfter.getLeg().getTo(), + maneuverPosition); + } + if (legAfter.getLeg().getFrom() != null) { + Distance distance = getClosestDistanceToMarkInternal(markPositionAtTimePointCache, + legAfter.getLeg().getFrom(), maneuverPosition); + if (result == null || distance != null && distance.compareTo(result) < 0) { + result = distance; + } + } + } + return result; + } + + private Distance getClosestDistanceToMarkInternal( + NonCachingMarkPositionAtTimePointCache markPositionAtTimePointCache, Waypoint waypoint, + Position maneuverPosition) { + Distance result = null; + for (Mark mark : waypoint.getMarks()) { + Position markPosition = markPositionAtTimePointCache.getEstimatedPosition(mark); + Distance distance = markPosition.getDistance(maneuverPosition); + if (result == null || distance.compareTo(result) < 0) { + result = distance; + } + } + return result; } /** @@ -381,10 +449,10 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl TrackedLegOfCompetitor legAfter = maneuverDetector.trackedRace.getTrackedLeg(maneuverDetector.competitor, timePoint); if (legAfter != null && legAfter.getLeg().getTo() != null) { + Position maneuverEndPosition = maneuverDetector.track.getEstimatedPosition(timePoint, false); Waypoint nextWaypoint = legAfter.getLeg().getTo(); for (Mark mark : nextWaypoint.getMarks()) { Position nextMarkPosition = markPositionAtTimePointCache.getEstimatedPosition(mark); - Position maneuverEndPosition = maneuverDetector.track.getEstimatedPosition(timePoint, false); Bearing absoluteBearing = maneuverEndPosition.getBearingGreatCircle(nextMarkPosition); Bearing resultCandidate = absoluteBearing.getDifferenceTo(boatCourse); if (result == null) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/polars/PolarDataService.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/polars/PolarDataService.java index 0e1c1ce4e70..231fd9b68ce 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/polars/PolarDataService.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/polars/PolarDataService.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.polars; +import java.util.Map; import java.util.Set; import java.util.function.Consumer; @@ -181,4 +182,11 @@ public interface PolarDataService { * with this service, then lets the {@code consumer} accept that domain factory. */ void runWithDomainFactory(Consumer consumer) throws InterruptedException; + + Map getFixCountPerBoatClass(); + + SpeedWithBearingWithConfidence getClosestTwaTws(ManeuverType type, Speed speedAtManeuverStart, + double courseChangeDeg, BoatClass boatClass); + + double getManeuverAngleInDegreesFromTwa(double twa, ManeuverType maneuverType); } diff --git a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/jaxrs/api/test/PolarDataResourceTest.java b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/jaxrs/api/test/PolarDataResourceTest.java index 0ebfeff56d2..5ec38c3b121 100644 --- a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/jaxrs/api/test/PolarDataResourceTest.java +++ b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/jaxrs/api/test/PolarDataResourceTest.java @@ -61,7 +61,7 @@ public class PolarDataResourceTest { assertThat(polarService.getSpeedRegressionsPerAngle().size(), is(68)); assertThat(polarService.getCubicRegressionsPerCourse().size(), is(4)); - assertThat(polarService.getFixCointPerBoatClass().get(boatClass), is(9330L)); + assertThat(polarService.getFixCountPerBoatClass().get(boatClass), is(9330L)); // presuming that if downwind functions & regression collections' size are correct then any other thing is // imported correctly assertThat(polarService.getAngleRegressionFunction(boatClass, LegType.DOWNWIND), is(angleDownwindFunction)); diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/impl/PolarDataServiceImpl.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/impl/PolarDataServiceImpl.java index 56b91be5abc..a6b97c92076 100755 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/impl/PolarDataServiceImpl.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/impl/PolarDataServiceImpl.java @@ -177,7 +177,8 @@ public class PolarDataServiceImpl implements ReplicablePolarService, ClearStateT return result; } - private SpeedWithBearingWithConfidence getClosestTwaTws(ManeuverType type, Speed speedAtManeuverStart, + @Override + public SpeedWithBearingWithConfidence getClosestTwaTws(ManeuverType type, Speed speedAtManeuverStart, double courseChangeDeg, BoatClass boatClass) { assert type == ManeuverType.TACK || type == ManeuverType.JIBE; double minDiff = Double.MAX_VALUE; @@ -186,8 +187,9 @@ public class PolarDataServiceImpl implements ReplicablePolarService, ClearStateT boatClass, speedAtManeuverStart, type == ManeuverType.TACK ? LegType.UPWIND : LegType.DOWNWIND, type == ManeuverType.TACK ? courseChangeDeg >= 0 ? Tack.PORT : Tack.STARBOARD : courseChangeDeg >= 0 ? Tack.STARBOARD : Tack.PORT)) { - double diff = Math.abs(trueWindSpeedAndAngle.getObject().getBearing().getDegrees() * 2) - - Math.abs(courseChangeDeg); + double targetManeuverAngle = getManeuverAngleInDegreesFromTwa( + trueWindSpeedAndAngle.getObject().getBearing().getDegrees(), type); + double diff = Math.abs(targetManeuverAngle) - Math.abs(courseChangeDeg); if (diff < minDiff) { minDiff = diff; closestTwsTwa = trueWindSpeedAndAngle; @@ -235,11 +237,21 @@ public class PolarDataServiceImpl implements ReplicablePolarService, ClearStateT } SpeedWithBearingWithConfidence speed = polarDataMiner.getAverageSpeedAndCourseOverGround(boatClass, windSpeed, legType); - Bearing bearing = new DegreeBearingImpl(speed.getObject().getBearing().getDegrees() * 2); + Bearing bearing = new DegreeBearingImpl(getManeuverAngleInDegreesFromTwa(speed.getObject().getBearing().getDegrees(), maneuverType)); BearingWithConfidence bearingWithConfidence = new BearingWithConfidenceImpl(bearing, speed.getConfidence(), null); return bearingWithConfidence; } + + public double getManeuverAngleInDegreesFromTwa(double twa, ManeuverType maneuverType) { + if (maneuverType == ManeuverType.TACK) { + return Math.abs(twa) * 2; + } + if (maneuverType == ManeuverType.JIBE) { + return (180 - Math.abs(twa)) * 2; + } + throw new IllegalArgumentException("ManeuverType needs to be tack or jibe."); + } @Override public void insertExistingFixes(TrackedRace trackedRace) { @@ -388,7 +400,8 @@ public class PolarDataServiceImpl implements ReplicablePolarService, ClearStateT return polarDataMiner.getSpeedRegressionPerAngleClusterProcessor().getRegressionsImpl(); } - public Map getFixCointPerBoatClass() { + @Override + public Map getFixCountPerBoatClass() { return polarDataMiner.getSpeedRegressionPerAngleClusterProcessor().getFixCountPerBoatClass(); } diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AngleAndSpeedRegression.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AngleAndSpeedRegression.java index 4aec93bf628..258bc9a4ef9 100644 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AngleAndSpeedRegression.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AngleAndSpeedRegression.java @@ -107,8 +107,7 @@ public class AngleAndSpeedRegression implements Serializable { boolean angleFound; try { angle = angleRegression.getOrCreatePolynomialFunction().value(windSpeedCandidateInKnots); - if ((tack == Tack.PORT && legType == LegType.UPWIND) - || (tack == Tack.STARBOARD && legType == LegType.DOWNWIND)) { + if (tack == Tack.PORT) { angle = -angle; } angleFound = true; diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EstimationDataSerializationDeserializationTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EstimationDataSerializationDeserializationTest.java index 779585de9d7..b4c77ee8dd9 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EstimationDataSerializationDeserializationTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EstimationDataSerializationDeserializationTest.java @@ -132,11 +132,15 @@ public class EstimationDataSerializationDeserializationTest { Bearing relativeBearingToNextMarkBeforeManeuver = new DegreeBearingImpl(202.23); Bearing relativeBearingToNextMarkAfterManeuver = new DegreeBearingImpl(10.01); boolean markPassing = true; + Distance closestDistanceToMark = new MeterDistance(3.0); + Double deviationFromTargetTackAngle = 23.30; + Double deviationFromTargetJibeAngle = 22.30; CompleteManeuverCurveWithEstimationData toSerialize = new CompleteManeuverCurveWithEstimationDataImpl( maneuverPosition, mainCurve, curve, wind, tackingCount, jibingCount, maneuverStartsByRunningAwayFromWind, relativeBearingToNextMarkBeforeManeuver, - relativeBearingToNextMarkAfterManeuver, markPassing); + relativeBearingToNextMarkAfterManeuver, markPassing, closestDistanceToMark, + deviationFromTargetTackAngle, deviationFromTargetJibeAngle); CompleteManeuverCurveWithEstimationDataJsonSerializer serializer = new CompleteManeuverCurveWithEstimationDataJsonSerializer( new ManeuverMainCurveWithEstimationDataJsonSerializer(), new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer(), @@ -148,6 +152,11 @@ public class EstimationDataSerializationDeserializationTest { new WindJsonDeserializer(new PositionJsonDeserializer()), new PositionJsonDeserializer()); CompleteManeuverCurveWithEstimationData deserialized = deserializer.deserialize(json); + assertEquals(deviationFromTargetJibeAngle, + deserialized.getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees()); + assertEquals(deviationFromTargetTackAngle, + deserialized.getDeviationOfManeuverAngleFromTargetTackAngleInDegrees()); + assertEquals(closestDistanceToMark, deserialized.getDistanceToClosestMark()); assertEquals(maneuverPosition, deserialized.getPosition()); assertEquals(tackingCount, deserialized.getTackingCount()); assertEquals(jibingCount, deserialized.getJibingCount()); @@ -303,11 +312,15 @@ public class EstimationDataSerializationDeserializationTest { Bearing relativeBearingToNextMarkAfterManeuver = null; boolean markPassing = false; DegreePosition maneuverPosition = new DegreePosition(50.325246, 11.148556); + Distance closestDistanceToMark = null; + Double deviationFromTargetTackAngle = null; + Double deviationFromTargetJibeAngle = null; CompleteManeuverCurveWithEstimationData toSerialize = new CompleteManeuverCurveWithEstimationDataImpl( maneuverPosition, mainCurve, curve, wind, tackingCount, jibingCount, maneuverStartsByRunningAwayFromWind, relativeBearingToNextMarkBeforeManeuver, - relativeBearingToNextMarkAfterManeuver, markPassing); + relativeBearingToNextMarkAfterManeuver, markPassing, closestDistanceToMark, + deviationFromTargetTackAngle, deviationFromTargetJibeAngle); CompleteManeuverCurveWithEstimationDataJsonSerializer serializer = new CompleteManeuverCurveWithEstimationDataJsonSerializer( new ManeuverMainCurveWithEstimationDataJsonSerializer(), new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer(), @@ -319,6 +332,11 @@ public class EstimationDataSerializationDeserializationTest { new WindJsonDeserializer(new PositionJsonDeserializer()), new PositionJsonDeserializer()); CompleteManeuverCurveWithEstimationData deserialized = deserializer.deserialize(json); + assertEquals(deviationFromTargetJibeAngle, + deserialized.getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees()); + assertEquals(deviationFromTargetTackAngle, + deserialized.getDeviationOfManeuverAngleFromTargetTackAngleInDegrees()); + assertEquals(closestDistanceToMark, deserialized.getDistanceToClosestMark()); assertEquals(maneuverPosition, deserialized.getPosition()); assertEquals(tackingCount, deserialized.getTackingCount()); assertEquals(jibingCount, deserialized.getJibingCount()); diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CompleteManeuverCurveWithEstimationDataJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CompleteManeuverCurveWithEstimationDataJsonDeserializer.java index 6c7dfe3c4b0..0408e37fd08 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CompleteManeuverCurveWithEstimationDataJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CompleteManeuverCurveWithEstimationDataJsonDeserializer.java @@ -4,6 +4,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.impl.MeterDistance; import com.sap.sailing.domain.maneuverdetection.CompleteManeuverCurveWithEstimationData; import com.sap.sailing.domain.maneuverdetection.ManeuverCurveWithUnstableCourseAndSpeedWithEstimationData; import com.sap.sailing.domain.maneuverdetection.ManeuverMainCurveWithEstimationData; @@ -12,6 +13,7 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializationExcepti import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.serialization.impl.CompleteManeuverCurveWithEstimationDataJsonSerializer; import com.sap.sse.common.Bearing; +import com.sap.sse.common.Distance; import com.sap.sse.common.impl.DegreeBearingImpl; /** @@ -59,16 +61,28 @@ public class CompleteManeuverCurveWithEstimationDataJsonDeserializer CompleteManeuverCurveWithEstimationDataJsonSerializer.RELATIVE_BEARING_TO_NEXT_MARK_BEFORE_MANEUVER); Double relativeBearingToNextMarkAfterManeuver = (Double) object.get( CompleteManeuverCurveWithEstimationDataJsonSerializer.RELATIVE_BEARING_TO_NEXT_MARK_AFTER_MANEUVER); + Double closestDistanceToMarkInMeters = (Double) object + .get(CompleteManeuverCurveWithEstimationDataJsonSerializer.CLOSEST_DISTANCE_TO_MARK); + Double deviationFromTargetTackAngle = (Double) object + .get(CompleteManeuverCurveWithEstimationDataJsonSerializer.DEVIATION_FROM_TARGET_TACK_ANGLE); + Double deviationFromTargetJibeAngle = (Double) object + .get(CompleteManeuverCurveWithEstimationDataJsonSerializer.DEVIATION_FROM_TARGET_JIBE_ANGLE); return new CompleteManeuverCurveWithEstimationDataImpl(position, mainCurve, curveWithUnstableCourseAndSpeed, wind, tackingCount, jibingCount, maneuverStartsByRunningAwayFromWind, convertBearing(relativeBearingToNextMarkBeforeManeuver), - convertBearing(relativeBearingToNextMarkAfterManeuver), markPassing); + convertBearing(relativeBearingToNextMarkAfterManeuver), markPassing, + convertDistance(closestDistanceToMarkInMeters), deviationFromTargetTackAngle, + deviationFromTargetJibeAngle); } private Bearing convertBearing(Double degrees) { return degrees == null ? null : new DegreeBearingImpl(degrees); } + private Distance convertDistance(Double meters) { + return meters == null ? null : new MeterDistance(meters); + } + public static Integer getInteger(Object object) { if (object == null) { return null; diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurveWithEstimationDataJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurveWithEstimationDataJsonSerializer.java index c904b298a51..5c3ae7b119d 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurveWithEstimationDataJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurveWithEstimationDataJsonSerializer.java @@ -23,6 +23,9 @@ public class CompleteManeuverCurveWithEstimationDataJsonSerializer public static final String MANEUVER_STARTS_BY_RUNNING_AWAY_FROM_WIND = "maneuverStartsByRunningAwayFromWind"; public static final String RELATIVE_BEARING_TO_NEXT_MARK_BEFORE_MANEUVER = "relativeBearingToNextMarkBeforeManeuver"; public static final String RELATIVE_BEARING_TO_NEXT_MARK_AFTER_MANEUVER = "relativeBearingToNextMarkAfterManeuver"; + public static final String CLOSEST_DISTANCE_TO_MARK = "closestDistanceToMarkInMeters"; + public static final String DEVIATION_FROM_TARGET_TACK_ANGLE = "deviationFromTargetTackAngleInDegrees"; + public static final String DEVIATION_FROM_TARGET_JIBE_ANGLE = "deviationFromTargetJibeAngleInDegrees"; private final ManeuverCurveBoundariesJsonSerializer mainCurveSerializer; private final ManeuverCurveBoundariesJsonSerializer curveWithUnstableCourseAndSpeedSerializer; @@ -59,6 +62,12 @@ public class CompleteManeuverCurveWithEstimationDataJsonSerializer result.put(RELATIVE_BEARING_TO_NEXT_MARK_AFTER_MANEUVER, maneuverWithEstimationData.getRelativeBearingToNextMarkAfterManeuver() == null ? null : maneuverWithEstimationData.getRelativeBearingToNextMarkAfterManeuver().getDegrees()); + result.put(CLOSEST_DISTANCE_TO_MARK, maneuverWithEstimationData.getDistanceToClosestMark() == null ? null + : maneuverWithEstimationData.getDistanceToClosestMark().getMeters()); + result.put(DEVIATION_FROM_TARGET_TACK_ANGLE, + maneuverWithEstimationData.getDeviationOfManeuverAngleFromTargetTackAngleInDegrees()); + result.put(DEVIATION_FROM_TARGET_JIBE_ANGLE, + maneuverWithEstimationData.getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees()); return result; } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java index b155633069e..6bb7a8fb7d6 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java @@ -3,6 +3,7 @@ package com.sap.sailing.server.gateway.serialization.impl; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.maneuverdetection.CompleteManeuverCurveWithEstimationData; @@ -10,6 +11,7 @@ import com.sap.sailing.domain.maneuverdetection.ManeuverDetectorWithEstimationDa import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorImpl; import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorWithEstimationDataSupportDecoratorImpl; import com.sap.sailing.domain.maneuverdetection.impl.TrackTimeInfo; +import com.sap.sailing.domain.polars.PolarDataService; import com.sap.sailing.domain.tracking.CompleteManeuverCurve; import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.Maneuver; @@ -29,12 +31,16 @@ public class CompleteManeuverCurvesWithEstimationDataJsonSerializer extends Abst public static final String DISTANCE_TRAVELLED_IN_METERS = "distanceTravelledInMeters"; public static final String START_TIME_POINT = "startUnixTime"; public static final String END_TIME_POINT = "endUnixTime"; + public static final String FIXES_COUNT_FOR_POLARS = "fixesCountForPolars"; private final BoatClassJsonSerializer boatClassJsonSerializer; private final CompleteManeuverCurveWithEstimationDataJsonSerializer maneuverWithEstimationDataJsonSerializer; + private final PolarDataService polarDataService; - public CompleteManeuverCurvesWithEstimationDataJsonSerializer(BoatClassJsonSerializer boatClassJsonSerializer, + public CompleteManeuverCurvesWithEstimationDataJsonSerializer(PolarDataService polarDataService, + BoatClassJsonSerializer boatClassJsonSerializer, CompleteManeuverCurveWithEstimationDataJsonSerializer maneuverWithEstimationDataJsonSerializer) { + this.polarDataService = polarDataService; this.boatClassJsonSerializer = boatClassJsonSerializer; this.maneuverWithEstimationDataJsonSerializer = maneuverWithEstimationDataJsonSerializer; } @@ -59,6 +65,7 @@ public class CompleteManeuverCurvesWithEstimationDataJsonSerializer extends Abst completeManeuverCurvesWithEstimationData .add(maneuverWithEstimationDataJsonSerializer.serialize(maneuver)); } + forCompetitorJson.put(FIXES_COUNT_FOR_POLARS, getFixesCountForPolars(trackedRace, competitor)); forCompetitorJson.put(MANEUVER_CURVES, completeManeuverCurvesWithEstimationData); Duration averageIntervalBetweenFixes = trackedRace.getTrack(competitor) .getAverageIntervalBetweenFixes(); @@ -84,7 +91,7 @@ public class CompleteManeuverCurvesWithEstimationDataJsonSerializer extends Abst TrackedRace trackedRace, Competitor competitor) { Iterable maneuvers = trackedRace.getManeuvers(competitor, false); ManeuverDetectorWithEstimationDataSupport maneuverDetector = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl( - new ManeuverDetectorImpl(trackedRace, competitor)); + new ManeuverDetectorImpl(trackedRace, competitor), polarDataService); Iterable maneuversWithEstimationData = null; try { Iterable maneuverCurves = maneuverDetector.getCompleteManeuverCurves(maneuvers); @@ -95,4 +102,10 @@ public class CompleteManeuverCurvesWithEstimationDataJsonSerializer extends Abst return maneuversWithEstimationData; } + private long getFixesCountForPolars(TrackedRace trackedRace, Competitor competitor) { + BoatClass boatClass = trackedRace.getRace().getBoatOfCompetitor(competitor).getBoatClass(); + Long fixesCountForBoatPolars = polarDataService.getFixCountPerBoatClass().get(boatClass); + return fixesCountForBoatPolars == null ? 0L : fixesCountForBoatPolars; + } + } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index 15c76506ba3..6ae0be5b38d 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -1043,7 +1043,7 @@ public class RegattasResource extends AbstractSailingServerResource { } else { TrackedRace trackedRace = findTrackedRace(regattaName, raceName); CompleteManeuverCurvesWithEstimationDataJsonSerializer serializer = new CompleteManeuverCurvesWithEstimationDataJsonSerializer( - new DetailedBoatClassJsonSerializer(), + getService().getPolarDataService(), new DetailedBoatClassJsonSerializer(), new CompleteManeuverCurveWithEstimationDataJsonSerializer( new ManeuverMainCurveWithEstimationDataJsonSerializer(), new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer(), From 53abb3e7306e71d396784aa38d3fcba0dfccd9d9 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Thu, 5 Jul 2018 12:37:32 +0200 Subject: [PATCH 014/292] Added export for gps fixes with estimation data --- .../impl/ManeuverDetectorImpl.java | 3 - ...ithEstimationDataSupportDecoratorImpl.java | 4 +- ...nDataSerializationDeserializationTest.java | 21 ++-- ...rveWithEstimationDataJsonDeserializer.java | 10 +- .../impl/ManeuverWindJsonDeserializer.java | 29 +++++ ...CurveWithEstimationDataJsonSerializer.java | 4 +- ...FixesWithEstimationDataJsonSerializer.java | 119 ++++++++++++++++++ .../gateway/jaxrs/api/RegattasResource.java | 37 +++++- 8 files changed, 204 insertions(+), 23 deletions(-) create mode 100644 java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/ManeuverWindJsonDeserializer.java create mode 100644 java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/GpsFixesWithEstimationDataJsonSerializer.java diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java index e7d32f9abb1..0d77148b553 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java @@ -800,9 +800,6 @@ public class ManeuverDetectorImpl extends AbstractManeuverDetectorImpl { } } } - if(result == null) { - System.out.println("a"); - } return result; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java index 1281b2f14f3..00d7e544997 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java @@ -385,7 +385,7 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl deviationFromTackAngle, deviationFromJibeAngle); } - private Distance getClosestDistanceToMark(TimePoint timePoint) { + public Distance getClosestDistanceToMark(TimePoint timePoint) { NonCachingMarkPositionAtTimePointCache markPositionAtTimePointCache = new NonCachingMarkPositionAtTimePointCache( maneuverDetector.trackedRace, timePoint); Distance result = null; @@ -442,7 +442,7 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl * Gets the relative bearing of the next mark from the boat's position and course at {@code timePoint}. The relative * bearing is calculated by absolute bearing of next mark from the boat's position minus the boat's course. */ - private Bearing getRelativeBearingToNextMark(TimePoint timePoint, Bearing boatCourse) { + public Bearing getRelativeBearingToNextMark(TimePoint timePoint, Bearing boatCourse) { NonCachingMarkPositionAtTimePointCache markPositionAtTimePointCache = new NonCachingMarkPositionAtTimePointCache( maneuverDetector.trackedRace, timePoint); Bearing result = null; diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EstimationDataSerializationDeserializationTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EstimationDataSerializationDeserializationTest.java index b4c77ee8dd9..fa01070bb1b 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EstimationDataSerializationDeserializationTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EstimationDataSerializationDeserializationTest.java @@ -28,14 +28,14 @@ import com.sap.sailing.server.gateway.deserialization.impl.CompleteManeuverCurve import com.sap.sailing.server.gateway.deserialization.impl.DetailedBoatClassJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.ManeuverMainCurveWithEstimationDataJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.ManeuverWindJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.PositionJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.WindJsonDeserializer; import com.sap.sailing.server.gateway.serialization.impl.CompleteManeuverCurveWithEstimationDataJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DetailedBoatClassJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ManeuverMainCurveWithEstimationDataJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.ManeuverWindJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.PositionJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.WindJsonSerializer; import com.sap.sse.common.Bearing; import com.sap.sse.common.Distance; import com.sap.sse.common.Duration; @@ -120,12 +120,9 @@ public class EstimationDataSerializationDeserializationTest { longestIntervalBetweenTwoFixes, intervalBetweenLastFixOfCurveAndNextFix, intervalBetweenFirstFixOfCurveAndPreviousFix); - MillisecondsTimePoint windTimePoint = new MillisecondsTimePoint(dateFormat.parse("06/23/2011-15:28:25")); SpeedWithBearing windSpeedWithBearing = new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(340)); - DegreePosition windPosition = new DegreePosition(54.325246, 10.148556); - Wind wind = new WindImpl(windPosition, windTimePoint, windSpeedWithBearing); - DegreePosition maneuverPosition = new DegreePosition(50.325246, 11.148556); + Wind wind = new WindImpl(maneuverPosition, mainCurve.getTimePointOfMaxTurningRate(), windSpeedWithBearing); int jibingCount = 203; int tackingCount = 12345; boolean maneuverStartsByRunningAwayFromWind = true; @@ -144,12 +141,12 @@ public class EstimationDataSerializationDeserializationTest { CompleteManeuverCurveWithEstimationDataJsonSerializer serializer = new CompleteManeuverCurveWithEstimationDataJsonSerializer( new ManeuverMainCurveWithEstimationDataJsonSerializer(), new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer(), - new WindJsonSerializer(new PositionJsonSerializer()), new PositionJsonSerializer()); + new ManeuverWindJsonSerializer(), new PositionJsonSerializer()); JSONObject json = serializer.serialize(toSerialize); CompleteManeuverCurveWithEstimationDataJsonDeserializer deserializer = new CompleteManeuverCurveWithEstimationDataJsonDeserializer( new ManeuverMainCurveWithEstimationDataJsonDeserializer(), new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonDeserializer(), - new WindJsonDeserializer(new PositionJsonDeserializer()), new PositionJsonDeserializer()); + new ManeuverWindJsonDeserializer(), new PositionJsonDeserializer()); CompleteManeuverCurveWithEstimationData deserialized = deserializer.deserialize(json); assertEquals(deviationFromTargetJibeAngle, @@ -165,8 +162,8 @@ public class EstimationDataSerializationDeserializationTest { assertEquals(relativeBearingToNextMarkBeforeManeuver, deserialized.getRelativeBearingToNextMarkBeforeManeuver()); assertEquals(relativeBearingToNextMarkAfterManeuver, deserialized.getRelativeBearingToNextMarkAfterManeuver()); - assertEquals(windTimePoint, deserialized.getWind().getTimePoint()); - assertEquals(windPosition, deserialized.getWind().getPosition()); + assertEquals(wind.getTimePoint(), deserialized.getWind().getTimePoint()); + assertEquals(wind.getPosition(), deserialized.getWind().getPosition()); assertEquals(windSpeedWithBearing.getBearing(), deserialized.getWind().getBearing()); assertEquals(windSpeedWithBearing.getMetersPerSecond(), deserialized.getWind().getMetersPerSecond(), DELTA); @@ -324,12 +321,12 @@ public class EstimationDataSerializationDeserializationTest { CompleteManeuverCurveWithEstimationDataJsonSerializer serializer = new CompleteManeuverCurveWithEstimationDataJsonSerializer( new ManeuverMainCurveWithEstimationDataJsonSerializer(), new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer(), - new WindJsonSerializer(new PositionJsonSerializer()), new PositionJsonSerializer()); + new ManeuverWindJsonSerializer(), new PositionJsonSerializer()); JSONObject json = serializer.serialize(toSerialize); CompleteManeuverCurveWithEstimationDataJsonDeserializer deserializer = new CompleteManeuverCurveWithEstimationDataJsonDeserializer( new ManeuverMainCurveWithEstimationDataJsonDeserializer(), new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonDeserializer(), - new WindJsonDeserializer(new PositionJsonDeserializer()), new PositionJsonDeserializer()); + new ManeuverWindJsonDeserializer(), new PositionJsonDeserializer()); CompleteManeuverCurveWithEstimationData deserialized = deserializer.deserialize(json); assertEquals(deviationFromTargetJibeAngle, diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CompleteManeuverCurveWithEstimationDataJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CompleteManeuverCurveWithEstimationDataJsonDeserializer.java index 0408e37fd08..886f0e3c745 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CompleteManeuverCurveWithEstimationDataJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CompleteManeuverCurveWithEstimationDataJsonDeserializer.java @@ -3,8 +3,10 @@ package com.sap.sailing.server.gateway.deserialization.impl; import org.json.simple.JSONObject; import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.Wind; import com.sap.sailing.domain.common.impl.MeterDistance; +import com.sap.sailing.domain.common.impl.WindImpl; import com.sap.sailing.domain.maneuverdetection.CompleteManeuverCurveWithEstimationData; import com.sap.sailing.domain.maneuverdetection.ManeuverCurveWithUnstableCourseAndSpeedWithEstimationData; import com.sap.sailing.domain.maneuverdetection.ManeuverMainCurveWithEstimationData; @@ -26,13 +28,13 @@ public class CompleteManeuverCurveWithEstimationDataJsonDeserializer private final ManeuverMainCurveWithEstimationDataJsonDeserializer mainCurveDeserializer; private final ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonDeserializer curveWithUnstableCourseAndSpeedDeserializer; - private final WindJsonDeserializer windDeserializer; + private final ManeuverWindJsonDeserializer windDeserializer; private final PositionJsonDeserializer positionDeserializer; public CompleteManeuverCurveWithEstimationDataJsonDeserializer( ManeuverMainCurveWithEstimationDataJsonDeserializer mainCurveDeserializer, ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonDeserializer curveWithUnstableCourseAndSpeedDeserializer, - WindJsonDeserializer windDeserializer, PositionJsonDeserializer positionDeserializer) { + ManeuverWindJsonDeserializer windDeserializer, PositionJsonDeserializer positionDeserializer) { this.mainCurveDeserializer = mainCurveDeserializer; this.curveWithUnstableCourseAndSpeedDeserializer = curveWithUnstableCourseAndSpeedDeserializer; this.windDeserializer = windDeserializer; @@ -50,7 +52,9 @@ public class CompleteManeuverCurveWithEstimationDataJsonDeserializer .deserialize((JSONObject) object.get( CompleteManeuverCurveWithEstimationDataJsonSerializer.CURVE_WITH_UNSTABLE_COURSE_AND_SPEED)); JSONObject windJson = (JSONObject) object.get(CompleteManeuverCurveWithEstimationDataJsonSerializer.WIND); - Wind wind = windJson == null ? null : windDeserializer.deserialize(windJson); + SpeedWithBearing windSpeedWithBearing = windJson == null ? null : windDeserializer.deserialize(windJson); + Wind wind = windSpeedWithBearing == null ? null + : new WindImpl(position, mainCurve.getTimePointOfMaxTurningRate(), windSpeedWithBearing); Integer tackingCount = getInteger( object.get(CompleteManeuverCurveWithEstimationDataJsonSerializer.TACKING_COUNT)); Integer jibingCount = getInteger( diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/ManeuverWindJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/ManeuverWindJsonDeserializer.java new file mode 100644 index 00000000000..ab20cd8fee8 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/ManeuverWindJsonDeserializer.java @@ -0,0 +1,29 @@ +package com.sap.sailing.server.gateway.deserialization.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.common.SpeedWithBearing; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.serialization.impl.ManeuverWindJsonSerializer; +import com.sap.sse.common.Bearing; +import com.sap.sse.common.impl.DegreeBearingImpl; + +/** + * + * @author Vladislav Chumak (D069712) + * + */ +public class ManeuverWindJsonDeserializer implements JsonDeserializer { + + public SpeedWithBearing deserialize(JSONObject object) throws JsonDeserializationException { + + Double directionInTrueDegrees = (Double) object.get(ManeuverWindJsonSerializer.DIRECTION_IN_TRUE_DEGREES); + Double speedInKnots = (Double) object.get(ManeuverWindJsonSerializer.SPEED_IN_KNOTS); + Bearing degreeBearing = new DegreeBearingImpl(directionInTrueDegrees); + SpeedWithBearing speedBearing = new KnotSpeedWithBearingImpl(speedInKnots, degreeBearing); + return speedBearing; + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurveWithEstimationDataJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurveWithEstimationDataJsonSerializer.java index 5c3ae7b119d..e1b807cf388 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurveWithEstimationDataJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurveWithEstimationDataJsonSerializer.java @@ -29,13 +29,13 @@ public class CompleteManeuverCurveWithEstimationDataJsonSerializer private final ManeuverCurveBoundariesJsonSerializer mainCurveSerializer; private final ManeuverCurveBoundariesJsonSerializer curveWithUnstableCourseAndSpeedSerializer; - private final WindJsonSerializer windSerializer; + private final ManeuverWindJsonSerializer windSerializer; private final PositionJsonSerializer positionSerializer; public CompleteManeuverCurveWithEstimationDataJsonSerializer( ManeuverCurveBoundariesJsonSerializer mainCurveSerializer, ManeuverCurveBoundariesJsonSerializer curveWithUnstableCourseAndSpeedSerializer, - WindJsonSerializer windSerializer, PositionJsonSerializer positionSerializer) { + ManeuverWindJsonSerializer windSerializer, PositionJsonSerializer positionSerializer) { this.mainCurveSerializer = mainCurveSerializer; this.curveWithUnstableCourseAndSpeedSerializer = curveWithUnstableCourseAndSpeedSerializer; this.windSerializer = windSerializer; diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/GpsFixesWithEstimationDataJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/GpsFixesWithEstimationDataJsonSerializer.java new file mode 100644 index 00000000000..4ad7c938008 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/GpsFixesWithEstimationDataJsonSerializer.java @@ -0,0 +1,119 @@ +package com.sap.sailing.server.gateway.serialization.impl; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.SpeedWithBearing; +import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorImpl; +import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorWithEstimationDataSupportDecoratorImpl; +import com.sap.sailing.domain.maneuverdetection.impl.TrackTimeInfo; +import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sse.common.Bearing; +import com.sap.sse.common.Distance; +import com.sap.sse.common.Duration; + +/** + * + * @author Vladislav Chumak (D069712) + * + */ +public class GpsFixesWithEstimationDataJsonSerializer extends AbstractTrackedRaceDataJsonSerializer { + public static final String GPS_FIXES = "gpsFixes"; + public static final String BOAT_CLASS = "boatClass"; + public static final String COMPETITOR_NAME = "competitorName"; + public static final String AVG_INTERVAL_BETWEEN_FIXES_IN_SECONDS = "avgIntervalBetweenFixesInSeconds"; + public static final String DISTANCE_TRAVELLED_IN_METERS = "distanceTravelledInMeters"; + public static final String START_TIME_POINT = "startUnixTime"; + public static final String END_TIME_POINT = "endUnixTime"; + public static final String WIND = "wind"; + public static final String RELATIVE_BEARING_TO_NEXT_MARK = "relativeBearingToNextMark"; + public static final String CLOSEST_DISTANCE_TO_MARK = "closestDistanceToMarkInMeters"; + + private final BoatClassJsonSerializer boatClassJsonSerializer; + private final GPSFixMovingJsonSerializer gpsFixMovingJsonSerializer; + private final boolean addWind; + private final boolean addNextWaypoint; + private final ManeuverWindJsonSerializer windJsonSerializer; + private final Boolean smoothFixes; + + public GpsFixesWithEstimationDataJsonSerializer(BoatClassJsonSerializer boatClassJsonSerializer, + GPSFixMovingJsonSerializer gpsFixMovingJsonSerializer, ManeuverWindJsonSerializer windJsonSerializer, + boolean addWind, boolean addNextWaypoint, Boolean smoothFixes) { + this.boatClassJsonSerializer = boatClassJsonSerializer; + this.gpsFixMovingJsonSerializer = gpsFixMovingJsonSerializer; + this.windJsonSerializer = windJsonSerializer; + this.addWind = addWind; + this.addNextWaypoint = addNextWaypoint; + this.smoothFixes = smoothFixes; + } + + @Override + public JSONObject serialize(TrackedRace trackedRace) { + final JSONObject result = new JSONObject(); + JSONArray byCompetitorJson = new JSONArray(); + result.put(BYCOMPETITOR, byCompetitorJson); + for (Competitor competitor : trackedRace.getRace().getCompetitors()) { + ManeuverDetectorImpl maneuverDetector = new ManeuverDetectorImpl(trackedRace, competitor); + ManeuverDetectorWithEstimationDataSupportDecoratorImpl estimationDataSupportDecoratorImpl = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl( + maneuverDetector, null); + TrackTimeInfo trackTimeInfo = maneuverDetector.getTrackTimeInfo(); + if (trackTimeInfo != null) { + final JSONObject forCompetitorJson = new JSONObject(); + byCompetitorJson.add(forCompetitorJson); + forCompetitorJson.put(COMPETITOR_NAME, competitor.getName()); + forCompetitorJson.put(BOAT_CLASS, boatClassJsonSerializer + .serialize(trackedRace.getRace().getBoatOfCompetitor(competitor).getBoatClass())); + final JSONArray gpsFixesWithEstimationData = new JSONArray(); + GPSFixTrack track = trackedRace.getTrack(competitor); + track.lockForRead(); + try { + for (GPSFixMoving gpsFix : track.getFixes()) { + JSONObject serializedGpsFix = gpsFixMovingJsonSerializer.serialize(gpsFix); + if (addWind) { + Wind wind = trackedRace.getWind(gpsFix.getPosition(), gpsFix.getTimePoint()); + JSONObject serializedWind = wind == null ? null : windJsonSerializer.serialize(wind); + serializedGpsFix.put(WIND, serializedWind); + } + if (addNextWaypoint) { + Distance closestDistanceToMark = estimationDataSupportDecoratorImpl + .getClosestDistanceToMark(gpsFix.getTimePoint()); + SpeedWithBearing speedWithBearing = smoothFixes + ? track.getEstimatedSpeed(gpsFix.getTimePoint()) : gpsFix.getSpeed(); + Bearing relativeBearingToNextMark = speedWithBearing == null ? null + : estimationDataSupportDecoratorImpl.getRelativeBearingToNextMark( + gpsFix.getTimePoint(), speedWithBearing.getBearing()); + serializedGpsFix.put(CLOSEST_DISTANCE_TO_MARK, + closestDistanceToMark == null ? null : closestDistanceToMark.getMeters()); + serializedGpsFix.put(RELATIVE_BEARING_TO_NEXT_MARK, + relativeBearingToNextMark == null ? null : relativeBearingToNextMark.getDegrees()); + } + gpsFixesWithEstimationData.add(serializedGpsFix); + } + } finally { + track.unlockAfterRead(); + } + forCompetitorJson.put(GPS_FIXES, gpsFixesWithEstimationData); + Duration averageIntervalBetweenFixes = trackedRace.getTrack(competitor) + .getAverageIntervalBetweenFixes(); + forCompetitorJson.put(AVG_INTERVAL_BETWEEN_FIXES_IN_SECONDS, + averageIntervalBetweenFixes == null ? 0 : averageIntervalBetweenFixes.asSeconds()); + Double distanceTravelledInMeters = null; + if (trackTimeInfo.getTrackStartTimePoint() != null && trackTimeInfo.getTrackEndTimePoint() != null) { + distanceTravelledInMeters = track.getDistanceTraveled(trackTimeInfo.getTrackStartTimePoint(), + trackTimeInfo.getTrackEndTimePoint()).getMeters(); + } + forCompetitorJson.put(DISTANCE_TRAVELLED_IN_METERS, distanceTravelledInMeters); + forCompetitorJson.put(START_TIME_POINT, trackTimeInfo.getTrackStartTimePoint() == null ? null + : trackTimeInfo.getTrackStartTimePoint().asMillis()); + forCompetitorJson.put(END_TIME_POINT, trackTimeInfo.getTrackEndTimePoint() == null ? null + : trackTimeInfo.getTrackEndTimePoint().asMillis()); + } + } + return result; + } + +} diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index 6ae0be5b38d..c2e4743c7dd 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -85,9 +85,12 @@ import com.sap.sailing.server.gateway.serialization.impl.DetailedBoatClassJsonSe import com.sap.sailing.server.gateway.serialization.impl.DistanceJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.FleetJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.GPSFixJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.GPSFixMovingJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.GpsFixesWithEstimationDataJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ManeuverJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ManeuverMainCurveWithEstimationDataJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.ManeuverWindJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ManeuversJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.MarkPassingsJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer; @@ -1047,7 +1050,39 @@ public class RegattasResource extends AbstractSailingServerResource { new CompleteManeuverCurveWithEstimationDataJsonSerializer( new ManeuverMainCurveWithEstimationDataJsonSerializer(), new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer(), - new WindJsonSerializer(new PositionJsonSerializer()), new PositionJsonSerializer())); + new ManeuverWindJsonSerializer(), new PositionJsonSerializer())); + JSONObject jsonMarkPassings = serializer.serialize(trackedRace); + String json = jsonMarkPassings.toJSONString(); + return Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); + } + } + return response; + } + + @GET + @Produces("application/json;charset=UTF-8") + @Path("{regattaname}/races/{racename}/gpsFixesWithEstimationData") + public Response getGpsFixesWithEstimationData(@PathParam("regattaname") String regattaName, + @PathParam("racename") String raceName, @QueryParam("addWind") @DefaultValue("true") Boolean addWind, + @QueryParam("addNextWaypoint") @DefaultValue("true") Boolean addNextWaypoint, + @QueryParam("smoothFixes") @DefaultValue("true") Boolean smoothFixes) { + Response response; + Regatta regatta = findRegattaByName(regattaName); + if (regatta == null) { + response = Response.status(Status.NOT_FOUND) + .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.") + .type(MediaType.TEXT_PLAIN).build(); + } else { + RaceDefinition race = findRaceByName(regatta, raceName); + if (race == null) { + response = Response.status(Status.NOT_FOUND) + .entity("Could not find a race with name '" + StringEscapeUtils.escapeHtml(raceName) + "'.") + .type(MediaType.TEXT_PLAIN).build(); + } else { + TrackedRace trackedRace = findTrackedRace(regattaName, raceName); + GpsFixesWithEstimationDataJsonSerializer serializer = new GpsFixesWithEstimationDataJsonSerializer( + new DetailedBoatClassJsonSerializer(), new GPSFixMovingJsonSerializer(), + new ManeuverWindJsonSerializer(), addWind, addNextWaypoint, smoothFixes); JSONObject jsonMarkPassings = serializer.serialize(trackedRace); String json = jsonMarkPassings.toJSONString(); return Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); From 656e16545d3827a5e53db7bb294085291442821e Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Thu, 5 Jul 2018 13:06:39 +0200 Subject: [PATCH 015/292] bug4614: Changed getDoubleValue() in SortableMinMaxColumn to return the desired value according to the rendering order. --- .../racemap/maneuver/ManeuverTablePanel.java | 10 +++--- .../maneuver/SortableMinMaxColumn.java | 2 +- .../gwt/ui/leaderboard/MinMaxRenderer.java | 31 ++++++++++--------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java index 2d233399dbf..48a9d511e1e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java @@ -141,17 +141,17 @@ public class ManeuverTablePanel extends AbstractCompositeComponent { protected static final String BACKGROUND_BAR_STYLE_GOOD = "minMaxBackgroundBarGood"; private final HasStringAndDoubleValue valueProvider; + /** used to determine minimum and maximum values for the rendered bars.*/ private final Comparator comparator; private Double minimumValue; private Double maximumValue; @@ -119,7 +120,8 @@ public class MinMaxRenderer { * @param row * The row to get the percentage for. */ - protected int getPercentage(T row) { + + protected int getPercentage(T row) { int percentage = 0; Double value = valueProvider.getDoubleValue(row); if (value != null) { @@ -128,10 +130,8 @@ public class MinMaxRenderer { percentage = (int) (minBarLength + (100. - minBarLength) * (value - getMinimumDouble()) / (getMaximumDouble() - getMinimumDouble())); } - - } + } return percentage; - } private Double getMinimumDouble() { @@ -149,23 +149,24 @@ public class MinMaxRenderer { * The values of {@link LeaderboardRowDTO}s to determine the minimum and maximum values for. */ public void updateMinMax(Iterable displayedLeaderboardRowsProvider) { - T minimumRow = null; - T maximumRow = null; + T minimumOrderRow = null; + T maximumOrderRow = null; for (T row : displayedLeaderboardRowsProvider) { if (valueProvider.getDoubleValue(row) != null - && (minimumRow == null || comparator.compare(minimumRow, row) > 0)) { - minimumRow = row; + && (minimumOrderRow == null || comparator.compare(minimumOrderRow, row) > 0)) { + minimumOrderRow = row; } if (valueProvider.getDoubleValue(row) != null - && (maximumRow == null || comparator.compare(maximumRow, row) < 0)) { - maximumRow = row; + && (maximumOrderRow == null || comparator.compare(maximumOrderRow, row) < 0)) { + maximumOrderRow = row; } + } + if (minimumOrderRow != null) { + minimumValue = valueProvider.getDoubleValue(minimumOrderRow); + } - if (minimumRow != null) { - minimumValue = valueProvider.getDoubleValue(minimumRow); - } - if (maximumRow != null) { - maximumValue = valueProvider.getDoubleValue(maximumRow); + if (maximumOrderRow != null) { + maximumValue = valueProvider.getDoubleValue(maximumOrderRow); } } From 80de00ec48500abe06ca83a1cd24be7f4f2e3693 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Thu, 5 Jul 2018 14:05:23 +0200 Subject: [PATCH 016/292] Added parameters to get maneuvers and gps fixes before and after start/finish line --- .../impl/ManeuverDetectorImpl.java | 2 +- ...urvesWithEstimationDataJsonSerializer.java | 77 ++++++++++++++++--- ...FixesWithEstimationDataJsonSerializer.java | 36 ++++++++- .../gateway/jaxrs/api/RegattasResource.java | 28 ++++++- 4 files changed, 124 insertions(+), 19 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java index 0d77148b553..b4068b215f9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorImpl.java @@ -128,7 +128,7 @@ public class ManeuverDetectorImpl extends AbstractManeuverDetectorImpl { * @return an empty list if no maneuver spots are detected for competitor between from and * to, or else the list of maneuver spots with corresponding maneuvers detected. */ - protected List detectManeuvers(TimePoint earliestManeuverStart, TimePoint latestManeuverEnd) { + public List detectManeuvers(TimePoint earliestManeuverStart, TimePoint latestManeuverEnd) { ApproximatedFixesCalculator approximatedFixesCalculator = new ApproximatedFixesCalculatorImpl(trackedRace, competitor); Iterable approximatedFixes = approximatedFixesCalculator.approximate(earliestManeuverStart, diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java index 6bb7a8fb7d6..357d034b0d4 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurvesWithEstimationDataJsonSerializer.java @@ -1,5 +1,8 @@ package com.sap.sailing.server.gateway.serialization.impl; +import java.util.List; +import java.util.stream.Collectors; + import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -10,6 +13,7 @@ import com.sap.sailing.domain.maneuverdetection.CompleteManeuverCurveWithEstimat import com.sap.sailing.domain.maneuverdetection.ManeuverDetectorWithEstimationDataSupport; import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorImpl; import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorWithEstimationDataSupportDecoratorImpl; +import com.sap.sailing.domain.maneuverdetection.impl.ManeuverSpot; import com.sap.sailing.domain.maneuverdetection.impl.TrackTimeInfo; import com.sap.sailing.domain.polars.PolarDataService; import com.sap.sailing.domain.tracking.CompleteManeuverCurve; @@ -17,6 +21,8 @@ import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.Maneuver; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.Duration; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsDurationImpl; /** * @@ -36,13 +42,23 @@ public class CompleteManeuverCurvesWithEstimationDataJsonSerializer extends Abst private final BoatClassJsonSerializer boatClassJsonSerializer; private final CompleteManeuverCurveWithEstimationDataJsonSerializer maneuverWithEstimationDataJsonSerializer; private final PolarDataService polarDataService; + private final Integer startBeforeStartLineInSeconds; + private final Integer endBeforeStartLineInSeconds; + private final Integer startAfterFinishLineInSeconds; + private final Integer endAfterFinishLineInSeconds; public CompleteManeuverCurvesWithEstimationDataJsonSerializer(PolarDataService polarDataService, BoatClassJsonSerializer boatClassJsonSerializer, - CompleteManeuverCurveWithEstimationDataJsonSerializer maneuverWithEstimationDataJsonSerializer) { + CompleteManeuverCurveWithEstimationDataJsonSerializer maneuverWithEstimationDataJsonSerializer, + Integer startBeforeStartLineInSeconds, Integer endBeforeStartLineInSeconds, + Integer startAfterFinishLineInSeconds, Integer endAfterFinishLineInSeconds) { this.polarDataService = polarDataService; this.boatClassJsonSerializer = boatClassJsonSerializer; this.maneuverWithEstimationDataJsonSerializer = maneuverWithEstimationDataJsonSerializer; + this.startBeforeStartLineInSeconds = startBeforeStartLineInSeconds; + this.endBeforeStartLineInSeconds = endBeforeStartLineInSeconds; + this.startAfterFinishLineInSeconds = startAfterFinishLineInSeconds; + this.endAfterFinishLineInSeconds = endAfterFinishLineInSeconds; } @Override @@ -53,15 +69,41 @@ public class CompleteManeuverCurvesWithEstimationDataJsonSerializer extends Abst for (Competitor competitor : trackedRace.getRace().getCompetitors()) { ManeuverDetectorImpl maneuverDetector = new ManeuverDetectorImpl(trackedRace, competitor); TrackTimeInfo trackTimeInfo = maneuverDetector.getTrackTimeInfo(); + TimePoint from = null; + TimePoint to = null; + if (startBeforeStartLineInSeconds != Integer.MIN_VALUE) { + from = trackTimeInfo.getTrackStartTimePoint() + .minus(new MillisecondsDurationImpl(startBeforeStartLineInSeconds * 1000L)); + } else if (startAfterFinishLineInSeconds != Integer.MIN_VALUE) { + from = trackTimeInfo.getTrackEndTimePoint() + .plus(new MillisecondsDurationImpl(startAfterFinishLineInSeconds * 1000L)); + } + if (endAfterFinishLineInSeconds != Integer.MIN_VALUE) { + to = trackTimeInfo.getTrackEndTimePoint() + .plus(new MillisecondsDurationImpl(endAfterFinishLineInSeconds * 1000L)); + } else if (endBeforeStartLineInSeconds != Integer.MIN_VALUE) { + to = trackTimeInfo.getTrackStartTimePoint() + .minus(new MillisecondsDurationImpl(endBeforeStartLineInSeconds * 1000L)); + } if (trackTimeInfo != null) { + if (from != null ^ to != null) { + if (from == null) { + from = trackTimeInfo.getTrackStartTimePoint(); + } + if (to == null) { + to = trackTimeInfo.getTrackEndTimePoint(); + } + } final JSONObject forCompetitorJson = new JSONObject(); byCompetitorJson.add(forCompetitorJson); forCompetitorJson.put(COMPETITOR_NAME, competitor.getName()); forCompetitorJson.put(BOAT_CLASS, boatClassJsonSerializer .serialize(trackedRace.getRace().getBoatOfCompetitor(competitor).getBoatClass())); final JSONArray completeManeuverCurvesWithEstimationData = new JSONArray(); - for (CompleteManeuverCurveWithEstimationData maneuver : getCompleteManeuverCurvesWithEstimationData( - trackedRace, competitor)) { + Iterable completeManeuvers = from != null + ? getCompleteManeuverCurvesWithEstimationData(trackedRace, competitor, from, to) + : getCompleteManeuverCurvesWithEstimationData(trackedRace, competitor); + for (CompleteManeuverCurveWithEstimationData maneuver : completeManeuvers) { completeManeuverCurvesWithEstimationData .add(maneuverWithEstimationDataJsonSerializer.serialize(maneuver)); } @@ -87,18 +129,29 @@ public class CompleteManeuverCurvesWithEstimationDataJsonSerializer extends Abst return result; } + private Iterable getCompleteManeuverCurvesWithEstimationData( + TrackedRace trackedRace, Competitor competitor, TimePoint from, TimePoint to) { + ManeuverDetectorImpl maneuverDetector = new ManeuverDetectorImpl(trackedRace, competitor); + List maneuverSpots = maneuverDetector.detectManeuvers(from, to); + List maneuverCurves = maneuverSpots.stream() + .map(maneuverSpot -> maneuverSpot.getManeuverCurve()).collect(Collectors.toList()); + ManeuverDetectorWithEstimationDataSupport maneuverDetectorWithEstimationData = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl( + maneuverDetector, polarDataService); + Iterable maneuversWithEstimationData = maneuverDetectorWithEstimationData + .getCompleteManeuverCurvesWithEstimationData(maneuverCurves); + return maneuversWithEstimationData; + } + private Iterable getCompleteManeuverCurvesWithEstimationData( TrackedRace trackedRace, Competitor competitor) { Iterable maneuvers = trackedRace.getManeuvers(competitor, false); - ManeuverDetectorWithEstimationDataSupport maneuverDetector = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl( - new ManeuverDetectorImpl(trackedRace, competitor), polarDataService); - Iterable maneuversWithEstimationData = null; - try { - Iterable maneuverCurves = maneuverDetector.getCompleteManeuverCurves(maneuvers); - maneuversWithEstimationData = maneuverDetector.getCompleteManeuverCurvesWithEstimationData(maneuverCurves); - } catch (Exception e) { - e.printStackTrace(); - } + ManeuverDetectorImpl maneuverDetector = new ManeuverDetectorImpl(trackedRace, competitor); + ManeuverDetectorWithEstimationDataSupport maneuverDetectorWithEstimationData = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl( + maneuverDetector, polarDataService); + Iterable maneuverCurves = maneuverDetectorWithEstimationData + .getCompleteManeuverCurves(maneuvers); + Iterable maneuversWithEstimationData = maneuverDetectorWithEstimationData + .getCompleteManeuverCurvesWithEstimationData(maneuverCurves); return maneuversWithEstimationData; } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/GpsFixesWithEstimationDataJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/GpsFixesWithEstimationDataJsonSerializer.java index 4ad7c938008..06cddcbfdd3 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/GpsFixesWithEstimationDataJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/GpsFixesWithEstimationDataJsonSerializer.java @@ -15,6 +15,8 @@ import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.Bearing; import com.sap.sse.common.Distance; import com.sap.sse.common.Duration; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsDurationImpl; /** * @@ -39,16 +41,26 @@ public class GpsFixesWithEstimationDataJsonSerializer extends AbstractTrackedRac private final boolean addNextWaypoint; private final ManeuverWindJsonSerializer windJsonSerializer; private final Boolean smoothFixes; + private Integer startBeforeStartLineInSeconds; + private Integer endBeforeStartLineInSeconds; + private Integer startAfterFinishLineInSeconds; + private Integer endAfterFinishLineInSeconds; public GpsFixesWithEstimationDataJsonSerializer(BoatClassJsonSerializer boatClassJsonSerializer, GPSFixMovingJsonSerializer gpsFixMovingJsonSerializer, ManeuverWindJsonSerializer windJsonSerializer, - boolean addWind, boolean addNextWaypoint, Boolean smoothFixes) { + boolean addWind, boolean addNextWaypoint, Boolean smoothFixes, Integer startBeforeStartLineInSeconds, + Integer endBeforeStartLineInSeconds, Integer startAfterFinishLineInSeconds, + Integer endAfterFinishLineInSeconds) { this.boatClassJsonSerializer = boatClassJsonSerializer; this.gpsFixMovingJsonSerializer = gpsFixMovingJsonSerializer; this.windJsonSerializer = windJsonSerializer; this.addWind = addWind; this.addNextWaypoint = addNextWaypoint; this.smoothFixes = smoothFixes; + this.startBeforeStartLineInSeconds = startBeforeStartLineInSeconds; + this.endBeforeStartLineInSeconds = endBeforeStartLineInSeconds; + this.startAfterFinishLineInSeconds = startAfterFinishLineInSeconds; + this.endAfterFinishLineInSeconds = endAfterFinishLineInSeconds; } @Override @@ -61,6 +73,26 @@ public class GpsFixesWithEstimationDataJsonSerializer extends AbstractTrackedRac ManeuverDetectorWithEstimationDataSupportDecoratorImpl estimationDataSupportDecoratorImpl = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl( maneuverDetector, null); TrackTimeInfo trackTimeInfo = maneuverDetector.getTrackTimeInfo(); + TimePoint from = null; + TimePoint to = null; + if (startBeforeStartLineInSeconds != Integer.MIN_VALUE) { + from = trackTimeInfo.getTrackStartTimePoint() + .minus(new MillisecondsDurationImpl(startBeforeStartLineInSeconds * 1000L)); + } else if (startAfterFinishLineInSeconds != Integer.MIN_VALUE) { + from = trackTimeInfo.getTrackEndTimePoint() + .plus(new MillisecondsDurationImpl(startAfterFinishLineInSeconds * 1000L)); + } else { + from = trackTimeInfo.getTrackStartTimePoint(); + } + if (endAfterFinishLineInSeconds != Integer.MIN_VALUE) { + to = trackTimeInfo.getTrackEndTimePoint() + .plus(new MillisecondsDurationImpl(endAfterFinishLineInSeconds * 1000L)); + } else if (endBeforeStartLineInSeconds != Integer.MIN_VALUE) { + to = trackTimeInfo.getTrackStartTimePoint() + .minus(new MillisecondsDurationImpl(endBeforeStartLineInSeconds * 1000L)); + } else { + to = trackTimeInfo.getTrackEndTimePoint(); + } if (trackTimeInfo != null) { final JSONObject forCompetitorJson = new JSONObject(); byCompetitorJson.add(forCompetitorJson); @@ -71,7 +103,7 @@ public class GpsFixesWithEstimationDataJsonSerializer extends AbstractTrackedRac GPSFixTrack track = trackedRace.getTrack(competitor); track.lockForRead(); try { - for (GPSFixMoving gpsFix : track.getFixes()) { + for (GPSFixMoving gpsFix : track.getFixes(from, true, to, true)) { JSONObject serializedGpsFix = gpsFixMovingJsonSerializer.serialize(gpsFix); if (addWind) { Wind wind = trackedRace.getWind(gpsFix.getPosition(), gpsFix.getTimePoint()); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index c2e4743c7dd..8215e8819d9 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -1030,7 +1030,15 @@ public class RegattasResource extends AbstractSailingServerResource { @Produces("application/json;charset=UTF-8") @Path("{regattaname}/races/{racename}/completeManeuverCurvesWithEstimationData") public Response getCompleteManeuverCurvesWithEstimationData(@PathParam("regattaname") String regattaName, - @PathParam("racename") String raceName) { + @PathParam("racename") String raceName, + @QueryParam("startBeforeStartLineInSeconds") @DefaultValue(Integer.MIN_VALUE + + "") Integer startBeforeStartLineInSeconds, + @QueryParam("endBeforeStartLineInSeconds") @DefaultValue(Integer.MIN_VALUE + + "") Integer endBeforeStartLineInSeconds, + @QueryParam("startAfterFinishLineInSeconds") @DefaultValue(Integer.MIN_VALUE + + "") Integer startAfterFinishLineInSeconds, + @QueryParam("endAfterFinishLineInSeconds") @DefaultValue(Integer.MIN_VALUE + + "") Integer endAfterFinishLineInSeconds) { Response response; Regatta regatta = findRegattaByName(regattaName); if (regatta == null) { @@ -1050,7 +1058,9 @@ public class RegattasResource extends AbstractSailingServerResource { new CompleteManeuverCurveWithEstimationDataJsonSerializer( new ManeuverMainCurveWithEstimationDataJsonSerializer(), new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer(), - new ManeuverWindJsonSerializer(), new PositionJsonSerializer())); + new ManeuverWindJsonSerializer(), new PositionJsonSerializer()), + startBeforeStartLineInSeconds, endBeforeStartLineInSeconds, startAfterFinishLineInSeconds, + endAfterFinishLineInSeconds); JSONObject jsonMarkPassings = serializer.serialize(trackedRace); String json = jsonMarkPassings.toJSONString(); return Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); @@ -1065,7 +1075,15 @@ public class RegattasResource extends AbstractSailingServerResource { public Response getGpsFixesWithEstimationData(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName, @QueryParam("addWind") @DefaultValue("true") Boolean addWind, @QueryParam("addNextWaypoint") @DefaultValue("true") Boolean addNextWaypoint, - @QueryParam("smoothFixes") @DefaultValue("true") Boolean smoothFixes) { + @QueryParam("smoothFixes") @DefaultValue("true") Boolean smoothFixes, + @QueryParam("startBeforeStartLineInSeconds") @DefaultValue(Integer.MIN_VALUE + + "") Integer startBeforeStartLineInSeconds, + @QueryParam("endBeforeStartLineInSeconds") @DefaultValue(Integer.MIN_VALUE + + "") Integer endBeforeStartLineInSeconds, + @QueryParam("startAfterFinishLineInSeconds") @DefaultValue(Integer.MIN_VALUE + + "") Integer startAfterFinishLineInSeconds, + @QueryParam("endAfterFinishLineInSeconds") @DefaultValue(Integer.MIN_VALUE + + "") Integer endAfterFinishLineInSeconds) { Response response; Regatta regatta = findRegattaByName(regattaName); if (regatta == null) { @@ -1082,7 +1100,9 @@ public class RegattasResource extends AbstractSailingServerResource { TrackedRace trackedRace = findTrackedRace(regattaName, raceName); GpsFixesWithEstimationDataJsonSerializer serializer = new GpsFixesWithEstimationDataJsonSerializer( new DetailedBoatClassJsonSerializer(), new GPSFixMovingJsonSerializer(), - new ManeuverWindJsonSerializer(), addWind, addNextWaypoint, smoothFixes); + new ManeuverWindJsonSerializer(), addWind, addNextWaypoint, smoothFixes, + startBeforeStartLineInSeconds, endBeforeStartLineInSeconds, startAfterFinishLineInSeconds, + endAfterFinishLineInSeconds); JSONObject jsonMarkPassings = serializer.serialize(trackedRace); String json = jsonMarkPassings.toJSONString(); return Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); From 7d07b8fe483f3fb8597069e88e55bd67e1b61b5c Mon Sep 17 00:00:00 2001 From: Lennart Hensler Date: Thu, 5 Jul 2018 18:04:34 +0200 Subject: [PATCH 017/292] First attempt to correct the maneuver count calculations of TrackedRaceOfCompetitor --- .../data/RaceOfCompetitorWithContext.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/data/RaceOfCompetitorWithContext.java b/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/data/RaceOfCompetitorWithContext.java index e1b5013233e..e3258e846e6 100644 --- a/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/data/RaceOfCompetitorWithContext.java +++ b/java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/data/RaceOfCompetitorWithContext.java @@ -259,22 +259,29 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext { } private int getNumberOf(ManeuverType maneuverType) { - TrackedRace trackedRace = getTrackedRace(); int number = 0; - if (trackedRace != null && trackedRace.getStartOfRace() != null) { - final TimePoint end; - final TimePoint endOfTracking = trackedRace.getEndOfTracking(); - if (trackedRace.getEndOfRace() != null) { - end = trackedRace.getEndOfRace(); + TrackedRace trackedRace = getTrackedRace(); + if (trackedRace != null) { + Course course = trackedRace.getRace().getCourse(); + Waypoint startWaypoint = course.getFirstWaypoint(); + MarkPassing startPassing = trackedRace.getMarkPassing(getCompetitor(), startWaypoint); + TimePoint start = startPassing != null ? startPassing.getTimePoint() : trackedRace.getStartOfRace(); + + Waypoint finishWaypoint = course.getLastWaypoint(); + MarkPassing finishPassing = trackedRace.getMarkPassing(getCompetitor(), finishWaypoint); + TimePoint end; + if (finishPassing != null) { + end = finishPassing.getTimePoint(); } else { - final TimePoint now = MillisecondsTimePoint.now(); - if (endOfTracking != null && endOfTracking.before(now)) { - end = endOfTracking; - } else { - end = now; + end = trackedRace.getEndOfRace(); + if (end == null) { + TimePoint endOfTracking = trackedRace.getEndOfTracking(); + TimePoint now = MillisecondsTimePoint.now(); + end = endOfTracking != null && endOfTracking.before(now) ? endOfTracking : now; } } - for (Maneuver maneuver : trackedRace.getManeuvers(getCompetitor(), trackedRace.getStartOfRace(), end, false)) { + + for (Maneuver maneuver : trackedRace.getManeuvers(getCompetitor(), start, end, false)) { if (maneuver.getType() == maneuverType) { number++; } From f384a85a58acd62ad76d8a12d0b7641bb71e2106 Mon Sep 17 00:00:00 2001 From: Lennart Hensler Date: Fri, 6 Jul 2018 12:07:42 +0200 Subject: [PATCH 018/292] Fixed the source paths of the DataMiningResources --- .../ui/client/resources/DataMiningResources.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/resources/DataMiningResources.java b/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/resources/DataMiningResources.java index a3bb8df0fb2..81122a16629 100644 --- a/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/resources/DataMiningResources.java +++ b/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/resources/DataMiningResources.java @@ -5,19 +5,19 @@ import com.google.gwt.resources.client.ImageResource; public interface DataMiningResources extends ClientBundle { - @Source("com/sap/sailing/gwt/ui/client/images/close.png") + @Source("com/sap/sse/datamining/ui/images/close.png") ImageResource closeIcon(); - @Source("com/sap/sailing/gwt/ui/client/images/arrow_left.png") + @Source("com/sap/sse/datamining/ui/images/arrow_left.png") ImageResource arrowLeftIcon(); - @Source("com/sap/sailing/gwt/ui/client/images/arrow_right.png") + @Source("com/sap/sse/datamining/ui/images/arrow_right.png") ImageResource arrowRightIcon(); - @Source("com/sap/sailing/gwt/ui/client/images/plusicon_small.png") + @Source("com/sap/sse/datamining/ui/images/plusicon_small.png") ImageResource plusIcon(); - @Source("com/sap/sailing/gwt/ui/client/images/magnifier_small.png") + @Source("com/sap/sse/datamining/ui/images/magnifier_small.png") ImageResource searchIcon(); } From d510aaffe5981964d69855b58d894de76f69bcaa Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sun, 8 Jul 2018 23:10:12 +0200 Subject: [PATCH 019/292] added a comment Change-Id: I064852e27210946caafd3efbf61645b539bced4b --- .../com/sap/sailing/domain/tracking/impl/TimeRangeCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TimeRangeCache.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TimeRangeCache.java index de43e8d22f7..b4ed5ace655 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TimeRangeCache.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TimeRangeCache.java @@ -144,7 +144,7 @@ public class TimeRangeCache { // no writer can be active because we're holding the read lock; read access on the lruCache is synchronized using // the lruCache's mutex; this is necessary because we're using access-based LRU pinging where even getting an entry // modifies the internal parts of the data structure which is not thread safe. - synchronized (lruCache) { + synchronized (lruCache) { // ping the "perfect match" although it may not even have existed in the cache lruCache.get(new Util.Pair(from, to)); } return result; From a1c5ee246b6bf3f6cd007b4b325bd2d1032c77c9 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sun, 8 Jul 2018 23:20:12 +0200 Subject: [PATCH 020/292] catch Throwable instead of Exception to also catch AssertionErrors --- .../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 19180b1b143..3eeba3fab02 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 @@ -5062,7 +5062,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final MasterDataImporter importer = new MasterDataImporter(baseDomainFactory, getService()); importer.importFromStream(inputStream, importOperationId, override); - } catch (Exception e) { + } catch (Throwable e) { // do not assume that RuntimeException is logged properly logger.log(Level.SEVERE, e.getMessage(), e); getService() From 0ede320c21d39c7706b9e0942c37b80f56eeb750 Mon Sep 17 00:00:00 2001 From: D067890 Date: Mon, 9 Jul 2018 16:21:25 +0200 Subject: [PATCH 021/292] Added RaceLogEvent for tagging, added fitting visit methods --- .../domain/persistence/impl/FieldNames.java | 2 +- .../impl/MongoObjectFactoryImpl.java | 13 ++++- .../impl/MongoRaceLogStoreVisitor.java | 7 +++ .../abstractlog/race/RaceLogEventVisitor.java | 2 + .../abstractlog/race/RaceLogTagEvent.java | 20 ++++++++ .../impl/AbstractRaceLogChangedVisitor.java | 6 +++ .../race/impl/BaseRaceLogEventVisitor.java | 7 ++- .../race/impl/RaceLogTagEventImpl.java | 51 +++++++++++++++++++ .../impl/RaceColumnRaceLogReplicator.java | 6 +++ .../impl/RaceLogTagEventDeserializer.java | 42 +++++++++++++++ .../racelog/impl/RaceLogEventSerializer.java | 14 ++++- .../impl/RaceLogTagEventSerializer.java | 35 +++++++++++++ .../racelog/RaceLogEventSerializerTest.java | 9 +++- 13 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java create mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java create mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java index b557b018195..35bebcb9fa6 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java @@ -105,7 +105,7 @@ public enum FieldNames { RACE_LOG_REVOKED_EVENT_SHORT_INFO, RACE_LOG_REVOKED_REASON, RACE_LOG_DEVICE_MAPPING_EVENT_ID, RACE_LOG_CLOSING_TIMEPOINT, TIMEPOINT_OF_FIXED_MARKPASSING, INDEX_OF_PASSED_WAYPOINT,INDEX_OF_FIRST_SUPPRESSED_WAYPOINT, MARK, RACE_LOG_COMPETITOR_ID, RACE_LOG_BOAT_ID, RACE_LOG_DEPDENDENT_ON_FLEET, RACE_LOG_DEPDENDENT_ON_RACECOLUMN, RACE_LOG_DEPDENDENT_ON_REGATTALIKE, - RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS, + RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS, RACE_LOG_TAG, RACE_LOG_COMMENT, RACE_LOG_IMAGE_URL, /** @deprecated Replaced by {@link #REGATTA_LOG_FROM}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_FROM, /** @deprecated Replaced by {@link #REGATTA_LOG_TO}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_TO, /** @deprecated Replaced by a regatta log entry with type {@link #REGATTA_LOG_MARK} */ @Deprecated RACE_LOG_MARK, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 408e806b9fc..c589f23c665 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -46,6 +46,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; @@ -1087,6 +1088,17 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogUseCompetitorsFromRaceLogEvent(event)); return result; } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogTagEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogTagEvent.class.getSimpleName()); + + result.put(FieldNames.RACE_LOG_TAG.name(), event.getTag()); + result.put(FieldNames.RACE_LOG_COMMENT.name(), event.getComment()); + result.put(FieldNames.RACE_LOG_IMAGE_URL.name(), event.getImageURL().toString()); + return null; + } public DBObject storeRaceLogUseCompetitorsFromRaceLogEvent(RaceLogUseCompetitorsFromRaceLogEvent event) { DBObject result = new BasicDBObject(); @@ -1776,5 +1788,4 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { e.printStackTrace(); } } - } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java index 4ba962744a7..11cb40b051c 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java @@ -21,6 +21,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; @@ -180,4 +181,10 @@ public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor { DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); mongoObjectFactory.storeRaceLogEventEvent(object); } + + @Override + public void visit(RaceLogTagEvent event) { + DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); + mongoObjectFactory.storeRaceLogEventEvent(object); + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java index f51bda94195..a26c060ac4c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java @@ -53,4 +53,6 @@ public interface RaceLogEventVisitor { public void visit(RaceLogEndOfTrackingEvent event); public void visit(RaceLogUseCompetitorsFromRaceLogEvent event); + + public void visit(RaceLogTagEvent event); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java new file mode 100644 index 00000000000..dcff00983eb --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java @@ -0,0 +1,20 @@ +package com.sap.sailing.domain.abstractlog.race; + +import java.net.URL; + +import com.sap.sailing.domain.abstractlog.Revokable; + +public interface RaceLogTagEvent extends RaceLogEvent, Revokable { + + String getTag(); + + /* + * Comment is optional + */ + String getComment(); + /* + * Image URL in RaceLogTagEvents is optional + */ + URL getImageURL(); + +} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java index 9662e231f16..89e0c66cb50 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java @@ -19,6 +19,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; @@ -138,4 +139,9 @@ public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisit public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { notifyListenerAboutEventAdded(event); } + + @Override + public void visit(RaceLogTagEvent event) { + notifyListenerAboutEventAdded(event); + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java index 8f35eb16aba..dd36294e008 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java @@ -18,6 +18,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; @@ -145,4 +146,8 @@ public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor { } -} + @Override + public void visit(RaceLogTagEvent event) { + //TODO maybe add overridding visit methods for subclasses of this class D067890 + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java new file mode 100644 index 00000000000..5a7e88d7db9 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -0,0 +1,51 @@ +package com.sap.sailing.domain.abstractlog.race.impl; + +import java.io.Serializable; +import java.net.URL; +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; +import com.sap.sse.common.TimePoint; + +public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagEvent{ + + + private static final long serialVersionUID = 7213518902555323432L; + + private String tag, comment; + private URL imageURL; + + + public RaceLogTagEventImpl(String pTag, String pComment, URL pImageURL,TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId) { + super(createdAt, logicalTimePoint, author, pId, pPassId); + tag = pTag; + comment = pComment; + imageURL = pImageURL; + } + + @Override + public String getTag() { + return tag; + } + + @Override + public String getComment() { + return comment; + } + + @Override + public TimePoint getTimePoint() { + return getLogicalTimePoint(); + } + + @Override + public URL getImageURL() { + return imageURL; + } + + @Override + public void accept(RaceLogEventVisitor visitor) { + visitor.visit(this); + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java index 26c2a045b4c..82427674879 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java @@ -21,6 +21,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; @@ -162,4 +163,9 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { notifyOnAdd(event); } + + @Override + public void visit(RaceLogTagEvent event) { + notifyOnAdd(event); + } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java new file mode 100644 index 00000000000..f06f6e492ef --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java @@ -0,0 +1,42 @@ +package com.sap.sailing.server.gateway.deserialization.racelog.impl; + +import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogTagEventImpl; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.impl.DynamicCompetitor; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogTagEventSerializer; +import com.sap.sse.common.TimePoint; + +public class RaceLogTagEventDeserializer extends BaseRaceLogEventDeserializer{ + + public RaceLogTagEventDeserializer(JsonDeserializer competitorDeserializer) { + super(competitorDeserializer); + } + + @Override + protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) + throws JsonDeserializationException { + String tag = object.get(RaceLogTagEventSerializer.FIELD_TAG).toString(); + String comment = object.get(RaceLogTagEventSerializer.FIELD_COMMENT).toString(); + String urlPath = object.get(RaceLogTagEventSerializer.FIELD_URL).toString(); + URL url; + try { + url = new URL(urlPath); + } catch (MalformedURLException e) { + throw new JsonDeserializationException(); + } + return new RaceLogTagEventImpl(tag, comment, url, timePoint, timePoint, author, id, passId); + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java index f904497e346..5b43d716987 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java @@ -21,6 +21,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; @@ -80,7 +81,8 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac new RaceLogDependentStartTimeEventSerializer(competitorSerializer), new RaceLogStartOfTrackingEventSerializer(competitorSerializer), new RaceLogUseCompetitorsFromRaceLogEventSerializer(competitorSerializer), - new RaceLogEndOfTrackingEventSerializer(competitorSerializer)); + new RaceLogEndOfTrackingEventSerializer(competitorSerializer), + new RaceLogTagEventSerializer(competitorSerializer)); } private final JsonSerializer flagEventSerializer; @@ -106,6 +108,7 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac private final JsonSerializer startOfTrackingEventSerializer; private final JsonSerializer endOfTrackingEventSerializer; private final JsonSerializer useCompetitorsFromRaceLogEventSerializer; + private final JsonSerializer tagSerializer; private JsonSerializer chosenSerializer; @@ -133,7 +136,8 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac JsonSerializer dependentStartTimeEventSerializer, JsonSerializer startOfTrackingEventSerializer, JsonSerializer endOfTrackingEventSerializer, - JsonSerializer useCompetitorsFromRaceLogEventSerializer) { + JsonSerializer useCompetitorsFromRaceLogEventSerializer, + JsonSerializer tagSerializer) { this.flagEventSerializer = flagEventSerializer; this.startTimeSerializer = startTimeSerializer; this.raceStatusSerializer = raceStatusSerializer; @@ -157,6 +161,7 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac this.startOfTrackingEventSerializer = startOfTrackingEventSerializer; this.endOfTrackingEventSerializer = endOfTrackingEventSerializer; this.useCompetitorsFromRaceLogEventSerializer = useCompetitorsFromRaceLogEventSerializer; + this.tagSerializer = tagSerializer; this.chosenSerializer = null; } @@ -289,4 +294,9 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { chosenSerializer = useCompetitorsFromRaceLogEventSerializer; } + + @Override + public void visit(RaceLogTagEvent event) { + chosenSerializer = tagSerializer; + } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java new file mode 100644 index 00000000000..03183760d93 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java @@ -0,0 +1,35 @@ +package com.sap.sailing.server.gateway.serialization.racelog.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class RaceLogTagEventSerializer extends BaseRaceLogEventSerializer{ + + public static final String VALUE_CLASS = RaceLogTagEvent.class.getSimpleName(); + public static final String FIELD_TAG = "tag"; + public static final String FIELD_COMMENT = "comment"; + public static final String FIELD_URL = "url"; + + public RaceLogTagEventSerializer(JsonSerializer competitorSerializer) { + super(competitorSerializer); + } + + @Override + protected String getClassFieldValue() { + return VALUE_CLASS; + } + + @Override + public JSONObject serialize(RaceLogEvent object) { + RaceLogTagEvent tagEvent = (RaceLogTagEvent) object; + JSONObject result = super.serialize(tagEvent); + result.put(FIELD_TAG, tagEvent.getTag()); + result.put(FIELD_COMMENT, tagEvent.getComment()); + result.put(FIELD_URL, tagEvent.getImageURL().toString()); + return result; + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index 078923639e8..64091171d93 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -69,6 +69,7 @@ public class RaceLogEventSerializerTest { private JsonSerializer startOfTrackingEventSerializer; private JsonSerializer useCompetitorsFromRaceLogEventSerializer; private JsonSerializer endOfTrackingEventSerializer; + private JsonSerializer tagEventSerializer; private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1); @@ -98,6 +99,7 @@ public class RaceLogEventSerializerTest { startOfTrackingEventSerializer = mock(JsonSerializer.class); useCompetitorsFromRaceLogEventSerializer = mock(JsonSerializer.class); endOfTrackingEventSerializer = mock(JsonSerializer.class); + tagEventSerializer = mock(JsonSerializer.class); serializer = new RaceLogEventSerializer(flagEventSerializer, startTimeSerializer, raceStatusSerializer, passChangedSerializer, courseDesignChangedEventSerializer, @@ -109,7 +111,7 @@ public class RaceLogEventSerializerTest { fixedMarkPassingEventSerializer, suppressedMarkPassingsSerializer, additionalScoringInformationSerializer, dependentStartTimeEventSerializer, startOfTrackingEventSerializer, useCompetitorsFromRaceLogEventSerializer, - endOfTrackingEventSerializer); + endOfTrackingEventSerializer, tagEventSerializer); } @Test @@ -249,4 +251,9 @@ public class RaceLogEventSerializerTest { serializer.serialize(event2); verify(registerCompetitorEventSerializer).serialize(event2); } + + @Test + public void testTagSerializer() { + // TODO add test for Serializer for RaceLogTagEvents D067890 + } } From f9e76bcd71cd29048b7c4e76e1f3ff514f18ca5c Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Mon, 9 Jul 2018 17:07:08 +0200 Subject: [PATCH 022/292] Bug 4104: Added first version with collapsable panel for tags at the right side of RaceBoard. --- java/com.sap.sailing.gwt.ui/RaceBoard.css | 27 +++- .../sailing/gwt/ui/client/StringMessages.java | 2 + .../gwt/ui/client/StringMessages.properties | 3 +- .../gwt/ui/raceboard/RaceBoardPanel.java | 42 +++++-- .../raceboard/SideBySideComponentViewer.java | 71 +++++++++-- .../gwt/ui/raceboard/TaggingPanel.java | 54 ++++++++ .../ui/raceboard/TouchSplitLayoutPanel.java | 30 ++++- .../sse/gwt/resources/css/CommonControls.css | 119 ++++++++++++------ 8 files changed, 284 insertions(+), 64 deletions(-) create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java diff --git a/java/com.sap.sailing.gwt.ui/RaceBoard.css b/java/com.sap.sailing.gwt.ui/RaceBoard.css index 38eecd7a2b7..7ee5fde83db 100755 --- a/java/com.sap.sailing.gwt.ui/RaceBoard.css +++ b/java/com.sap.sailing.gwt.ui/RaceBoard.css @@ -594,7 +594,9 @@ img.openColumn { background-position: 5% 50%, 95% 50% } -.gwt-SplitLayoutPanel-EastToggleButton-Open-leaderboard { +.gwt-SplitLayoutPanel-EastToggleButton-Open-leaderboard, +.gwt-SplitLayoutPanel-WestToggleButton-Open-leaderboard + { background-color: white; background-image: url(images/viewicons/@1x/img/SAP_RV_Leaderboard_GHOSTED.png), @@ -604,7 +606,8 @@ img.openColumn { background-position: 5px center, calc(100% - 6px) center; } -.gwt-SplitLayoutPanel-EastToggleButton-Closed-leaderboard { +.gwt-SplitLayoutPanel-EastToggleButton-Closed-leaderboard, +.gwt-SplitLayoutPanel-WestToggleButton-Closed-leaderboard { background-color: white; background-image: url(images/viewicons/@1x/img/SAP_RV_Leaderboard_INACTIVE.png), @@ -614,6 +617,26 @@ img.openColumn { background-position: 5px center, calc(100% - 6px) center; } +.gwt-SplitLayoutPanel-WestToggleButton-Open-tags { + background-color: white; + background-image: + url(images/viewicons/@1x/img/SAP_RV_Map_GHOSTED.png), + url(images/arrows_bottom_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 4% 50%, 96% 50%; + background-position: 5px center, calc(100% - 6px) center; +} + +.gwt-SplitLayoutPanel-WestToggleButton-Closed-tags { + background-color: white; + background-image: + url(images/viewicons/@1x/img/SAP_RV_Map_INACTIVE.png), + url(images/arrows_top_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 4% 50%, 96% 50%; + background-position: 5px center, calc(100% - 6px) center; +} + .gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-media, .gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-media { background-color: white; 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 109d2206aa9..bb4a27c499f 100755 --- 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 @@ -2084,4 +2084,6 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String manage2SailEventIdBoxTooltip(); String manage2SailPort(); String windFinderSpotCollectionsList(); + + String tagging(); } 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 2f5df3eabda..1198f0ea8c5 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 @@ -2077,4 +2077,5 @@ gender=Gender manage2SailEventIdBox=Manage2Sail Event ID manage2SailEventURLBox=Manage2Sail EventURL (json) manage2SailEventIdBoxTooltip=Event ID or a URL that contains the event ID from Manage2Sail -manage2SailPort=Port \ No newline at end of file +manage2SailPort=Port +tagging=Tags \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java index 8cd5dd24f94..f14ec7a6a5f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java @@ -145,7 +145,9 @@ public class RaceBoardPanel private MediaPlayerManagerComponent mediaPlayerManagerComponent; private EditMarkPassingsPanel editMarkPassingPanel; private EditMarkPositionPanel editMarkPositionPanel; - + + private final TaggingPanel taggingPanel; + private final DockLayoutPanel dockPanel; private final ResizableFlowPanel timePanelWrapper; private final static int TIMEPANEL_COLLAPSED_HEIGHT = 67; @@ -154,7 +156,7 @@ public class RaceBoardPanel /** * The component viewer */ - private SideBySideComponentViewer leaderboardAndMapViewer; + private SideBySideComponentViewer mapViewer; private final AsyncActionsExecutor asyncActionsExecutor; @@ -249,7 +251,8 @@ public class RaceBoardPanel @Override public void execute() { // Show/hide the leaderboard panels toggle button text based on the race map height - leaderboardAndMapViewer.setLeftComponentToggleButtonTextVisibilityAndDraggerPosition(raceMap.getOffsetHeight() > 400); + mapViewer.setLeftComponentToggleButtonTextVisibilityAndDraggerPosition(raceMap.getOffsetHeight() > 400); + mapViewer.setRightComponentToggleButtonTextVisibilityAndDraggerPosition(raceMap.getOffsetHeight() > 400); } }); } @@ -297,7 +300,13 @@ public class RaceBoardPanel raceMap.getRightHeaderPanel().add(regattaAndRaceTimeInformationHeader); raceMap.getRightHeaderPanel().add(userManagementMenuView); addChildComponent(raceMap); - + + // add panel for tagging functionality, hidden by default + taggingPanel = new TaggingPanel(new Label("Hello World!"), stringMessages, parent, componentContext); + addChildComponent(taggingPanel); + taggingPanel.setVisible(true); + taggingPanel.setVisible(false); + // Determine if the screen is large enough to initially display the leaderboard panel on the left side of the // map based on the initial screen width. Afterwards, the leaderboard panel visibility can be toggled as usual. boolean isScreenLargeEnoughToInitiallyDisplayLeaderboard = Document.get().getClientWidth() >= 1024; @@ -315,6 +324,7 @@ public class RaceBoardPanel isScreenLargeEnoughToInitiallyDisplayLeaderboard, raceMap, userService, showChartMarkEditMediaButtonsAndVideo); // initializes the raceMap field leaderboardPanel.addLeaderboardUpdateListener(this); + // in case the URL configuration contains the name of a competitors filter set we try to activate it // FIXME the competitorsFilterSets has now moved to CompetitorSearchTextBox (which should probably be renamed); pass on the parameters to the LeaderboardPanel and see what it does with it if (getPerspectiveSettings().getActiveCompetitorsFilterSetName() != null) { @@ -418,7 +428,7 @@ public class RaceBoardPanel mediaPlayerManagerComponent = new MediaPlayerManagerComponent(this, getComponentContext(), mediaPlayerLifecycle, selectedRaceIdentifier, raceTimesInfoProvider, timer, mediaService, userService, stringMessages, errorReporter, userAgent, this, mediaPlayerSettings); - leaderboardAndMapViewer = new SideBySideComponentViewer(leaderboardPanel, raceMap, mediaPlayerManagerComponent, + mapViewer = new SideBySideComponentViewer(leaderboardPanel, raceMap, taggingPanel, mediaPlayerManagerComponent, componentsForSideBySideViewer, stringMessages, userService, editMarkPassingPanel, editMarkPositionPanel, maneuverTablePanel); mediaPlayerManagerComponent.addPlayerChangeListener(new PlayerChangeListener() { @@ -433,7 +443,7 @@ public class RaceBoardPanel addChildComponent(component); } this.setupUserManagementControlPanel(userService); - mainPanel.add(leaderboardAndMapViewer.getViewerWidget()); + mainPanel.add(mapViewer.getViewerWidget()); boolean showLeaderboard = getPerspectiveSettings().isShowLeaderboard() && isScreenLargeEnoughToInitiallyDisplayLeaderboard; setLeaderboardVisible(showLeaderboard); if (showChartMarkEditMediaButtonsAndVideo) { @@ -546,7 +556,19 @@ public class RaceBoardPanel * @param visible true if the leaderboard shall be open/visible */ public void setLeaderboardVisible(boolean visible) { - setComponentVisible(leaderboardAndMapViewer, leaderboardPanel, visible); + setComponentVisible(mapViewer, leaderboardPanel, visible); + } + + /** + * Sets the collapsable panel for the tagging open or close, if in CASCADE view mode.
+ * Displays or hides the tagging panel, if in ONESCREEN view mode.

+ * + * The race board should be completely rendered before this method is called, or a few exceptions could be thrown. + * + * @param visible true if the leaderboard shall be open/visible + */ + public void setTaggingPanelVisible(boolean visible) { + setComponentVisible(mapViewer, taggingPanel, visible); } /** @@ -558,11 +580,11 @@ public class RaceBoardPanel * @param visible true if the wind chart shall be open/visible */ public void setWindChartVisible(boolean visible) { - setComponentVisible(leaderboardAndMapViewer, windChart, visible); + setComponentVisible(mapViewer, windChart, visible); } public void showInWindChart(WindSource windprovider) { - setComponentVisible(leaderboardAndMapViewer, windChart, true); + setComponentVisible(mapViewer, windChart, true); windChart.showProvider(windprovider); } @@ -575,7 +597,7 @@ public class RaceBoardPanel * @param visible true if the competitor chart shall be open/visible */ public void setCompetitorChartVisible(boolean visible) { - setComponentVisible(leaderboardAndMapViewer, competitorChart, visible); + setComponentVisible(mapViewer, competitorChart, visible); } protected SailingServiceAsync getSailingService() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SideBySideComponentViewer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SideBySideComponentViewer.java index 4872431ba0d..f1977626c1f 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SideBySideComponentViewer.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SideBySideComponentViewer.java @@ -47,6 +47,7 @@ public class SideBySideComponentViewer implements UserStatusEventHandler { private static final int DEFAULT_SOUTH_SPLIT_PANEL_HEIGHT = 200; private final int MIN_LEADERBOARD_WIDTH = Math.min(432, Window.getClientWidth() - 40); // fallback value "432" works well for 505 and ESS + private final int MIN_TAGGING_WIDTH = Math.min(300, Window.getClientWidth() - 40); /** * Absolute Panel that informs its children about a resize @@ -63,9 +64,11 @@ public class SideBySideComponentViewer implements UserStatusEventHandler { } private Component leftComponent; + private final Component centerComponent; private final Component rightComponent; private final List> components; private final ScrollPanel leftScrollPanel; + private final ScrollPanel rightScrollPanel; private final StringMessages stringMessages; private final Button mediaSelectionButton; private final Button mediaManagementButton; @@ -77,13 +80,15 @@ public class SideBySideComponentViewer implements UserStatusEventHandler { private TouchSplitLayoutPanel splitLayoutPanel; - public SideBySideComponentViewer(final Component leftComponentP, final Component rightComponentP, - final MediaPlayerManagerComponent mediaPlayerManagerComponent, List> components, - final StringMessages stringMessages, UserService userService, EditMarkPassingsPanel markPassingsPanel, - EditMarkPositionPanel markPositionPanel, ManeuverTablePanel maneuverTablePanel) { + public SideBySideComponentViewer(final Component leftComponentP, final Component centerComponentP, + final Component rightComponentP, final MediaPlayerManagerComponent mediaPlayerManagerComponent, + List> components, final StringMessages stringMessages, UserService userService, + EditMarkPassingsPanel markPassingsPanel, EditMarkPositionPanel markPositionPanel, + ManeuverTablePanel maneuverTablePanel) { this.mediaPlayerManagerComponent = mediaPlayerManagerComponent; this.stringMessages = stringMessages; this.leftComponent = leftComponentP; + this.centerComponent = centerComponentP; this.rightComponent = rightComponentP; this.components = components; this.mediaSelectionButton = createMediaSelectionButton(mediaPlayerManagerComponent); @@ -130,6 +135,9 @@ public class SideBySideComponentViewer implements UserStatusEventHandler { this.leftScrollPanel = new ScrollPanel(); this.leftScrollPanel.add(leftComponentP.getEntryWidget()); this.leftScrollPanel.setTitle(leftComponentP.getEntryWidget().getTitle()); + this.rightScrollPanel = new ScrollPanel(); + this.rightScrollPanel.add(rightComponentP.getEntryWidget()); + this.rightScrollPanel.setTitle(rightComponentP.getEntryWidget().getTitle()); this.mainPanel = new LayoutPanel(); this.mainPanel.setSize("100%", "100%"); this.mainPanel.getElement().getStyle().setMarginTop(-12, Unit.PX); @@ -142,11 +150,14 @@ public class SideBySideComponentViewer implements UserStatusEventHandler { // initialize the leaderboard component splitLayoutPanel.insert(leftScrollPanel, leftComponent, Direction.WEST, MIN_LEADERBOARD_WIDTH); + + // initialize the tagging component + splitLayoutPanel.insert(rightScrollPanel, rightComponent, Direction.EAST, MIN_TAGGING_WIDTH); // create a panel that will contain the horizontal toggle buttons ResizableAbsolutePanel panelForMapAndHorizontalToggleButtons = new ResizableAbsolutePanel(); - panelForMapAndHorizontalToggleButtons.add(rightComponent.getEntryWidget()); - splitLayoutPanel.insert(panelForMapAndHorizontalToggleButtons, rightComponent, Direction.CENTER, 0); + panelForMapAndHorizontalToggleButtons.add(centerComponent.getEntryWidget()); + splitLayoutPanel.insert(panelForMapAndHorizontalToggleButtons, centerComponent, Direction.CENTER, 0); // add additional toggle buttons panel that currently only contains the video button List> additionalVerticalButtons = new ArrayList>(); @@ -239,16 +250,28 @@ public class SideBySideComponentViewer implements UserStatusEventHandler { * itself when it is not visible. */ public void forceLayout() { - if (!leftComponent.isVisible() && rightComponent.isVisible()) { + if (!leftComponent.isVisible() && centerComponent.isVisible()) { // the leaderboard is not visible, but the map is if (isWidgetInSplitPanel(leftScrollPanel)) { splitLayoutPanel.setWidgetVisibility(leftScrollPanel, leftComponent, /* hidden */true, MIN_LEADERBOARD_WIDTH); } - } else if (leftComponent.isVisible() && rightComponent.isVisible()) { + } else if (leftComponent.isVisible() && centerComponent.isVisible()) { // the leaderboard and the map are visible splitLayoutPanel.setWidgetVisibility(leftScrollPanel, leftComponent, /* hidden */false, MIN_LEADERBOARD_WIDTH); - } else if (!leftComponent.isVisible() && !rightComponent.isVisible()) { + } else if (!leftComponent.isVisible() && !centerComponent.isVisible()) { + } + + if (!rightComponent.isVisible() && centerComponent.isVisible()) { + // the tagging is not visible, but the map is + if (isWidgetInSplitPanel(rightScrollPanel)) { + splitLayoutPanel.setWidgetVisibility(rightScrollPanel, rightComponent, /* hidden */true, + MIN_TAGGING_WIDTH); + } + } else if (rightComponent.isVisible() && centerComponent.isVisible()) { + // the leaderboard and the map are visible + splitLayoutPanel.setWidgetVisibility(rightScrollPanel, rightComponent, /* hidden */false, MIN_TAGGING_WIDTH); + } else if (!rightComponent.isVisible() && !centerComponent.isVisible()) { } for (Component component : components) { @@ -331,6 +354,25 @@ public class SideBySideComponentViewer implements UserStatusEventHandler { } } + /** + * Shows/hides the text on right components toggle button by modifying CSS font-size property and adjust + * the dragger position by modifying CSS margin-top property. + * + * @param visible + * true to show the button text, false to hide it + */ + void setRightComponentToggleButtonTextVisibilityAndDraggerPosition(final boolean visible) { + Splitter rightScrollPanelSplitter = splitLayoutPanel.getAssociatedSplitter(rightScrollPanel); + if (rightScrollPanelSplitter != null) { + Style toggleButtonStyle = rightScrollPanelSplitter.getToggleButton().getElement().getStyle(); + if (visible) toggleButtonStyle.clearFontSize(); + else toggleButtonStyle.setFontSize(0, Unit.PX); + Style drapperStyle = rightScrollPanelSplitter.getDragger().getElement().getStyle(); + if (visible) drapperStyle.clearMarginTop(); + else drapperStyle.setMarginTop(-25, Unit.PX); + } + } + public void setLeftComponentToggleButtonVisible(boolean visible) { Splitter leftScrollPanelSplitter = splitLayoutPanel.getAssociatedSplitter(leftScrollPanel); if (leftScrollPanelSplitter != null) { @@ -338,7 +380,18 @@ public class SideBySideComponentViewer implements UserStatusEventHandler { } } + public void setRightComponentToggleButtonVisible(boolean visible) { + Splitter rightScrollPanelSplitter = splitLayoutPanel.getAssociatedSplitter(rightScrollPanel); + if (rightScrollPanelSplitter != null) { + rightScrollPanelSplitter.getToggleButton().setVisible(visible); + } + } + public ScrollPanel getLeftScrollPanel() { return leftScrollPanel; } + + public ScrollPanel getRightScrollPanel() { + return rightScrollPanel; + } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java new file mode 100644 index 00000000000..626e76a6bc8 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -0,0 +1,54 @@ +package com.sap.sailing.gwt.ui.raceboard; + +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.gwt.client.shared.components.Component; +import com.sap.sse.gwt.client.shared.components.ComponentWithoutSettings; +import com.sap.sse.gwt.client.shared.settings.ComponentContext; + +public class TaggingPanel extends ComponentWithoutSettings { + + private final Widget widget; + private final StringMessages stringMessages; + + public TaggingPanel(Widget widget, StringMessages stringMessages, Component parent, ComponentContext context) { + super(parent, context); + this.widget = widget; + this.stringMessages = stringMessages; + + widget.setTitle(stringMessages.tagging()); + widget.getElement().getStyle().setMargin(6, Unit.PX); + widget.getElement().getStyle().setMarginTop(10, Unit.PX); + } + + @Override + public String getId() { + return "TaggingPanel"; + } + + @Override + public String getLocalizedShortName() { + return stringMessages.tagging(); + } + + @Override + public Widget getEntryWidget() { + return widget; + } + + @Override + public boolean isVisible() { + return widget.isVisible(); + } + + @Override + public void setVisible(boolean visibility) { + widget.setVisible(visibility); + } + + @Override + public String getDependentCssClassName() { + return "tags"; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TouchSplitLayoutPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TouchSplitLayoutPanel.java index c8d4cb11d3f..f9a04b7f713 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TouchSplitLayoutPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TouchSplitLayoutPanel.java @@ -79,6 +79,7 @@ import com.sap.sse.gwt.client.shared.components.Component; *

    *
  • .gwt-SplitLayoutPanel { the panel itself }
  • *
  • .gwt-SplitLayoutPanel .gwt-SplitLayoutPanel-HDragger { horizontal dragger }
  • + *
  • .gwt-SplitLayoutPanel .gwt-SplitLayoutPanel-HDragger-Inverted { horizontal dragger }
  • *
  • .gwt-SplitLayoutPanel .gwt-SplitLayoutPanel-VDragger { vertical dragger }
  • *
* @@ -394,7 +395,11 @@ public class TouchSplitLayoutPanel extends DockLayoutPanel { super(target, associatedComponent, reverse); addStyleName("SplitLayoutPanel-Divider-Horizontal"); getDragger().getElement().getStyle().setPropertyPx("width", horizontalSplitterSize); - getDragger().setStyleName("gwt-SplitLayoutPanel-HDragger"); + if(!reverse) { + getDragger().setStyleName("gwt-SplitLayoutPanel-HDragger"); + } else { + getDragger().setStyleName("gwt-SplitLayoutPanel-HDragger-Inverted"); + } } @Override @@ -598,7 +603,8 @@ public class TouchSplitLayoutPanel extends DockLayoutPanel { HSplitter lastHorizontalSplitter = null; VSplitter lastVerticalSplitter = null; List allVerticalSplitters = new ArrayList(); - List allHorizontalSplitters = new ArrayList(); + List horizontalEastSplitters = new ArrayList(); + List horizontalWestSplitters = new ArrayList(); for (Widget widget : splitterChildren) { if (widget instanceof VSplitter) { allVerticalSplitters.add((VSplitter) widget); @@ -607,7 +613,12 @@ public class TouchSplitLayoutPanel extends DockLayoutPanel { lastVerticalSplitter = (VSplitter)widget; } else if (widget instanceof HSplitter) { lastHorizontalSplitter = (HSplitter) widget; - allHorizontalSplitters.add((HSplitter) widget); + LayoutData layoutData = (LayoutData) widget.getLayoutData(); + if(layoutData.direction == Direction.EAST) { + horizontalEastSplitters.add((HSplitter) widget); + } else if(layoutData.direction == Direction.WEST) { + horizontalWestSplitters.add((HSplitter) widget); + } } } if (lastVerticalSplitter != null) { @@ -620,9 +631,16 @@ public class TouchSplitLayoutPanel extends DockLayoutPanel { } ensureVerticalToggleButtonPosition(); if (lastHorizontalSplitter != null) { - Panel horizontalButtonsPanel = createToggleButtonPanel(allHorizontalSplitters, - "gwt-SplitLayoutPanel-EastToggleButton-Panel", "gwt-SplitLayoutPanel-EastToggleButton", cm, /* additional buttons and styles */ null); - panelForHorizontalButtons.add(horizontalButtonsPanel); + if(horizontalEastSplitters.size() > 0) { + Panel horizontalButtonsPanel = createToggleButtonPanel(horizontalEastSplitters, + "gwt-SplitLayoutPanel-WestToggleButton-Panel", "gwt-SplitLayoutPanel-WestToggleButton", cm, /* additional buttons and styles */ null); + panelForHorizontalButtons.add(horizontalButtonsPanel); + } + if(horizontalWestSplitters.size() > 0) { + Panel horizontalButtonsPanel = createToggleButtonPanel(horizontalWestSplitters, + "gwt-SplitLayoutPanel-EastToggleButton-Panel", "gwt-SplitLayoutPanel-EastToggleButton", cm, /* additional buttons and styles */ null); + panelForHorizontalButtons.add(horizontalButtonsPanel); + } lastHorizontalSplitter.setVisible(false); lastHorizontalSplitter.setDraggerVisible(false); } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/css/CommonControls.css b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/css/CommonControls.css index ba62f6e3b00..ff51c8b8c97 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/css/CommonControls.css +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/css/CommonControls.css @@ -167,49 +167,83 @@ body ::-webkit-scrollbar-track { top: 3px; } -.gwt-SplitLayoutPanel-EastToggleButton-Panel { +.gwt-SplitLayoutPanel-EastToggleButton-Panel, +.gwt-SplitLayoutPanel-WestToggleButton-Panel { position: absolute; bottom: -10px; } -.gwt-SplitLayoutPanel-EastToggleButton { - height: 40px; - background-color: white; - border: none; - -webkit-transform: rotate(-90deg); - -moz-transform: rotate(-90deg); - -o-transform: rotate(-90deg); - -ms-transform: rotate(-90deg); - transform: rotate(-90deg); - -webkit-transform-origin: 0 0; - -moz-transform-origin: 0 0; - -o-transform-origin: 0 0; - -ms-transform-origin: 0 0; - transform-origin: 0 0; - padding-right: 25px; - padding-left: 30px; - border-bottom: 1px solid #cecece; - border-right: 1px solid #cecece; - border-left: 1px solid #cecece; - border-bottom-right-radius: 10px; - border-bottom-left-radius: 10px; +.gwt-SplitLayoutPanel-WestToggleButton-Panel { + right: 0; } -.gwt-SplitLayoutPanel-EastToggleButton-Open { +.gwt-SplitLayoutPanel-EastToggleButton, +.gwt-SplitLayoutPanel-WestToggleButton { + height: 40px; + background-color: white; + border: none; + border-right: 1px solid #cecece; + border-left: 1px solid #cecece; +} + +.gwt-SplitLayoutPanel-EastToggleButton { + -webkit-transform-origin: 0 0; + -moz-transform-origin: 0 0; + -o-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + transform: rotate(-90deg); + border-bottom: 1px solid #cecece; + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; + padding-right: 25px; + padding-left: 30px; +} + +.gwt-SplitLayoutPanel-WestToggleButton { + position: absolute; + right: -1px; + bottom: 0; + -webkit-transform-origin: 100% 0; + -moz-transform-origin: 100% 0; + -o-transform-origin: 100% 0; + -ms-transform-origin: 100% 0; + transform-origin: 100% 0; + -webkit-transform: rotate(-90deg) translate(100%, -100%); + -moz-transform: rotate(-90deg) translate(100%, -100%); + -o-transform: rotate(-90deg) translate(100%, -100%); + -ms-transform: rotate(-90deg) translate(100%, -100%); + transform: rotate(-90deg) translate(100%, -100%); + border-top: 1px solid #cecece; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + padding-right: 25px; + padding-left: 30px; +} + +.gwt-SplitLayoutPanel-EastToggleButton-Open, +.gwt-SplitLayoutPanel-WestToggleButton-Closed { background: white url(images/arrows_top_black_small.png) 96% 50% no-repeat; } -.gwt-SplitLayoutPanel-EastToggleButton-Closed { +.gwt-SplitLayoutPanel-EastToggleButton-Closed, +.gwt-SplitLayoutPanel-WestToggleButton-Open { background: white url(images/arrows_bottom_black_small.png) 96% 50% no-repeat; } -.gwt-SplitLayoutPanel-EastToggleButton:hover { +.gwt-SplitLayoutPanel-EastToggleButton:hover, +.gwt-SplitLayoutPanel-WestToggleButton:hover { background-color: #ececec; } -.gwt-SplitLayoutPanel-EastToggleButton:focus { +.gwt-SplitLayoutPanel-EastToggleButton:focus, +.gwt-SplitLayoutPanel-WestToggleButton:focus { outline: 0 !important; } @@ -244,19 +278,32 @@ body ::-webkit-scrollbar-track { background-color: #ececec; } -.gwt-SplitLayoutPanel-HDragger { +.gwt-SplitLayoutPanel-HDragger, +.gwt-SplitLayoutPanel-HDragger-Inverted { position: absolute; - height: 60px !important; - width: 25px !important; - margin-left: 3px; - top: 40% !important; - background: #ffffff url(images/thumb_vertical.png) 70% 50% no-repeat; - border: 2px solid #cecece; - border-left: 0px; - cursor: col-resize; + height: 60px !important; + width: 25px !important; + margin-left: 3px; + top: 40% !important; + background: #ffffff url(images/thumb_vertical.png) 70% 50% no-repeat; + background-position: center; + border: 2px solid #cecece; + cursor: col-resize; + z-index: 1; +} + +.gwt-SplitLayoutPanel-HDragger { border-top-right-radius: 25px; border-bottom-right-radius: 25px; - z-index: 1; + border-left: 0; +} + +.gwt-SplitLayoutPanel-HDragger-Inverted { + border-top-left-radius: 25px; + border-bottom-left-radius: 25px; + border-right: 0; + /* margin-left needs to be (-1) * width */ + margin-left: -25px; } .SplitLayoutPanel-Divider-Horizontal { From 5fcfa6a135b6f20ae64b2e6654c00d8757198c31 Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 10 Jul 2018 10:49:15 +0200 Subject: [PATCH 023/292] return result instead of null --- .../sailing/domain/persistence/impl/MongoObjectFactoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index c589f23c665..8def4445e0e 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -1097,7 +1097,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { result.put(FieldNames.RACE_LOG_TAG.name(), event.getTag()); result.put(FieldNames.RACE_LOG_COMMENT.name(), event.getComment()); result.put(FieldNames.RACE_LOG_IMAGE_URL.name(), event.getImageURL().toString()); - return null; + return result; } public DBObject storeRaceLogUseCompetitorsFromRaceLogEvent(RaceLogUseCompetitorsFromRaceLogEvent event) { From b9a21503aec6dc5ee1d0ee6736581c9fc48230a2 Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 10 Jul 2018 10:50:08 +0200 Subject: [PATCH 024/292] Added access to Deserializer and added further visit method --- .../sap/sailing/gwt/ui/server/SailingServiceImpl.java | 11 +++++++++++ .../racelog/impl/RaceLogEventDeserializer.java | 11 +++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) 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 3eeba3fab02..fc52bd51d59 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 @@ -88,6 +88,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.AbortingFlagFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder; @@ -114,6 +115,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventI import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogSuppressedMarkPassingsEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogTagEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; @@ -7782,6 +7784,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } + @Override + public void visit(RaceLogTagEvent event) { + // TODO change body of method and check if it is okay D067890 + if (!dependentStartTime && isLatestPass(event)) { + raceLog.add(new RaceLogTagEventImpl(event.getTag(), event.getComment(), event.getImageURL(), event.getCreatedAt(), event.getLogicalTimePoint(), + event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId())); + } + } + private boolean isLatestPass(RaceLogEvent event) { return event.getPassId() == raceLogOfRaceToSlice.getCurrentPassId(); } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java index d3b7eb24e5b..83b46276d59 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java @@ -41,6 +41,7 @@ import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogStartPro import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogStartTimeEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogStartTrackingEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogSuppressedMarkPassingsEventSerializer; +import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogTagEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogUseCompetitorsFromRaceLogEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogWindFixEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.tracking.impl.SmartphoneUUIDJsonHandler; @@ -85,7 +86,8 @@ public class RaceLogEventDeserializer implements JsonDeserializer new RaceLogSuppressedMarkPassingsEventDeserializer(competitorDeserializer), new RaceLogStartOfTrackingEventDeserializer(competitorDeserializer), new RaceLogUseCompetitorsFromRaceLogEventDeserializer(competitorDeserializer), - new RaceLogEndOfTrackingEventDeserializer(competitorDeserializer)); + new RaceLogEndOfTrackingEventDeserializer(competitorDeserializer), + new RaceLogTagEventDeserializer(competitorDeserializer)); } protected final JsonDeserializer flagEventDeserializer; @@ -111,6 +113,7 @@ public class RaceLogEventDeserializer implements JsonDeserializer protected final JsonDeserializer startOfTrackingDeserializer; protected final JsonDeserializer endOfTrackingDeserializer; protected final JsonDeserializer useCompetitorsFromRaceLogDeserializer; + protected final JsonDeserializer tagEventDeserializer; public RaceLogEventDeserializer(JsonDeserializer flagEventDeserializer, JsonDeserializer startTimeEventDeserializer, @@ -134,7 +137,8 @@ public class RaceLogEventDeserializer implements JsonDeserializer JsonDeserializer suppressedMarkPassingsEventDeserializer, JsonDeserializer startOfTrackingEventDeserializer, JsonDeserializer useCompetitorsFromRaceLogDeserializer, - JsonDeserializer endOfTrackingEventDeserializer) { + JsonDeserializer endOfTrackingEventDeserializer, + JsonDeserializer tagEventDeserializer) { this.flagEventDeserializer = flagEventDeserializer; this.startTimeEventDeserializer = startTimeEventDeserializer; this.dependentStartTimeEventDeserializer = dependentStartTimeEventDeserializer; @@ -158,6 +162,7 @@ public class RaceLogEventDeserializer implements JsonDeserializer this.startOfTrackingDeserializer = startOfTrackingEventDeserializer; this.endOfTrackingDeserializer = endOfTrackingEventDeserializer; this.useCompetitorsFromRaceLogDeserializer = useCompetitorsFromRaceLogDeserializer; + this.tagEventDeserializer = tagEventDeserializer; } protected JsonDeserializer getDeserializer(JSONObject object) throws JsonDeserializationException { @@ -209,6 +214,8 @@ public class RaceLogEventDeserializer implements JsonDeserializer return endOfTrackingDeserializer; } else if (type.equals(RaceLogUseCompetitorsFromRaceLogEventSerializer.VALUE_CLASS)){ return endOfTrackingDeserializer; + } else if (type.equals(RaceLogTagEventSerializer.VALUE_CLASS)){ + return tagEventDeserializer; } throw new JsonDeserializationException(String.format("There is no deserializer defined for event type %s.", From ab006775039a4fb4778a2e53ecbd1c092c20a19e Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 10 Jul 2018 12:35:43 +0200 Subject: [PATCH 025/292] Updated wrong parameter --- .../racelog/impl/RaceLogTagEventDeserializer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java index f06f6e492ef..4e7a2250e45 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java @@ -36,7 +36,7 @@ public class RaceLogTagEventDeserializer extends BaseRaceLogEventDeserializer{ } catch (MalformedURLException e) { throw new JsonDeserializationException(); } - return new RaceLogTagEventImpl(tag, comment, url, timePoint, timePoint, author, id, passId); + return new RaceLogTagEventImpl(tag, comment, url, createdAt, timePoint, author, id, passId); } } From 897b8ecd859113508d3d56b43f4902d63d7e1e79 Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 10 Jul 2018 12:37:07 +0200 Subject: [PATCH 026/292] bug4104: Added second RaceLogTagEventImpl Constructor --- .../domain/abstractlog/race/impl/RaceLogTagEventImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index 5a7e88d7db9..e73cac5b6f7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -23,6 +23,10 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE comment = pComment; imageURL = pImageURL; } + + public RaceLogTagEventImpl(String pTag, String pComment, URL pImageURL, TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId) { + this(pTag, pComment, pImageURL, now(), logicalTimePoint, author, randId(), pPassId); + } @Override public String getTag() { From cf3d5108c8a8f3e58b8fe0176b15bc2ce0426c78 Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 10 Jul 2018 12:39:12 +0200 Subject: [PATCH 027/292] bug4104: added method to add RaceLogEvents for tags into RaceState --- .../domain/abstractlog/race/state/RaceState.java | 9 ++++++++- .../abstractlog/race/state/impl/RaceStateImpl.java | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java index 6df0c3f9ca0..f1358100c47 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.abstractlog.race.state; +import java.net.URL; + import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.RaceLog; @@ -194,7 +196,12 @@ public interface RaceState extends ReadonlyRaceState { * an already existing one. */ void setAdditionalScoringInformationEnabled(TimePoint creationTimePoint, boolean enable, AdditionalScoringInformationType informationType); - + + /* + * Adds a new tag to this race + */ + void setNewTag(TimePoint now, String tag, String comment, URL imageURL); + boolean isAdditionalScoringInformationEnabled(AdditionalScoringInformationType informationType); /** diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java index a20fc0ad4ea..bbb44297801 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.abstractlog.race.state.impl; +import java.net.URL; import java.util.Collections; import java.util.logging.Level; import java.util.logging.Logger; @@ -23,6 +24,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEvent import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogTagEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; @@ -216,6 +218,13 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { public void setWindFix(TimePoint timePoint, Wind wind, boolean isMagnetic) { raceLog.add(new RaceLogWindFixEventImpl(timePoint, author, raceLog.getCurrentPassId(), wind, isMagnetic)); } + + @Override + public void setNewTag(TimePoint timePoint, String tag, String comment, URL imageURL) { + // TODO check if this method is in the right place D067890 + raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, timePoint, author, raceLog.getCurrentPassId())); + + } @Override public void setAdditionalScoringInformationEnabled(TimePoint timePoint, boolean enable, AdditionalScoringInformationType informationType) { @@ -246,5 +255,4 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { public void forceUpdate() { super.update(); } - -} +} \ No newline at end of file From 9d317ff0b85741ba3d02b62253df82de42853d72 Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 10 Jul 2018 15:10:39 +0200 Subject: [PATCH 028/292] bug 4104: DocumentObjectFactory should be able to loadRaceLogTagEvents --- .../impl/DomainObjectFactoryImpl.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) 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 749cf0d754d..5fe209e096b 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 @@ -62,6 +62,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultImpl; @@ -84,6 +85,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventI import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogSuppressedMarkPassingsEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogTagEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl; import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; @@ -1589,7 +1591,9 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } else if (eventClass.equals(RaceLogUseCompetitorsFromRaceLogEvent.class.getSimpleName())) { resultEvent = loadRaceLogUseCompetitorsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else { + } else if (eventClass.equals(RaceLogTagEvent.class.getSimpleName())) { + resultEvent = loadRaceLogTagEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + }else { throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass)); } return new Pair<>(resultEvent, dbObjectForUpdate); @@ -1764,6 +1768,22 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { .valueOf(dbObject.get(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name()).toString()); return new RaceLogStartProcedureChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, type); } + + private RaceLogEvent loadRaceLogTagEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + String tag = (String) dbObject.get(FieldNames.RACE_LOG_TAG.name()); + String comment = (String) dbObject.get(FieldNames.RACE_LOG_COMMENT.name()); + String urlPath = (String) dbObject.get(FieldNames.RACE_LOG_IMAGE_URL.name()); + URL url; + try { + url = new URL(urlPath); + } catch (MalformedURLException e) { + // TODO update this method D067890 + url = null; + } + return new RaceLogTagEventImpl(tag, comment, url, createdAt, logicalTimePoint, author, id, passId); + } private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, From 902be52661af2d15fd9684d6b07847fc732d05b1 Mon Sep 17 00:00:00 2001 From: D067890 Date: Thu, 12 Jul 2018 15:43:47 +0200 Subject: [PATCH 029/292] bug4104: changed type of imageURL to String --- .../persistence/impl/DomainObjectFactoryImpl.java | 9 +-------- .../persistence/impl/MongoObjectFactoryImpl.java | 2 +- .../domain/abstractlog/race/RaceLogTagEvent.java | 4 +--- .../abstractlog/race/impl/RaceLogTagEventImpl.java | 10 ++++------ .../domain/abstractlog/race/state/RaceState.java | 2 +- .../abstractlog/race/state/impl/RaceStateImpl.java | 2 +- .../racelog/impl/RaceLogTagEventDeserializer.java | 12 ++---------- .../racelog/impl/RaceLogTagEventSerializer.java | 2 +- 8 files changed, 12 insertions(+), 31 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 5fe209e096b..cbb826daf02 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 @@ -1775,14 +1775,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String tag = (String) dbObject.get(FieldNames.RACE_LOG_TAG.name()); String comment = (String) dbObject.get(FieldNames.RACE_LOG_COMMENT.name()); String urlPath = (String) dbObject.get(FieldNames.RACE_LOG_IMAGE_URL.name()); - URL url; - try { - url = new URL(urlPath); - } catch (MalformedURLException e) { - // TODO update this method D067890 - url = null; - } - return new RaceLogTagEventImpl(tag, comment, url, createdAt, logicalTimePoint, author, id, passId); + return new RaceLogTagEventImpl(tag, comment, urlPath, createdAt, logicalTimePoint, author, id, passId); } private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 8def4445e0e..4cd17bc6297 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -1096,7 +1096,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { result.put(FieldNames.RACE_LOG_TAG.name(), event.getTag()); result.put(FieldNames.RACE_LOG_COMMENT.name(), event.getComment()); - result.put(FieldNames.RACE_LOG_IMAGE_URL.name(), event.getImageURL().toString()); + result.put(FieldNames.RACE_LOG_IMAGE_URL.name(), event.getImageURL()); return result; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java index dcff00983eb..3b01156067c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java @@ -1,7 +1,5 @@ package com.sap.sailing.domain.abstractlog.race; -import java.net.URL; - import com.sap.sailing.domain.abstractlog.Revokable; public interface RaceLogTagEvent extends RaceLogEvent, Revokable { @@ -15,6 +13,6 @@ public interface RaceLogTagEvent extends RaceLogEvent, Revokable { /* * Image URL in RaceLogTagEvents is optional */ - URL getImageURL(); + String getImageURL(); } \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index e73cac5b6f7..7de38ae2af7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -1,7 +1,6 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.net.URL; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; @@ -12,11 +11,10 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE private static final long serialVersionUID = 7213518902555323432L; - private String tag, comment; - private URL imageURL; + private String tag, comment, imageURL; - public RaceLogTagEventImpl(String pTag, String pComment, URL pImageURL,TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, + public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL,TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, int pPassId) { super(createdAt, logicalTimePoint, author, pId, pPassId); tag = pTag; @@ -24,7 +22,7 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE imageURL = pImageURL; } - public RaceLogTagEventImpl(String pTag, String pComment, URL pImageURL, TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId) { + public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId) { this(pTag, pComment, pImageURL, now(), logicalTimePoint, author, randId(), pPassId); } @@ -44,7 +42,7 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE } @Override - public URL getImageURL() { + public String getImageURL() { return imageURL; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java index f1358100c47..f4af18643e5 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java @@ -200,7 +200,7 @@ public interface RaceState extends ReadonlyRaceState { /* * Adds a new tag to this race */ - void setNewTag(TimePoint now, String tag, String comment, URL imageURL); + void setNewTag(TimePoint now, String tag, String comment, String imageURL); boolean isAdditionalScoringInformationEnabled(AdditionalScoringInformationType informationType); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java index bbb44297801..feff8c7bdfd 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java @@ -220,7 +220,7 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { } @Override - public void setNewTag(TimePoint timePoint, String tag, String comment, URL imageURL) { + public void setNewTag(TimePoint timePoint, String tag, String comment, String imageURL) { // TODO check if this method is in the right place D067890 raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, timePoint, author, raceLog.getCurrentPassId())); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java index 4e7a2250e45..f4db0477b5b 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java @@ -1,8 +1,6 @@ package com.sap.sailing.server.gateway.deserialization.racelog.impl; import java.io.Serializable; -import java.net.MalformedURLException; -import java.net.URL; import java.util.List; import org.json.simple.JSONObject; @@ -29,14 +27,8 @@ public class RaceLogTagEventDeserializer extends BaseRaceLogEventDeserializer{ throws JsonDeserializationException { String tag = object.get(RaceLogTagEventSerializer.FIELD_TAG).toString(); String comment = object.get(RaceLogTagEventSerializer.FIELD_COMMENT).toString(); - String urlPath = object.get(RaceLogTagEventSerializer.FIELD_URL).toString(); - URL url; - try { - url = new URL(urlPath); - } catch (MalformedURLException e) { - throw new JsonDeserializationException(); - } - return new RaceLogTagEventImpl(tag, comment, url, createdAt, timePoint, author, id, passId); + String imageURL = object.get(RaceLogTagEventSerializer.FIELD_URL).toString(); + return new RaceLogTagEventImpl(tag, comment, imageURL, createdAt, timePoint, author, id, passId); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java index 03183760d93..22c41f54c10 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java @@ -29,7 +29,7 @@ public class RaceLogTagEventSerializer extends BaseRaceLogEventSerializer{ JSONObject result = super.serialize(tagEvent); result.put(FIELD_TAG, tagEvent.getTag()); result.put(FIELD_COMMENT, tagEvent.getComment()); - result.put(FIELD_URL, tagEvent.getImageURL().toString()); + result.put(FIELD_URL, tagEvent.getImageURL()); return result; } } \ No newline at end of file From 76903cf54f3c2289b0c916f3f34f23a75540b0de Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Fri, 13 Jul 2018 09:43:08 +0200 Subject: [PATCH 030/292] Bug 4104: Added DTO class for tags. --- .../com/sap/sailing/gwt/ui/shared/TagDTO.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java new file mode 100644 index 00000000000..74054884e6a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java @@ -0,0 +1,61 @@ +package com.sap.sailing.gwt.ui.shared; + +import com.sap.sse.common.TimePoint; +import com.sap.sse.gwt.client.media.ImageDTO; + +public class TagDTO { + String tag; + String comment; + ImageDTO image; + String username; + TimePoint createdAt; + TimePoint raceTimepoint; + + public TagDTO(String tag, String comment, ImageDTO image, String username, TimePoint createdAt, TimePoint raceTimepoint) { + this.tag = tag; + this.comment = comment; + this.image = image; + this.username = username; + this.createdAt = createdAt; + this.raceTimepoint = raceTimepoint; + } + + // Missing comment as it is optional + public TagDTO(String tag, ImageDTO image, String username, TimePoint createdAt, TimePoint raceTimepoint) { + this(tag, null, image, username, createdAt, raceTimepoint); + } + + // Missing image as it is optional + public TagDTO(String tag, String comment, String username, TimePoint createdAt, TimePoint raceTimepoint) { + this(tag, comment, null, username, createdAt, raceTimepoint); + } + + // Missing image & comment as they are optional + public TagDTO(String tag, String username, TimePoint createdAt, TimePoint raceTimepoint) { + this(tag, null, null, username, createdAt, raceTimepoint); + } + + public String getTag() { + return tag; + } + + public String getComment() { + return comment; + } + + public ImageDTO getImage() { + return image; + } + + public String getUsername() { + return username; + } + + public TimePoint getCreatedAt() { + return createdAt; + } + + public TimePoint getRaceTimepoint() { + return raceTimepoint; + } +} From de3ff8b5c89a1328bfa99f5520a62c50c39a3db6 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Fri, 13 Jul 2018 10:19:32 +0200 Subject: [PATCH 031/292] Revert "Bug 4104: Added DTO class for tags." This reverts commit 76903cf54f3c2289b0c916f3f34f23a75540b0de. --- .../com/sap/sailing/gwt/ui/shared/TagDTO.java | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java deleted file mode 100644 index 74054884e6a..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.sap.sailing.gwt.ui.shared; - -import com.sap.sse.common.TimePoint; -import com.sap.sse.gwt.client.media.ImageDTO; - -public class TagDTO { - String tag; - String comment; - ImageDTO image; - String username; - TimePoint createdAt; - TimePoint raceTimepoint; - - public TagDTO(String tag, String comment, ImageDTO image, String username, TimePoint createdAt, TimePoint raceTimepoint) { - this.tag = tag; - this.comment = comment; - this.image = image; - this.username = username; - this.createdAt = createdAt; - this.raceTimepoint = raceTimepoint; - } - - // Missing comment as it is optional - public TagDTO(String tag, ImageDTO image, String username, TimePoint createdAt, TimePoint raceTimepoint) { - this(tag, null, image, username, createdAt, raceTimepoint); - } - - // Missing image as it is optional - public TagDTO(String tag, String comment, String username, TimePoint createdAt, TimePoint raceTimepoint) { - this(tag, comment, null, username, createdAt, raceTimepoint); - } - - // Missing image & comment as they are optional - public TagDTO(String tag, String username, TimePoint createdAt, TimePoint raceTimepoint) { - this(tag, null, null, username, createdAt, raceTimepoint); - } - - public String getTag() { - return tag; - } - - public String getComment() { - return comment; - } - - public ImageDTO getImage() { - return image; - } - - public String getUsername() { - return username; - } - - public TimePoint getCreatedAt() { - return createdAt; - } - - public TimePoint getRaceTimepoint() { - return raceTimepoint; - } -} From 13107bba7b7267c1a09f209a067ee7c936c84577 Mon Sep 17 00:00:00 2001 From: D067890 Date: Fri, 13 Jul 2018 10:53:36 +0200 Subject: [PATCH 032/292] bug4104: RaceLogTagEvents now contain a user name --- .../impl/DomainObjectFactoryImpl.java | 3 ++- .../domain/persistence/impl/FieldNames.java | 2 +- .../abstractlog/race/RaceLogTagEvent.java | 5 +++-- .../race/impl/RaceLogTagEventImpl.java | 19 ++++++++++--------- .../abstractlog/race/state/RaceState.java | 2 +- .../race/state/impl/RaceStateImpl.java | 4 ++-- .../gwt/ui/server/SailingServiceImpl.java | 2 +- .../impl/RaceLogTagEventDeserializer.java | 3 ++- .../impl/RaceLogTagEventSerializer.java | 3 ++- 9 files changed, 24 insertions(+), 19 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 cbb826daf02..bfff2bb15dd 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 @@ -1773,9 +1773,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { String tag = (String) dbObject.get(FieldNames.RACE_LOG_TAG.name()); + String userName = (String) dbObject.get(FieldNames.RACE_LOG_USER_NAME.name()); String comment = (String) dbObject.get(FieldNames.RACE_LOG_COMMENT.name()); String urlPath = (String) dbObject.get(FieldNames.RACE_LOG_IMAGE_URL.name()); - return new RaceLogTagEventImpl(tag, comment, urlPath, createdAt, logicalTimePoint, author, id, passId); + return new RaceLogTagEventImpl(tag, userName, comment, urlPath, createdAt, logicalTimePoint, author, id, passId); } private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java index 35bebcb9fa6..a6d64fc0e74 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java @@ -105,7 +105,7 @@ public enum FieldNames { RACE_LOG_REVOKED_EVENT_SHORT_INFO, RACE_LOG_REVOKED_REASON, RACE_LOG_DEVICE_MAPPING_EVENT_ID, RACE_LOG_CLOSING_TIMEPOINT, TIMEPOINT_OF_FIXED_MARKPASSING, INDEX_OF_PASSED_WAYPOINT,INDEX_OF_FIRST_SUPPRESSED_WAYPOINT, MARK, RACE_LOG_COMPETITOR_ID, RACE_LOG_BOAT_ID, RACE_LOG_DEPDENDENT_ON_FLEET, RACE_LOG_DEPDENDENT_ON_RACECOLUMN, RACE_LOG_DEPDENDENT_ON_REGATTALIKE, - RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS, RACE_LOG_TAG, RACE_LOG_COMMENT, RACE_LOG_IMAGE_URL, + RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS, RACE_LOG_TAG, RACE_LOG_COMMENT, RACE_LOG_IMAGE_URL, RACE_LOG_USER_NAME, /** @deprecated Replaced by {@link #REGATTA_LOG_FROM}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_FROM, /** @deprecated Replaced by {@link #REGATTA_LOG_TO}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_TO, /** @deprecated Replaced by a regatta log entry with type {@link #REGATTA_LOG_MARK} */ @Deprecated RACE_LOG_MARK, diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java index 3b01156067c..68e98077412 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java @@ -6,6 +6,8 @@ public interface RaceLogTagEvent extends RaceLogEvent, Revokable { String getTag(); + String getUserName(); + /* * Comment is optional */ @@ -13,6 +15,5 @@ public interface RaceLogTagEvent extends RaceLogEvent, Revokable { /* * Image URL in RaceLogTagEvents is optional */ - String getImageURL(); - + String getImageURL(); } \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index 7de38ae2af7..54a13f235ec 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -11,19 +11,20 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE private static final long serialVersionUID = 7213518902555323432L; - private String tag, comment, imageURL; + private String tag, comment, imageURL, userName; - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL,TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, + public RaceLogTagEventImpl(String pTag, String pUserName, String pComment, String pImageURL,TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, int pPassId) { super(createdAt, logicalTimePoint, author, pId, pPassId); tag = pTag; comment = pComment; imageURL = pImageURL; + userName = pUserName; } - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId) { - this(pTag, pComment, pImageURL, now(), logicalTimePoint, author, randId(), pPassId); + public RaceLogTagEventImpl(String pTag, String pUserName, String pComment, String pImageURL, TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId) { + this(pTag, pUserName, pComment, pImageURL, now(), logicalTimePoint, author, randId(), pPassId); } @Override @@ -36,11 +37,6 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE return comment; } - @Override - public TimePoint getTimePoint() { - return getLogicalTimePoint(); - } - @Override public String getImageURL() { return imageURL; @@ -50,4 +46,9 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); } + + @Override + public String getUserName() { + return userName; + } } \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java index f4af18643e5..7e1388791a4 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java @@ -200,7 +200,7 @@ public interface RaceState extends ReadonlyRaceState { /* * Adds a new tag to this race */ - void setNewTag(TimePoint now, String tag, String comment, String imageURL); + void setNewTag(TimePoint now, String tag, String userName, String comment, String imageURL); boolean isAdditionalScoringInformationEnabled(AdditionalScoringInformationType informationType); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java index feff8c7bdfd..7745d015b32 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java @@ -220,9 +220,9 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { } @Override - public void setNewTag(TimePoint timePoint, String tag, String comment, String imageURL) { + public void setNewTag(TimePoint timePoint, String tag, String userName, String comment, String imageURL) { // TODO check if this method is in the right place D067890 - raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, timePoint, author, raceLog.getCurrentPassId())); + raceLog.add(new RaceLogTagEventImpl(tag, userName, comment, imageURL, timePoint, author, raceLog.getCurrentPassId())); } 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 fc52bd51d59..73108dccbdd 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 @@ -7788,7 +7788,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public void visit(RaceLogTagEvent event) { // TODO change body of method and check if it is okay D067890 if (!dependentStartTime && isLatestPass(event)) { - raceLog.add(new RaceLogTagEventImpl(event.getTag(), event.getComment(), event.getImageURL(), event.getCreatedAt(), event.getLogicalTimePoint(), + raceLog.add(new RaceLogTagEventImpl(event.getTag(), event.getUserName(), event.getComment(), event.getImageURL(), event.getCreatedAt(), event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId())); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java index f4db0477b5b..ff34d9313af 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java @@ -26,9 +26,10 @@ public class RaceLogTagEventDeserializer extends BaseRaceLogEventDeserializer{ AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { String tag = object.get(RaceLogTagEventSerializer.FIELD_TAG).toString(); + String username = object.get(RaceLogTagEventSerializer.FIELD_USER_NAME).toString(); String comment = object.get(RaceLogTagEventSerializer.FIELD_COMMENT).toString(); String imageURL = object.get(RaceLogTagEventSerializer.FIELD_URL).toString(); - return new RaceLogTagEventImpl(tag, comment, imageURL, createdAt, timePoint, author, id, passId); + return new RaceLogTagEventImpl(tag, username, comment, imageURL, createdAt, timePoint, author, id, passId); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java index 22c41f54c10..c99ef61240b 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java @@ -11,6 +11,7 @@ public class RaceLogTagEventSerializer extends BaseRaceLogEventSerializer{ public static final String VALUE_CLASS = RaceLogTagEvent.class.getSimpleName(); public static final String FIELD_TAG = "tag"; + public static final String FIELD_USER_NAME = "user_name"; public static final String FIELD_COMMENT = "comment"; public static final String FIELD_URL = "url"; @@ -28,7 +29,7 @@ public class RaceLogTagEventSerializer extends BaseRaceLogEventSerializer{ RaceLogTagEvent tagEvent = (RaceLogTagEvent) object; JSONObject result = super.serialize(tagEvent); result.put(FIELD_TAG, tagEvent.getTag()); - result.put(FIELD_COMMENT, tagEvent.getComment()); + result.put(FIELD_USER_NAME, tagEvent.getUserName()); result.put(FIELD_URL, tagEvent.getImageURL()); return result; } From 78c9ba3132aed23a0afac1cc6462ced164610649 Mon Sep 17 00:00:00 2001 From: D067890 Date: Fri, 13 Jul 2018 11:06:02 +0200 Subject: [PATCH 033/292] bug4104: updated if condition --- .../com/sap/sailing/gwt/ui/server/SailingServiceImpl.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/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 73108dccbdd..103c9eb7d0d 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 @@ -7786,8 +7786,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public void visit(RaceLogTagEvent event) { - // TODO change body of method and check if it is okay D067890 - if (!dependentStartTime && isLatestPass(event)) { + // TODO check if if condition is correct D067890 + if (hasStartTime && isLatestPass(event)) { raceLog.add(new RaceLogTagEventImpl(event.getTag(), event.getUserName(), event.getComment(), event.getImageURL(), event.getCreatedAt(), event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId())); } From 487d2f2577346de159cd000c98dedbfd6ac707fc Mon Sep 17 00:00:00 2001 From: D067890 Date: Fri, 13 Jul 2018 11:07:56 +0200 Subject: [PATCH 034/292] bug4104: added unit test for RaceLogTagEventSerializer --- .../test/racelog/RaceLogEventSerializerTest.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index 64091171d93..de7f46d7867 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -23,6 +23,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogTagEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; @@ -253,7 +254,10 @@ public class RaceLogEventSerializerTest { } @Test - public void testTagSerializer() { - // TODO add test for Serializer for RaceLogTagEvents D067890 + public void testTagSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = new RaceLogTagEventImpl("", "", "", "", MillisecondsTimePoint.now(), author, 0); + serializer.serialize(event); + verify(tagEventSerializer).serialize(event); } } From 9623e59b92aad87ce56faafa18f45d81b4892b97 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Fri, 13 Jul 2018 15:02:10 +0200 Subject: [PATCH 035/292] Bug 4104: Added button to add new tags to race log. Tags get displayed with a CellTable, only new added tags will be displayed yet. --- .../abstractlog/race/state/RaceState.java | 2 - .../race/state/impl/RaceStateImpl.java | 1 - .../sailing/gwt/ui/client/SailingService.java | 2 + .../gwt/ui/client/SailingServiceAsync.java | 2 + .../gwt/ui/raceboard/RaceBoardPanel.java | 3 +- .../gwt/ui/raceboard/TaggingPanel.java | 218 ++++++++++++++++-- .../gwt/ui/server/SailingServiceImpl.java | 6 + 7 files changed, 217 insertions(+), 17 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java index 7e1388791a4..073b5d7e6e1 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceState.java @@ -1,7 +1,5 @@ package com.sap.sailing.domain.abstractlog.race.state; -import java.net.URL; - import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.RaceLog; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java index 7745d015b32..13ae6a9c831 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java @@ -1,6 +1,5 @@ package com.sap.sailing.domain.abstractlog.race.state.impl; -import java.net.URL; import java.util.Collections; import java.util.logging.Level; import java.util.logging.Logger; 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 b45952f0b1e..b3524e201b6 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 @@ -782,4 +782,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS * Checks if the given race is currently in state tracking or loading. */ Boolean checkIfRaceIsTracking(RegattaAndRaceIdentifier race); + + void addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, String imageURL, String username, TimePoint raceTimepoint); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index 2c5324fc800..be274ad622f 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -989,4 +989,6 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan * @see SailingService#checkIfRaceIsTracking(RegattaAndRaceIdentifier) */ void checkIfRaceIsTracking(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback asyncCallback); + + void addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, String imageURL, String username, TimePoint raceTimepoint, AsyncCallback asyncCallback); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java index f14ec7a6a5f..20afad19ca1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java @@ -302,7 +302,7 @@ public class RaceBoardPanel addChildComponent(raceMap); // add panel for tagging functionality, hidden by default - taggingPanel = new TaggingPanel(new Label("Hello World!"), stringMessages, parent, componentContext); + taggingPanel = new TaggingPanel(parent, componentContext, stringMessages, sailingService, userService); addChildComponent(taggingPanel); taggingPanel.setVisible(true); taggingPanel.setVisible(false); @@ -673,6 +673,7 @@ public class RaceBoardPanel regattaAndRaceTimeInformationHeader.add(regattaNameAnchor); regattaAndRaceTimeInformationHeader.add(raceTimeLabel); currentRaceHasBeenSelectedOnce = true; + taggingPanel.updateRace(leaderboardName, raceColumn, fleet); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 626e76a6bc8..e6487b3c05f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -1,25 +1,217 @@ package com.sap.sailing.gwt.ui.raceboard; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.google.gwt.core.shared.GWT; import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.cellview.client.CellTable; +import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.view.client.ListDataProvider; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.RaceColumnDTO; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.gwt.client.Notification; +import com.sap.sse.gwt.client.Notification.NotificationType; import com.sap.sse.gwt.client.shared.components.Component; import com.sap.sse.gwt.client.shared.components.ComponentWithoutSettings; import com.sap.sse.gwt.client.shared.settings.ComponentContext; +import com.sap.sse.security.ui.client.UserService; public class TaggingPanel extends ComponentWithoutSettings { - - private final Widget widget; + + private final Panel panel; + private final Panel buttonsPanel; + private final CellTable content; + private final List
(created by {4} at {5})
{6}") + SafeHtml cellRemovable(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, + SafeHtml author, SafeHtml createdAt, SafeHtml content); + + @Template("
{3}
") + SafeHtml contentWithCommentWithImage(String styleTagImage, String styleTagComment, SafeUri imageURL, SafeHtml comment); - @Template("
{4}
(created by {5} at {6})
{7}
") - SafeHtml cellWithCommentWithoutImage(String styleTag, String styleTagHeading, String styleTagCreated, - String styleTagComment, SafeHtml tag, SafeHtml author, SafeHtml createdAt, SafeHtml comment); + @Template("
{1}
") + SafeHtml contentWithCommentWithoutImage(String styleTagComment, SafeHtml comment); - @Template("
{4}
(created by {5} at {6})
") - SafeHtml cellWithoutCommentWithImage(String styleTag, String styleTagHeading, String styleTagCreated, - String styleTagImage, SafeHtml tag, SafeHtml author, SafeHtml createdAt, SafeUri imageURL); - - @Template("
{3}
(created by {4} at {5})
") - SafeHtml cellWithoutCommentWithoutImage(String styleTag, String styleTagHeading, String styleTagCreated, - SafeHtml tag, SafeHtml author, SafeHtml createdAt); + @Template("
") + SafeHtml contentWithoutCommentWithImage(String styleTagImage, SafeUri imageURL); } private class TagCell extends AbstractCell { @@ -118,6 +127,10 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI private final TagPanelResources tagPanelRes = GWT.create(TagPanelResources.class); private final TagPanelStyle tagPanelStyle = tagPanelRes.style(); + public TagCell() { + super("click"); + } + @Override public void render(Context context, TagDTO tag, SafeHtmlBuilder htmlBuilder) { if (tag == null) { @@ -131,29 +144,42 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI SafeHtml safeComment = SafeHtmlUtils.fromString(tag.getComment()); SafeUri trustedImageURL = UriUtils.fromTrustedString(tag.getImageURL()); - SafeHtml cell = null; - if (tag.getComment().length() <= 0 && tag.getImageURL().length() <= 0) { - // no comment & no image - cell = tagCellTemplate.cellWithoutCommentWithoutImage(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), safeTag, safeAuthor, safeCreatedAt); - } else if (tag.getComment().length() > 0 && tag.getImageURL().length() <= 0) { - // comment & no image - cell = tagCellTemplate.cellWithCommentWithoutImage(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), tagPanelStyle.tagComment(), safeTag, safeAuthor, safeCreatedAt, - safeComment); + SafeHtml content = SafeHtmlUtils.EMPTY_SAFE_HTML; + if (tag.getComment().length() > 0 && tag.getImageURL().length() <= 0) { + content = tagCellTemplate.contentWithCommentWithoutImage(tagPanelStyle.tagComment(), safeComment); } else if (tag.getComment().length() <= 0 && tag.getImageURL().length() > 0) { - // no comment & image - cell = tagCellTemplate.cellWithoutCommentWithImage(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), tagPanelStyle.tagImage(), safeTag, safeAuthor, safeCreatedAt, - trustedImageURL); + content = tagCellTemplate.contentWithoutCommentWithImage(tagPanelStyle.tagImage(), trustedImageURL); + } else if (tag.getComment().length() > 0 && tag.getImageURL().length() > 0) { + content = tagCellTemplate.contentWithCommentWithImage(tagPanelStyle.tagImage(), + tagPanelStyle.tagComment(), trustedImageURL, safeComment); + } + + SafeHtml cell; + if (userService.getCurrentUser() != null + && tag.getUsername().equals(userService.getCurrentUser().getName())) { + cell = tagCellTemplate.cellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), + tagPanelStyle.tagCreated(), safeTag, safeAuthor, safeCreatedAt, content); } else { - // comment & image cell = tagCellTemplate.cell(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), tagPanelStyle.tagCreated(), - tagPanelStyle.tagImage(), tagPanelStyle.tagComment(), safeTag, safeAuthor, safeCreatedAt, - trustedImageURL, safeComment); + safeTag, safeAuthor, safeCreatedAt, content); } htmlBuilder.append(cell); } + + @Override + public void onBrowserEvent(Context context, Element parent, TagDTO tag, NativeEvent event, + ValueUpdater valueUpdater) { + super.onBrowserEvent(context, parent, tag, event, valueUpdater); + if ("click".equals(event.getType())) { + EventTarget eventTarget = event.getEventTarget(); + if (!Element.is(eventTarget)) { + return; + } + if (parent.getElementsByTagName("button").getItem(0).isOrHasChild(Element.as(eventTarget))) { + removeTagFromRaceLog(tag); + } + } + } } private class TagButton extends Button { @@ -167,7 +193,7 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - addNewTag(getTag(), getComment(), getImageURL()); + addTagToRaceLog(getTag(), getComment(), getImageURL()); } }); } @@ -188,8 +214,9 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI private class TagCreationPanel extends VerticalPanel { protected Button createTagFromTextBoxes, editCustomTagButtons; protected Panel customButtonsPanel = new FlowPanel(); - private final TagCreationInputPanel inputPanel; - public TagCreationPanel(StringMessages stringMessages) { + private final TagCreationInputPanel inputPanel; + + public TagCreationPanel(StringMessages stringMessages) { inputPanel = new TagCreationInputPanel(stringMessages); add(inputPanel); @@ -197,8 +224,8 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI createTagFromTextBoxes.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - if (isAuthorized()) { - addNewTag(inputPanel.getTagValue(), inputPanel.getCommentValue(), + if (isAuthorizedAndRaceLogAvailable()) { + addTagToRaceLog(inputPanel.getTagValue(), inputPanel.getCommentValue(), inputPanel.getImageURLValue()); } } @@ -209,7 +236,7 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI editCustomTagButtons.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - if (isAuthorized()) { + if (isAuthorizedAndRaceLogAvailable()) { new EditCustomTagsDialog(customButtonsPanel).show(); updateButtons(); } @@ -227,13 +254,14 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI }); } } - - private class EditCustomTagsDialog extends DataEntryDialog>{ + + private class EditCustomTagsDialog extends DataEntryDialog> { private final Panel customButtonsPanel; - + public EditCustomTagsDialog(Panel customButtonsPanel) { - super(stringMessages.tagEditCustomTagsButtonDialogHeader(), "", stringMessages.ok(), stringMessages.cancel(), null, null); - this.customButtonsPanel = customButtonsPanel; + super(stringMessages.tagEditCustomTagsButtonDialogHeader(), "", stringMessages.ok(), + stringMessages.cancel(), null, null); + this.customButtonsPanel = customButtonsPanel; } @Override @@ -274,7 +302,7 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI customButtonsPanel.remove(button); customTagButtonsTable.setRowData(customTagButtons); } - }); + }); customTagButtonsTable.addColumn(tagColumn, stringMessages.tagLabelTag()); customTagButtonsTable.addColumn(commentColumn, stringMessages.tagLabelComment()); customTagButtonsTable.addColumn(imageURLColumn, stringMessages.tagLabelImageURL()); @@ -282,16 +310,17 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI customTagButtonsTable.setRowData(customTagButtons); mainPanel.add(rightPanel); mainPanel.add(customTagButtonsTable); - + TagCreationInputPanel inputPanel = new TagCreationInputPanel(stringMessages); rightPanel.add(inputPanel); - + Button addCustomTagButton = new Button(stringMessages.tagAddCustomTagButton()); addCustomTagButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (inputPanel.getTagValue().length() > 0) { - TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), inputPanel.getImageURLValue(), inputPanel.getCommentValue()); + TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), + inputPanel.getImageURLValue(), inputPanel.getCommentValue()); customTagButtons.add(tagButton); customButtonsPanel.add(tagButton); customTagButtonsTable.setRowData(customTagButtons); @@ -354,6 +383,7 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI this.stringMessages = stringMessages; this.sailingService = sailingService; this.userService = userService; + userService.addUserStatusEventHandler(this); this.timer = timer; this.raceTimesInfoProvider = raceTimesInfoProvider; raceTimesInfoProvider.addRaceTimesInfoProviderListener(this); @@ -386,6 +416,7 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI @Override public void onSelectionChange(SelectionChangeEvent event) { // set time slider to corresponding position + GWT.log(event.getSource().toString()); timer.setTime(tagSelectionModel.getSelectedObject().getRaceTimepoint().asMillis()); } }); @@ -410,8 +441,8 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI } } - private void addNewTag(String tag, String comment, String imageURL) { - if (isAuthorized()) { + private void addTagToRaceLog(String tag, String comment, String imageURL) { + if (isAuthorizedAndRaceLogAvailable()) { if (tag.length() > 0) { sailingService.addTagToRaceLog(leaderboardName, raceColumn.getName(), fleet.getName(), tag, comment, imageURL, new MillisecondsTimePoint(timer.getTime()), new AsyncCallback() { @@ -432,7 +463,24 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI } - private boolean isAuthorized() { + private void removeTagFromRaceLog(TagDTO tag) { + sailingService.removeTagFromRaceLog(leaderboardName, raceColumn.getName(), fleet.getName(), tag, + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + Notification.notify("Could not remove tag!", NotificationType.ERROR); + } + + @Override + public void onSuccess(SuccessInfo result) { + Notification.notify("Removed tag successfully", NotificationType.SUCCESS); + } + }); + tagListProvider.getAllTags().remove(tag); + updateContent(); + } + + private boolean isAuthorizedAndRaceLogAvailable() { if (leaderboardName == null || raceColumn == null || fleet == null) { Notification.notify(stringMessages.tagNotAdded(), NotificationType.ERROR); return false; @@ -480,6 +528,11 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI }); } + @Override + public void onUserStatusChange(UserDTO user, boolean preAuthenticated) { + updateContent(); + } + @Override public String getId() { return "TaggingPanel"; @@ -509,4 +562,5 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI public String getDependentCssClassName() { return "tags"; } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css index f0183e1225d..127d497ea13 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css @@ -25,6 +25,12 @@ b { font-weight: bold; } +.tagHeading button { + float: right; + border: none; + background: transparent; +} + .tagImage { text-align: center; margin: 0 -5px; 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 865886f1302..faa6e990022 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 @@ -575,6 +575,7 @@ import com.sap.sse.replication.ReplicationService; import com.sap.sse.replication.impl.ReplicaDescriptor; import com.sap.sse.security.SecurityService; import com.sap.sse.security.SessionUtils; +import com.sap.sse.security.ui.shared.SuccessInfo; import com.sap.sse.shared.media.ImageDescriptor; import com.sap.sse.shared.media.MediaUtils; import com.sap.sse.shared.media.VideoDescriptor; @@ -6053,6 +6054,26 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, raceTimepoint, getService().getServerAuthor(), raceLog.getCurrentPassId())); } + + @Override + public SuccessInfo removeTagFromRaceLog(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) { + SuccessInfo successInfo = new SuccessInfo(true, null, null, null); + RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); + TagFinder tagFinder = new TagFinder(raceLog, tag.getCreatedAt().minus(1), tag.getCreatedAt().plus(1)); + List foundTagEvents = tagFinder.analyze(); + for (RaceLogTagEvent tagEvent : foundTagEvents) { + if (tagEvent.getTag().equals(tag.getTag()) + && tagEvent.getComment().equals(tag.getComment()) + && tagEvent.getImageURL().equals(tag.getImageURL())) { + try { + raceLog.revokeEvent(tagEvent.getAuthor(), tagEvent); + } catch (NotRevokableException e) { + successInfo = new SuccessInfo(false, "Could not remove tag! " + e.getMessage(), null, null); + } + } + } + return successInfo; + } /** * @param trackedRace From 7f6dc1e4414a1c1dde2dbe0bceafa12b999460e3 Mon Sep 17 00:00:00 2001 From: D067890 Date: Fri, 10 Aug 2018 08:56:36 +0200 Subject: [PATCH 102/292] bug4104: Added header to edit tag button dialog --- .../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 ++- .../java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java | 6 +++--- 4 files changed, 8 insertions(+), 5 deletions(-) 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 10a550fc143..bb9ebae8c0a 100755 --- 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 @@ -2119,4 +2119,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String tagNotSpecified(); String tagFilterDialogHeader(); String tagEditFilter(); + String tagEditCustomTagButton(); } 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 d5b076f5b27..c6660dfc902 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 @@ -2112,4 +2112,5 @@ tagEditCustomTagsButtonDialogHeader=Edit tag buttons tagAddCustomTagButton=Add tag button tagNotSpecified=Tag must not be empty tagFilterDialogHeader=Tag filters -tagEditFilter=Edit filter \ No newline at end of file +tagEditFilter=Edit filter +tagEditCustomTagButton=Edit tag button \ 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 4869e143497..faea6d35304 100755 --- 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 @@ -2107,4 +2107,5 @@ tagEditCustomTagsButtonDialogHeader=Bearbeite Tag Buttons tagAddCustomTagButton=Füge Tag Button hinzu tagNotSpecified=Tag muss spezifiziert sein, gebe bitte einen Wert für Tag an tagFilterDialogHeader=Tag Filters -tagEditFilter=Bearbeite Filter \ No newline at end of file +tagEditFilter=Bearbeite Filter +tagEditCustomTagButton=Bearbeite Tag Button \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 531b71fe4af..27be14fc4d3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -286,7 +286,7 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI customTagButtonsTable.setRowData(customTagButtons); } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { - new EditTagButtonDialog(button, customTagButtonsTable).show(); + new EditTagButtonDialog(button, customTagButtonsTable, stringMessages).show(); } } }); @@ -344,8 +344,8 @@ public class TaggingPanel extends ComponentWithoutSettings implements RaceTimesI private final VerticalPanel mainPanel; private final HorizontalPanel saveAndClosePanel; - public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable) { - + public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, StringMessages stringMessages) { + setText(stringMessages.tagEditCustomTagButton()); mainPanel = new VerticalPanel(); inputPanel = new TagCreationInputPanel(stringMessages); From c4989f3d2438e69a9a7ead7c7143865319035261 Mon Sep 17 00:00:00 2001 From: D067890 Date: Fri, 10 Aug 2018 10:13:24 +0200 Subject: [PATCH 103/292] bug4104: Moved ressource --- .../EditTagButtonsImagesBarCell.java | 28 ------------------- .../gwt/ui/raceboard/RaceBoardResources.java | 4 --- .../gwt/ui/raceboard/TaggingPanel.java | 26 +++++++++++++++++ 3 files changed, 26 insertions(+), 32 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EditTagButtonsImagesBarCell.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EditTagButtonsImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EditTagButtonsImagesBarCell.java deleted file mode 100644 index e419bde91cd..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EditTagButtonsImagesBarCell.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sap.sailing.gwt.ui.raceboard; - -import java.util.Arrays; - -import com.google.gwt.core.client.GWT; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.client.shared.controls.ImagesBarCell; -import com.sap.sse.gwt.client.IconResources; - -public class EditTagButtonsImagesBarCell extends ImagesBarCell { - public static final String ACTION_REMOVE = "ACTION_REMOVE"; - public static final String ACTION_EDIT = "ACTION_EDIT"; - private static RaceBoardResources resources = GWT.create(RaceBoardResources.class); - private final StringMessages stringMessages; - - public EditTagButtonsImagesBarCell(StringMessages stringMessages) { - super(); - this.stringMessages = stringMessages; - } - - - @Override - protected Iterable getImageSpecs() { - return Arrays.asList( - new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); - } -} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardResources.java index b77acefc17a..d59a7e30f18 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardResources.java @@ -1,7 +1,6 @@ package com.sap.sailing.gwt.ui.raceboard; import com.google.gwt.core.client.GWT; -import com.google.gwt.resources.client.ImageResource; import com.sap.sse.gwt.common.CommonSharedResources; import com.sap.sse.security.ui.authentication.generic.resource.AuthenticationResources; @@ -15,9 +14,6 @@ public interface RaceBoardResources extends CommonSharedResources, Authenticatio @Source({CommonSharedResources.MEDIA, "raceboard-media.gss"}) RaceBoardMediaCss mediaCss(); - //TODO image is stored in wrong folder - @Source("com/sap/sailing/gwt/ui/client/images/edit.png") - ImageResource editIcon(); public interface RaceBoardMainCss extends CommonMainCss { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index b1aec26e885..44486433878 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -1,6 +1,7 @@ package com.sap.sailing.gwt.ui.raceboard; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; @@ -16,6 +17,7 @@ import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; +import com.google.gwt.resources.client.ImageResource; import com.google.gwt.safehtml.client.SafeHtmlTemplates; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlBuilder; @@ -48,12 +50,14 @@ import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.TagListProvider; +import com.sap.sailing.gwt.ui.client.shared.controls.ImagesBarCell; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.raceboard.TaggingPanel.TagPanelResources.TagPanelStyle; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.TagDTO; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.Notification; import com.sap.sse.gwt.client.Notification.NotificationType; import com.sap.sse.gwt.client.player.Timer; @@ -70,6 +74,10 @@ public class TaggingPanel extends ComponentWithoutSettings public interface TagPanelResources extends ClientBundle { public static final TagPanelResources INSTANCE = GWT.create(TagPanelResources.class); + + //TODO image is stored in wrong folder + @Source("com/sap/sailing/gwt/ui/client/images/edit.png") + ImageResource editIcon(); @Source("tagging-panel.css") public TagPanelStyle style(); @@ -180,6 +188,24 @@ public class TaggingPanel extends ComponentWithoutSettings } } } + + private class EditTagButtonsImagesBarCell extends ImagesBarCell { + public static final String ACTION_REMOVE = "ACTION_REMOVE"; + public static final String ACTION_EDIT = "ACTION_EDIT"; + private final StringMessages stringMessages; + + public EditTagButtonsImagesBarCell(StringMessages stringMessages) { + this.stringMessages = stringMessages; + } + + + @Override + protected Iterable getImageSpecs() { + return Arrays.asList( + new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(TagPanelResources.INSTANCE.editIcon())), + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); + } + } private class TagButton extends Button { private String tag, imageURL, comment; From 7d5dac4a037c8a41e6dae9045d42f881ca6239de Mon Sep 17 00:00:00 2001 From: D067890 Date: Fri, 10 Aug 2018 11:01:43 +0200 Subject: [PATCH 104/292] bug4104: Use sample css for dialogs --- .../sailing/gwt/ui/raceboard/TaggingPanel.java | 17 ++++++++++++++++- .../gwt/ui/raceboard/tagging-buttondialog.css | 8 ++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-buttondialog.css diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 44486433878..733ea5cf7c3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -91,7 +91,18 @@ public class TaggingPanel extends ComponentWithoutSettings String tagImage(); } } + + public interface TagButtonDialogResources extends ClientBundle { + public static final TagButtonDialogResources INSTANCE = GWT.create(TagButtonDialogResources.class); + @Source("tagging-buttondialog.css") + public TagButtonDialogStyle style(); + + public interface TagButtonDialogStyle extends CssResource { + String button(); + } + } + public interface CellListResources extends CellList.Resources { public static final CellListResources INSTANCE = GWT.create(CellListResources.class); @@ -107,7 +118,8 @@ public class TaggingPanel extends ComponentWithoutSettings String cellListSelectedItem(); String cellListKeyboardSelectedItem(); } - } + } + public interface TagCellTemplate extends SafeHtmlTemplates { @Template("
{3}
(created by {4} at {5})
{6}
") @@ -304,6 +316,7 @@ public class TaggingPanel extends ComponentWithoutSettings private final Button addCustomTagButton; public EditCustomTagButtonsDialog(Panel customButtonsPanel) { + TagButtonDialogResources.INSTANCE.style().ensureInjected(); setText(stringMessages.tagEditCustomTagsButtonDialogHeader()); mainPanel = new VerticalPanel(); @@ -369,6 +382,7 @@ public class TaggingPanel extends ComponentWithoutSettings }); closeButton = new Button(stringMessages.close()); + closeButton.setStyleName(TagButtonDialogResources.INSTANCE.style().button()); //closeButton.getElement().getStyle().setMargin(3, Unit.PX); closeButton.addClickHandler(new ClickHandler() { @@ -398,6 +412,7 @@ public class TaggingPanel extends ComponentWithoutSettings private final HorizontalPanel saveAndClosePanel; public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, StringMessages stringMessages) { + TagButtonDialogResources.INSTANCE.style().ensureInjected(); setText(stringMessages.tagEditCustomTagButton()); mainPanel = new VerticalPanel(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-buttondialog.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-buttondialog.css new file mode 100644 index 00000000000..6f4d9ff53e5 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-buttondialog.css @@ -0,0 +1,8 @@ +b { + font-weight: bold; +} + +.button { + color: blue; +} + From 6541d1b7a48b59f3d9d3a0fb7405ecdf48811867 Mon Sep 17 00:00:00 2001 From: D067890 Date: Fri, 10 Aug 2018 12:37:01 +0200 Subject: [PATCH 105/292] bug4104: Tag Filter Panel now uses own CSS File --- .../gwt/ui/raceboard/TagFilterPanel.java | 51 +++++++- .../gwt/ui/raceboard/tagging-filter.css | 117 ++++++++++++++++++ 2 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java index 05258f4f337..5073d827029 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java @@ -1,5 +1,6 @@ package com.sap.sailing.gwt.ui.raceboard; +import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyUpEvent; @@ -7,6 +8,9 @@ import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONParser; import com.google.gwt.json.client.JSONValue; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.CssResource; +import com.google.gwt.resources.client.ImageResource; import com.google.gwt.storage.client.Storage; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; @@ -18,8 +22,7 @@ import com.sap.sailing.gwt.ui.client.shared.filter.FilterWithUI; import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSets; import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsDialog; import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsJsonDeSerializer; -import com.sap.sailing.gwt.ui.leaderboard.CompetitorFilterResources; -import com.sap.sailing.gwt.ui.leaderboard.CompetitorFilterResources.CompetitorFilterCss; +import com.sap.sailing.gwt.ui.raceboard.TagFilterPanel.TagFilterResources.TagFilterCss; import com.sap.sailing.gwt.ui.shared.TagDTO; import com.sap.sse.common.filter.FilterSet; import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; @@ -30,10 +33,50 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; * */ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWithUI { + + public interface TagFilterResources extends ClientBundle { + public static final TagFilterResources INSTANCE = GWT.create(TagFilterResources.class); + + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Clear.png") + ImageResource clearButton(); + + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_CompetitorsFilter_INACTIVE.png") + ImageResource filterInactiveButton(); + + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_CompetitorsFilter_ACTIVE.png") + ImageResource filterActiveButton(); + + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Search.png") + ImageResource searchButton(); + + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Settings.png") + ImageResource settingsButton(); + + @Source("tagging-filter.css") + TagFilterCss css(); + + public interface TagFilterCss extends CssResource { + String button(); + String hiddenButton(); + String clearButton(); + String searchButton(); + String settingsButton(); + String filterButton(); + String tagFilterContainer(); + String searchBox(); + String searchInput(); + String filterInactiveButtonBackgroundImage(); + String filterActiveButtonBackgroundImage(); + String clearButtonBackgroundImage(); + String searchButtonBackgroundImage(); + String settingsButtonBackgroundImage(); + } + + } private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailingAnalytics.raceBoard.tagsFilterSets"; - private final static CompetitorFilterCss css = CompetitorFilterResources.INSTANCE.css(); + private final static TagFilterCss css = TagFilterResources.INSTANCE.css(); private final TextBox searchTextBox; private final Button clearTextBoxButton; private final Button filterSettingsButton; @@ -48,7 +91,7 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit css.ensureInjected(); this.stringMessages = stringMessages; this.tagProvider = tagProvider; - this.setStyleName(css.competitorFilterContainer()); + this.setStyleName(css.tagFilterContainer()); TagsFilterSets loadedTagsFilterSets = loadTagsFilterSets(); if (loadedTagsFilterSets != null) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css new file mode 100644 index 00000000000..534106fb7c8 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css @@ -0,0 +1,117 @@ +.tagFilterContainer { + max-width: 425px; + width: 100%; + height: 2.25em; + background-color: #FFFFFF; + margin-left: 0px; + margin-right: 0px; + margin-top: 5px; + font-size: 1rem; + position: relative; + overflow: hidden; + border: none; + outline: 0; +} + +.searchBox { + border: 1px solid #ccc; + background-color: #eaeaea; + border-radius: 4px; + margin-right: 6em; +} + +.searchInput { + font-size: .933333333333333em; + height: 2.142857142857143em; + width: 70%; + border: none; + background-color: #eaeaea; + padding: 0; + margin-left: 2.4em; + margin-right: 0px; + margin-bottom: 1px; + outline: 0 !important; +} + +.button { + position: absolute; + top: .4em; + width: 2em; + height: 2em; + background-repeat: no-repeat; + background-position: center; + border: none; + -webkit-border-radius: 4px; + border-radius: 4px; + text-indent: -9999em; + -webkit-transition: background-color .2s; + -moz-transition: background-color .2s; + -o-transition: background-color .2s; + -ms-transition: background-color .2s; + transition: background-color .2s; + cursor: pointer; +} + +.button:focus, .button:hover { + background-color: #e2e2e2; +} + +.clearButton { + right: 7.3em; + top: 0.2em; +} + +.settingsButton { + right: 2.4em; + top: 0.2em; +} + +.filterButton { + right: 4.4em; + top: 0.2em; +} + +.searchButton { + top: 0.2em; + left: 0.2em; + opacity: 0.3; +} + +.hiddenButton { + display: none; +} + +@sprite .clearButtonBackgroundImage { + gwt-image: "clearButton"; + width: 2em; + height: 2em; + background-size: contain; +} + +@sprite .filterInactiveButtonBackgroundImage { + gwt-image: "filterInactiveButton"; + width: 2em; + height: 2em; + background-size: contain; +} + +@sprite .filterActiveButtonBackgroundImage { + gwt-image: "filterActiveButton"; + width: 2em; + height: 2em; + background-size: contain; +} + +@sprite .searchButtonBackgroundImage { + gwt-image: "searchButton"; + width: 2em; + height: 2em; + background-size: contain; +} + +@sprite .settingsButtonBackgroundImage { + gwt-image: "settingsButton"; + width: 2em; + height: 2em; + background-size: contain; +} \ No newline at end of file From ef8ad0f0a6a7490fc18e2e11c724fe95abec80fe Mon Sep 17 00:00:00 2001 From: D067890 Date: Fri, 10 Aug 2018 13:17:47 +0200 Subject: [PATCH 106/292] bug4104: Buttons are now centered properly --- .../gwt/ui/raceboard/TaggingPanel.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 733ea5cf7c3..702d3f79837 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -8,6 +8,7 @@ import java.util.Map; import com.google.gwt.cell.client.AbstractCell; import com.google.gwt.cell.client.FieldUpdater; import com.google.gwt.cell.client.ValueUpdater; +import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.shared.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.EventTarget; @@ -291,7 +292,15 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onClick(ClickEvent event) { if (isAuthorizedAndRaceLogAvailable()) { - new EditCustomTagButtonsDialog(customButtonsPanel).show(); + EditCustomTagButtonsDialog editCustomTagButtonsDialog = new EditCustomTagButtonsDialog(customButtonsPanel); + + //scheduler is used because otherwise DialogBox would not be centered properly + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + public void execute() { + editCustomTagButtonsDialog.show(); + editCustomTagButtonsDialog.center(); + } + }); updateButtons(); } } @@ -316,6 +325,7 @@ public class TaggingPanel extends ComponentWithoutSettings private final Button addCustomTagButton; public EditCustomTagButtonsDialog(Panel customButtonsPanel) { + setGlassEnabled(true); TagButtonDialogResources.INSTANCE.style().ensureInjected(); setText(stringMessages.tagEditCustomTagsButtonDialogHeader()); @@ -352,7 +362,15 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtonsTable.setRowData(customTagButtons); } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { - new EditTagButtonDialog(button, customTagButtonsTable, stringMessages).show(); + EditTagButtonDialog editCustomTagButtonDialog = new EditTagButtonDialog(button, customTagButtonsTable, stringMessages); + //scheduler is used because otherwise DialogBox would not be centered properly + + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + public void execute() { + editCustomTagButtonDialog.show(); + editCustomTagButtonDialog.center(); + } + }); } } }); @@ -383,7 +401,6 @@ public class TaggingPanel extends ComponentWithoutSettings closeButton = new Button(stringMessages.close()); closeButton.setStyleName(TagButtonDialogResources.INSTANCE.style().button()); - //closeButton.getElement().getStyle().setMargin(3, Unit.PX); closeButton.addClickHandler(new ClickHandler() { @Override @@ -397,7 +414,7 @@ public class TaggingPanel extends ComponentWithoutSettings mainPanel.add(addCustomTagButton); mainPanel.add(closeButton); - setWidget(mainPanel); + setWidget(mainPanel); } private void hideDialog() { From fccaff7d0313a9fc63c294097a23d5e220e2b44a Mon Sep 17 00:00:00 2001 From: D067890 Date: Fri, 10 Aug 2018 13:30:38 +0200 Subject: [PATCH 107/292] bug4104: comment texts of input panel are not resizeable anymore --- .../com/sap/sailing/gwt/ui/raceboard/TagCreationInputPanel.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/raceboard/TagCreationInputPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagCreationInputPanel.java index ce1da78ce10..8bb272b6f3c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagCreationInputPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagCreationInputPanel.java @@ -24,8 +24,8 @@ public class TagCreationInputPanel extends VerticalPanel{ urlTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); mainPanel.add(urlTextBox); - //resize must be set to none by css commentTextBox = new TextArea(); + commentTextBox.getElement().getStyle().setProperty("resize", "none"); commentTextBox.setWidth("100%"); commentTextBox.setVisibleLines(4); commentTextBox.setTitle(stringMessages.tagLabelComment()); From 0de2991c1716b428750ea9fc91bb9a7bf15c7f64 Mon Sep 17 00:00:00 2001 From: D067890 Date: Fri, 10 Aug 2018 17:11:00 +0200 Subject: [PATCH 108/292] bug4104: Updated UI of Tag Panel --- .../ui/raceboard/TagCreationInputPanel.java | 67 ----------- .../gwt/ui/raceboard/TaggingPanel.java | 113 +++++++++++++++--- .../gwt/ui/raceboard/tagging-buttondialog.css | 8 -- .../gwt/ui/raceboard/tagging-panel.css | 56 +++++++++ 4 files changed, 151 insertions(+), 93 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagCreationInputPanel.java delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-buttondialog.css diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagCreationInputPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagCreationInputPanel.java deleted file mode 100644 index 8bb272b6f3c..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagCreationInputPanel.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.sap.sailing.gwt.ui.raceboard; - -import com.google.gwt.user.client.ui.TextArea; -import com.google.gwt.user.client.ui.TextBox; -import com.google.gwt.user.client.ui.VerticalPanel; -import com.sap.sailing.gwt.ui.client.StringMessages; - -public class TagCreationInputPanel extends VerticalPanel{ - private TextBox tagTextBox, urlTextBox; - private TextArea commentTextBox; - - public TagCreationInputPanel(StringMessages stringMessages) { - VerticalPanel mainPanel = new VerticalPanel(); - - tagTextBox = new TextBox(); - tagTextBox.setWidth("100%"); - tagTextBox.setTitle(stringMessages.tagLabelTag()); - tagTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelTag()); - mainPanel.add(tagTextBox); - - urlTextBox = new TextBox(); - urlTextBox.setWidth("100%"); - urlTextBox.setTitle(stringMessages.tagLabelImageURL()); - urlTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); - mainPanel.add(urlTextBox); - - commentTextBox = new TextArea(); - commentTextBox.getElement().getStyle().setProperty("resize", "none"); - commentTextBox.setWidth("100%"); - commentTextBox.setVisibleLines(4); - commentTextBox.setTitle(stringMessages.tagLabelComment()); - commentTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment()); - mainPanel.add(commentTextBox); - add(mainPanel); - - } - - public String getTagValue() { - return tagTextBox.getValue(); - } - - public String getCommentValue() { - return commentTextBox.getValue(); - } - - public String getImageURLValue() { - return urlTextBox.getValue(); - } - - public void setTagValue(String tag) { - tagTextBox.setValue(tag); - } - - public void setCommentValue(String comment) { - commentTextBox.setValue(comment); - } - - public void setImageURLValue(String imageURL) { - urlTextBox.setValue(imageURL); - } - - public void clearAllValues() { - tagTextBox.setText(""); - urlTextBox.setText(""); - commentTextBox.setText(""); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 702d3f79837..4d80057f215 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -37,6 +37,8 @@ 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.ScrollPanel; +import com.google.gwt.user.client.ui.TextArea; +import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.SelectionChangeEvent; @@ -90,17 +92,14 @@ public class TaggingPanel extends ComponentWithoutSettings String tagCreated(); String tagComment(); String tagImage(); - } - } - - public interface TagButtonDialogResources extends ClientBundle { - public static final TagButtonDialogResources INSTANCE = GWT.create(TagButtonDialogResources.class); - - @Source("tagging-buttondialog.css") - public TagButtonDialogStyle style(); - - public interface TagButtonDialogStyle extends CssResource { + String button(); + String footerButton(); + String tagButtonTable(); + String inputPanelTag(); + String inputPanelComment(); + String inputPanelImageURL(); + String footerPanel(); } } @@ -228,6 +227,7 @@ public class TaggingPanel extends ComponentWithoutSettings this.tag = tag; this.imageURL = imageURL; this.comment = comment; + setStyleName(TagPanelResources.INSTANCE.style().button()); addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -265,16 +265,22 @@ public class TaggingPanel extends ComponentWithoutSettings private class TagCreationPanel extends VerticalPanel { private final Panel customButtonsPanel; + private final Panel standardButtonsPanel; + private final TagCreationInputPanel inputPanel; - public TagCreationPanel(StringMessages stringMessages) { - TagCreationInputPanel inputPanel = new TagCreationInputPanel(stringMessages); - Panel standardButtonsPanel = new FlowPanel(); + public TagCreationPanel(StringMessages stringMessages) { + setWidth("100%"); + inputPanel = new TagCreationInputPanel(stringMessages); + standardButtonsPanel = new FlowPanel(); + standardButtonsPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); customButtonsPanel = new FlowPanel(); + customButtonsPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); add(inputPanel); add(standardButtonsPanel); add(customButtonsPanel); Button createTagFromTextBoxes = new Button(stringMessages.tagAddButton()); + createTagFromTextBoxes.setStyleName(TagPanelResources.INSTANCE.style().button()); createTagFromTextBoxes.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -288,6 +294,7 @@ public class TaggingPanel extends ComponentWithoutSettings standardButtonsPanel.add(createTagFromTextBoxes); Button editCustomTagButtons = new Button(stringMessages.tagEditCustomTagButtons()); + editCustomTagButtons.setStyleName(TagPanelResources.INSTANCE.style().button()); editCustomTagButtons.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -316,6 +323,72 @@ public class TaggingPanel extends ComponentWithoutSettings } } + + public class TagCreationInputPanel extends VerticalPanel{ + private TextBox tagTextBox, urlTextBox; + private TextArea commentTextBox; + + public TagCreationInputPanel(StringMessages stringMessages) { + setWidth("100%"); + VerticalPanel mainPanel = new VerticalPanel(); + mainPanel.setWidth("100%"); + + tagTextBox = new TextBox(); + tagTextBox.setWidth("100%"); + tagTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelTag()); + tagTextBox.setTitle(stringMessages.tagLabelTag()); + tagTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelTag()); + mainPanel.add(tagTextBox); + + urlTextBox = new TextBox(); + urlTextBox.setWidth("100%"); + urlTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelImageURL()); + urlTextBox.setTitle(stringMessages.tagLabelImageURL()); + urlTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); + mainPanel.add(urlTextBox); + + commentTextBox = new TextArea(); + commentTextBox.setWidth("100%"); + commentTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelComment()); + commentTextBox.setVisibleLines(4); + commentTextBox.setTitle(stringMessages.tagLabelComment()); + commentTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment()); + mainPanel.add(commentTextBox); + add(mainPanel); + + } + + public String getTagValue() { + return tagTextBox.getValue(); + } + + public String getCommentValue() { + return commentTextBox.getValue(); + } + + public String getImageURLValue() { + return urlTextBox.getValue(); + } + + public void setTagValue(String tag) { + tagTextBox.setValue(tag); + } + + public void setCommentValue(String comment) { + commentTextBox.setValue(comment); + } + + public void setImageURLValue(String imageURL) { + urlTextBox.setValue(imageURL); + } + + public void clearAllValues() { + tagTextBox.setText(""); + urlTextBox.setText(""); + commentTextBox.setText(""); + } + } + private class EditCustomTagButtonsDialog extends DialogBox{ private final Button closeButton; @@ -326,12 +399,13 @@ public class TaggingPanel extends ComponentWithoutSettings public EditCustomTagButtonsDialog(Panel customButtonsPanel) { setGlassEnabled(true); - TagButtonDialogResources.INSTANCE.style().ensureInjected(); setText(stringMessages.tagEditCustomTagsButtonDialogHeader()); mainPanel = new VerticalPanel(); + mainPanel.setWidth("100px"); customTagButtonsTable = new CellTable(); + customTagButtonsTable.setStyleName(TagPanelResources.INSTANCE.style().tagButtonTable()); TextColumn tagColumn = new TextColumn() { @Override public String getValue(TagButton button) { @@ -384,6 +458,7 @@ public class TaggingPanel extends ComponentWithoutSettings inputPanel = new TagCreationInputPanel(stringMessages); addCustomTagButton = new Button(stringMessages.tagAddCustomTagButton()); + addCustomTagButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); addCustomTagButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -400,7 +475,7 @@ public class TaggingPanel extends ComponentWithoutSettings }); closeButton = new Button(stringMessages.close()); - closeButton.setStyleName(TagButtonDialogResources.INSTANCE.style().button()); + closeButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); closeButton.addClickHandler(new ClickHandler() { @Override @@ -429,7 +504,6 @@ public class TaggingPanel extends ComponentWithoutSettings private final HorizontalPanel saveAndClosePanel; public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, StringMessages stringMessages) { - TagButtonDialogResources.INSTANCE.style().ensureInjected(); setText(stringMessages.tagEditCustomTagButton()); mainPanel = new VerticalPanel(); @@ -439,6 +513,7 @@ public class TaggingPanel extends ComponentWithoutSettings inputPanel.setImageURLValue(tagButton.getImageURL()); saveButton = new Button("save"); + saveButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); saveButton.addClickHandler(new ClickHandler() { @Override @@ -452,7 +527,8 @@ public class TaggingPanel extends ComponentWithoutSettings }); - cancelButton = new Button(stringMessages.cancel()); + cancelButton = new Button(stringMessages.cancel()); + cancelButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); cancelButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -460,7 +536,8 @@ public class TaggingPanel extends ComponentWithoutSettings } }); - saveAndClosePanel = new HorizontalPanel(); + saveAndClosePanel = new HorizontalPanel(); + saveAndClosePanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); saveAndClosePanel.add(saveButton); saveAndClosePanel.add(cancelButton); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-buttondialog.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-buttondialog.css deleted file mode 100644 index 6f4d9ff53e5..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-buttondialog.css +++ /dev/null @@ -1,8 +0,0 @@ -b { - font-weight: bold; -} - -.button { - color: blue; -} - diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css index 127d497ea13..84edb7da168 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css @@ -51,4 +51,60 @@ b { .tagComment { font-size: 85%; +} + + +.button { + background-color: #fff; + border: 1px solid #cecece; + margin-left: 5px; + margin-bottom: 5px; + padding: 4px 4px; + border-radius: 4px; + cursor: pointer; +} + +.footerButton { + background-color: #fff; + border: 1px solid #cecece; + margin-left: 5px; + margin-bottom: 5px; + padding: 4px 4px; + border-radius: 4px; + cursor: pointer; + float: right; +} + +.footerPanel { + float: right; +} + +.tagButtonTable { + margin-top: 5px; + margin-bottom: -1px; + border-radius: 4px 4px 4px 4px; + border: 1px solid #cecece; + padding: 2px; +} + +.inputPanelTag { + margin-top: 5px; + margin-bottom: -1px; + border-radius: 4px 4px 0px 0px; + border: 1px solid #cecece; + padding: 2px; +} + +.inputPanelImageURL { + border: 1px solid #cecece; + padding: 2px; +} + +.inputPanelComment { + padding: 2px; + border: 1px solid #cecece; + margin-top: -1px; + resize: none; + margin-bottom: 5px; + border-radius: 0px 0px 4px 4px; } \ No newline at end of file From 0f19b955e100fd7880d9e7638bc809cf1005fb72 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Mon, 13 Aug 2018 11:06:22 +0200 Subject: [PATCH 109/292] Bug 4104: Added information to display in AdminConsole regarding tag events. --- .../domain/abstractlog/race/impl/RaceLogTagEventImpl.java | 5 +++++ .../com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index 267c1beee60..76df8659711 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -56,4 +56,9 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); } + + @Override + public String getShortInfo() { + return "tag=" + tag + ", comment=" + comment; + } } \ No newline at end of file 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 faa6e990022..3f7755a3b7e 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 @@ -6066,7 +6066,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S && tagEvent.getComment().equals(tag.getComment()) && tagEvent.getImageURL().equals(tag.getImageURL())) { try { - raceLog.revokeEvent(tagEvent.getAuthor(), tagEvent); + raceLog.revokeEvent(tagEvent.getAuthor(), tagEvent, "Revoked"); } catch (NotRevokableException e) { successInfo = new SuccessInfo(false, "Could not remove tag! " + e.getMessage(), null, null); } From a87539481920c87eba826a435b1897ce3290aede Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Mon, 13 Aug 2018 11:18:46 +0200 Subject: [PATCH 110/292] Bug 4104: Code formatting --- .../gwt/ui/raceboard/TaggingPanel.java | 157 +++++++++--------- 1 file changed, 83 insertions(+), 74 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 4d80057f215..a46677ffc5c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -77,8 +77,8 @@ public class TaggingPanel extends ComponentWithoutSettings public interface TagPanelResources extends ClientBundle { public static final TagPanelResources INSTANCE = GWT.create(TagPanelResources.class); - - //TODO image is stored in wrong folder + + // TODO image is stored in wrong folder @Source("com/sap/sailing/gwt/ui/client/images/edit.png") ImageResource editIcon(); @@ -92,7 +92,6 @@ public class TaggingPanel extends ComponentWithoutSettings String tagCreated(); String tagComment(); String tagImage(); - String button(); String footerButton(); String tagButtonTable(); @@ -102,7 +101,7 @@ public class TaggingPanel extends ComponentWithoutSettings String footerPanel(); } } - + public interface CellListResources extends CellList.Resources { public static final CellListResources INSTANCE = GWT.create(CellListResources.class); @@ -118,8 +117,7 @@ public class TaggingPanel extends ComponentWithoutSettings String cellListSelectedItem(); String cellListKeyboardSelectedItem(); } - } - + } public interface TagCellTemplate extends SafeHtmlTemplates { @Template("
{3}
(created by {4} at {5})
{6}
") @@ -200,22 +198,23 @@ public class TaggingPanel extends ComponentWithoutSettings } } } - + private class EditTagButtonsImagesBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; public static final String ACTION_EDIT = "ACTION_EDIT"; private final StringMessages stringMessages; - + public EditTagButtonsImagesBarCell(StringMessages stringMessages) { this.stringMessages = stringMessages; } - @Override protected Iterable getImageSpecs() { return Arrays.asList( - new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(TagPanelResources.INSTANCE.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); + new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), + makeImagePrototype(TagPanelResources.INSTANCE.editIcon())), + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), + makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } @@ -259,26 +258,25 @@ public class TaggingPanel extends ComponentWithoutSettings public void setComment(String comment) { this.comment = comment; } - - + } private class TagCreationPanel extends VerticalPanel { private final Panel customButtonsPanel; private final Panel standardButtonsPanel; private final TagCreationInputPanel inputPanel; - - public TagCreationPanel(StringMessages stringMessages) { + + public TagCreationPanel(StringMessages stringMessages) { setWidth("100%"); inputPanel = new TagCreationInputPanel(stringMessages); - standardButtonsPanel = new FlowPanel(); + standardButtonsPanel = new FlowPanel(); standardButtonsPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); - customButtonsPanel = new FlowPanel(); + customButtonsPanel = new FlowPanel(); customButtonsPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); add(inputPanel); add(standardButtonsPanel); add(customButtonsPanel); - + Button createTagFromTextBoxes = new Button(stringMessages.tagAddButton()); createTagFromTextBoxes.setStyleName(TagPanelResources.INSTANCE.style().button()); createTagFromTextBoxes.addClickHandler(new ClickHandler() { @@ -299,15 +297,16 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onClick(ClickEvent event) { if (isAuthorizedAndRaceLogAvailable()) { - EditCustomTagButtonsDialog editCustomTagButtonsDialog = new EditCustomTagButtonsDialog(customButtonsPanel); + EditCustomTagButtonsDialog editCustomTagButtonsDialog = new EditCustomTagButtonsDialog( + customButtonsPanel); - //scheduler is used because otherwise DialogBox would not be centered properly - Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + // scheduler is used because otherwise DialogBox would not be centered properly + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { public void execute() { editCustomTagButtonsDialog.show(); editCustomTagButtonsDialog.center(); } - }); + }); updateButtons(); } } @@ -322,31 +321,30 @@ public class TaggingPanel extends ComponentWithoutSettings }); } } - - - public class TagCreationInputPanel extends VerticalPanel{ + + public class TagCreationInputPanel extends VerticalPanel { private TextBox tagTextBox, urlTextBox; - private TextArea commentTextBox; - + private TextArea commentTextBox; + public TagCreationInputPanel(StringMessages stringMessages) { setWidth("100%"); VerticalPanel mainPanel = new VerticalPanel(); mainPanel.setWidth("100%"); - + tagTextBox = new TextBox(); tagTextBox.setWidth("100%"); tagTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelTag()); tagTextBox.setTitle(stringMessages.tagLabelTag()); tagTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelTag()); mainPanel.add(tagTextBox); - + urlTextBox = new TextBox(); urlTextBox.setWidth("100%"); urlTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelImageURL()); urlTextBox.setTitle(stringMessages.tagLabelImageURL()); urlTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); mainPanel.add(urlTextBox); - + commentTextBox = new TextArea(); commentTextBox.setWidth("100%"); commentTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelComment()); @@ -355,42 +353,42 @@ public class TaggingPanel extends ComponentWithoutSettings commentTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment()); mainPanel.add(commentTextBox); add(mainPanel); - + } - + public String getTagValue() { return tagTextBox.getValue(); } - + public String getCommentValue() { return commentTextBox.getValue(); } - + public String getImageURLValue() { return urlTextBox.getValue(); } - + public void setTagValue(String tag) { tagTextBox.setValue(tag); } - + public void setCommentValue(String comment) { commentTextBox.setValue(comment); } - + public void setImageURLValue(String imageURL) { urlTextBox.setValue(imageURL); } - + public void clearAllValues() { tagTextBox.setText(""); urlTextBox.setText(""); commentTextBox.setText(""); } } - - private class EditCustomTagButtonsDialog extends DialogBox{ - + + private class EditCustomTagButtonsDialog extends DialogBox { + private final Button closeButton; private final Panel mainPanel; private final CellTable customTagButtonsTable; @@ -424,7 +422,7 @@ public class TaggingPanel extends ComponentWithoutSettings return button.getImageURL(); } }; - + ImagesBarColumn actionsColumn = new ImagesBarColumn( new EditTagButtonsImagesBarCell(stringMessages)); actionsColumn.setFieldUpdater(new FieldUpdater() { @@ -433,37 +431,38 @@ public class TaggingPanel extends ComponentWithoutSettings if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { customTagButtons.remove(button); customButtonsPanel.remove(button); - customTagButtonsTable.setRowData(customTagButtons); - } - else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { - EditTagButtonDialog editCustomTagButtonDialog = new EditTagButtonDialog(button, customTagButtonsTable, stringMessages); - //scheduler is used because otherwise DialogBox would not be centered properly + customTagButtonsTable.setRowData(customTagButtons); + } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { + EditTagButtonDialog editCustomTagButtonDialog = new EditTagButtonDialog(button, + customTagButtonsTable, stringMessages); + // scheduler is used because otherwise DialogBox would not be centered properly - Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { public void execute() { editCustomTagButtonDialog.show(); editCustomTagButtonDialog.center(); } - }); - } + }); + } } }); - + customTagButtonsTable.addColumn(tagColumn, stringMessages.tagLabelTag()); customTagButtonsTable.addColumn(commentColumn, stringMessages.tagLabelComment()); customTagButtonsTable.addColumn(imageURLColumn, stringMessages.tagLabelImageURL()); customTagButtonsTable.addColumn(actionsColumn, "Actions"); customTagButtonsTable.setRowData(customTagButtons); - + inputPanel = new TagCreationInputPanel(stringMessages); - + addCustomTagButton = new Button(stringMessages.tagAddCustomTagButton()); addCustomTagButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); addCustomTagButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (inputPanel.getTagValue().length() > 0) { - TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), inputPanel.getImageURLValue(), inputPanel.getCommentValue()); + TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), + inputPanel.getImageURLValue(), inputPanel.getCommentValue()); inputPanel.clearAllValues(); customTagButtons.add(tagButton); customButtonsPanel.add(tagButton); @@ -473,45 +472,46 @@ public class TaggingPanel extends ComponentWithoutSettings } } }); - + closeButton = new Button(stringMessages.close()); closeButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); - + closeButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { hideDialog(); } }); - - mainPanel.add(customTagButtonsTable); + + mainPanel.add(customTagButtonsTable); mainPanel.add(inputPanel); mainPanel.add(addCustomTagButton); mainPanel.add(closeButton); - + setWidget(mainPanel); } - + private void hideDialog() { this.hide(); } } - - private final class EditTagButtonDialog extends DialogBox{ + + private final class EditTagButtonDialog extends DialogBox { private final Button saveButton, cancelButton; private final TagCreationInputPanel inputPanel; private final VerticalPanel mainPanel; private final HorizontalPanel saveAndClosePanel; - - public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, StringMessages stringMessages) { + + public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, + StringMessages stringMessages) { setText(stringMessages.tagEditCustomTagButton()); mainPanel = new VerticalPanel(); - + inputPanel = new TagCreationInputPanel(stringMessages); inputPanel.setTagValue(tagButton.getTag()); inputPanel.setCommentValue(tagButton.getComment()); inputPanel.setImageURLValue(tagButton.getImageURL()); - + saveButton = new Button("save"); saveButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); saveButton.addClickHandler(new ClickHandler() { @@ -524,10 +524,10 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtonsTable.redraw(); hideDialog(); } - + }); - - cancelButton = new Button(stringMessages.cancel()); + + cancelButton = new Button(stringMessages.cancel()); cancelButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); cancelButton.addClickHandler(new ClickHandler() { @Override @@ -535,22 +535,23 @@ public class TaggingPanel extends ComponentWithoutSettings hideDialog(); } }); - + saveAndClosePanel = new HorizontalPanel(); saveAndClosePanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); saveAndClosePanel.add(saveButton); saveAndClosePanel.add(cancelButton); - + mainPanel.add(inputPanel); mainPanel.add(saveAndClosePanel); setWidget(mainPanel); } - + private void hideDialog() { this.hide(); } } + private final HeaderPanel panel; private final TagCreationPanel tagCreationPanel; private final Panel filterbarPanel; @@ -600,7 +601,7 @@ public class TaggingPanel extends ComponentWithoutSettings initializePanel(); } - + public TaggingPanel(Component parent, ComponentContext context, StringMessages stringMessages, SailingServiceAsync sailingService, UserService userService, Timer timer, RaceTimesInfoProvider raceTimesInfoProvider, String leaderboardName, RaceColumnDTO raceColumn, @@ -708,6 +709,7 @@ public class TaggingPanel extends ComponentWithoutSettings tagListProvider.refresh(); } + @Override public void raceTimesInfosReceived(Map raceTimesInfo, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) { @@ -737,40 +739,47 @@ public class TaggingPanel extends ComponentWithoutSettings } }); } + @Override public void onUserStatusChange(UserDTO user, boolean preAuthenticated) { updateContent(); } + @Override public String getId() { return "TaggingPanel"; } + @Override public String getLocalizedShortName() { return stringMessages.tagPanel(); } + @Override public Widget getEntryWidget() { return panel; } + @Override public boolean isVisible() { return panel.isVisible(); } + @Override public void setVisible(boolean visibility) { panel.setVisible(visibility); } + @Override public String getDependentCssClassName() { return "tags"; } - } + From e55cfb0eba0657ca46f5acdd5cf5a9cd0f927528 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Mon, 13 Aug 2018 11:24:26 +0200 Subject: [PATCH 111/292] Revert "Bug 4104: Code formatting" This reverts commit a87539481920c87eba826a435b1897ce3290aede. --- .../gwt/ui/raceboard/TaggingPanel.java | 157 +++++++++--------- 1 file changed, 74 insertions(+), 83 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index a46677ffc5c..4d80057f215 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -77,8 +77,8 @@ public class TaggingPanel extends ComponentWithoutSettings public interface TagPanelResources extends ClientBundle { public static final TagPanelResources INSTANCE = GWT.create(TagPanelResources.class); - - // TODO image is stored in wrong folder + + //TODO image is stored in wrong folder @Source("com/sap/sailing/gwt/ui/client/images/edit.png") ImageResource editIcon(); @@ -92,6 +92,7 @@ public class TaggingPanel extends ComponentWithoutSettings String tagCreated(); String tagComment(); String tagImage(); + String button(); String footerButton(); String tagButtonTable(); @@ -101,7 +102,7 @@ public class TaggingPanel extends ComponentWithoutSettings String footerPanel(); } } - + public interface CellListResources extends CellList.Resources { public static final CellListResources INSTANCE = GWT.create(CellListResources.class); @@ -117,7 +118,8 @@ public class TaggingPanel extends ComponentWithoutSettings String cellListSelectedItem(); String cellListKeyboardSelectedItem(); } - } + } + public interface TagCellTemplate extends SafeHtmlTemplates { @Template("
{3}
(created by {4} at {5})
{6}
") @@ -198,23 +200,22 @@ public class TaggingPanel extends ComponentWithoutSettings } } } - + private class EditTagButtonsImagesBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; public static final String ACTION_EDIT = "ACTION_EDIT"; private final StringMessages stringMessages; - + public EditTagButtonsImagesBarCell(StringMessages stringMessages) { this.stringMessages = stringMessages; } + @Override protected Iterable getImageSpecs() { return Arrays.asList( - new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), - makeImagePrototype(TagPanelResources.INSTANCE.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), - makeImagePrototype(IconResources.INSTANCE.removeIcon()))); + new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(TagPanelResources.INSTANCE.editIcon())), + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } @@ -258,25 +259,26 @@ public class TaggingPanel extends ComponentWithoutSettings public void setComment(String comment) { this.comment = comment; } - + + } private class TagCreationPanel extends VerticalPanel { private final Panel customButtonsPanel; private final Panel standardButtonsPanel; private final TagCreationInputPanel inputPanel; - - public TagCreationPanel(StringMessages stringMessages) { + + public TagCreationPanel(StringMessages stringMessages) { setWidth("100%"); inputPanel = new TagCreationInputPanel(stringMessages); - standardButtonsPanel = new FlowPanel(); + standardButtonsPanel = new FlowPanel(); standardButtonsPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); - customButtonsPanel = new FlowPanel(); + customButtonsPanel = new FlowPanel(); customButtonsPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); add(inputPanel); add(standardButtonsPanel); add(customButtonsPanel); - + Button createTagFromTextBoxes = new Button(stringMessages.tagAddButton()); createTagFromTextBoxes.setStyleName(TagPanelResources.INSTANCE.style().button()); createTagFromTextBoxes.addClickHandler(new ClickHandler() { @@ -297,16 +299,15 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onClick(ClickEvent event) { if (isAuthorizedAndRaceLogAvailable()) { - EditCustomTagButtonsDialog editCustomTagButtonsDialog = new EditCustomTagButtonsDialog( - customButtonsPanel); + EditCustomTagButtonsDialog editCustomTagButtonsDialog = new EditCustomTagButtonsDialog(customButtonsPanel); - // scheduler is used because otherwise DialogBox would not be centered properly - Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + //scheduler is used because otherwise DialogBox would not be centered properly + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { public void execute() { editCustomTagButtonsDialog.show(); editCustomTagButtonsDialog.center(); } - }); + }); updateButtons(); } } @@ -321,30 +322,31 @@ public class TaggingPanel extends ComponentWithoutSettings }); } } - - public class TagCreationInputPanel extends VerticalPanel { + + + public class TagCreationInputPanel extends VerticalPanel{ private TextBox tagTextBox, urlTextBox; - private TextArea commentTextBox; - + private TextArea commentTextBox; + public TagCreationInputPanel(StringMessages stringMessages) { setWidth("100%"); VerticalPanel mainPanel = new VerticalPanel(); mainPanel.setWidth("100%"); - + tagTextBox = new TextBox(); tagTextBox.setWidth("100%"); tagTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelTag()); tagTextBox.setTitle(stringMessages.tagLabelTag()); tagTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelTag()); mainPanel.add(tagTextBox); - + urlTextBox = new TextBox(); urlTextBox.setWidth("100%"); urlTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelImageURL()); urlTextBox.setTitle(stringMessages.tagLabelImageURL()); urlTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); mainPanel.add(urlTextBox); - + commentTextBox = new TextArea(); commentTextBox.setWidth("100%"); commentTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelComment()); @@ -353,42 +355,42 @@ public class TaggingPanel extends ComponentWithoutSettings commentTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment()); mainPanel.add(commentTextBox); add(mainPanel); - + } - + public String getTagValue() { return tagTextBox.getValue(); } - + public String getCommentValue() { return commentTextBox.getValue(); } - + public String getImageURLValue() { return urlTextBox.getValue(); } - + public void setTagValue(String tag) { tagTextBox.setValue(tag); } - + public void setCommentValue(String comment) { commentTextBox.setValue(comment); } - + public void setImageURLValue(String imageURL) { urlTextBox.setValue(imageURL); } - + public void clearAllValues() { tagTextBox.setText(""); urlTextBox.setText(""); commentTextBox.setText(""); } } - - private class EditCustomTagButtonsDialog extends DialogBox { - + + private class EditCustomTagButtonsDialog extends DialogBox{ + private final Button closeButton; private final Panel mainPanel; private final CellTable customTagButtonsTable; @@ -422,7 +424,7 @@ public class TaggingPanel extends ComponentWithoutSettings return button.getImageURL(); } }; - + ImagesBarColumn actionsColumn = new ImagesBarColumn( new EditTagButtonsImagesBarCell(stringMessages)); actionsColumn.setFieldUpdater(new FieldUpdater() { @@ -431,38 +433,37 @@ public class TaggingPanel extends ComponentWithoutSettings if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { customTagButtons.remove(button); customButtonsPanel.remove(button); - customTagButtonsTable.setRowData(customTagButtons); - } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { - EditTagButtonDialog editCustomTagButtonDialog = new EditTagButtonDialog(button, - customTagButtonsTable, stringMessages); - // scheduler is used because otherwise DialogBox would not be centered properly + customTagButtonsTable.setRowData(customTagButtons); + } + else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { + EditTagButtonDialog editCustomTagButtonDialog = new EditTagButtonDialog(button, customTagButtonsTable, stringMessages); + //scheduler is used because otherwise DialogBox would not be centered properly - Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { public void execute() { editCustomTagButtonDialog.show(); editCustomTagButtonDialog.center(); } - }); - } + }); + } } }); - + customTagButtonsTable.addColumn(tagColumn, stringMessages.tagLabelTag()); customTagButtonsTable.addColumn(commentColumn, stringMessages.tagLabelComment()); customTagButtonsTable.addColumn(imageURLColumn, stringMessages.tagLabelImageURL()); customTagButtonsTable.addColumn(actionsColumn, "Actions"); customTagButtonsTable.setRowData(customTagButtons); - + inputPanel = new TagCreationInputPanel(stringMessages); - + addCustomTagButton = new Button(stringMessages.tagAddCustomTagButton()); addCustomTagButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); addCustomTagButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (inputPanel.getTagValue().length() > 0) { - TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), - inputPanel.getImageURLValue(), inputPanel.getCommentValue()); + TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), inputPanel.getImageURLValue(), inputPanel.getCommentValue()); inputPanel.clearAllValues(); customTagButtons.add(tagButton); customButtonsPanel.add(tagButton); @@ -472,46 +473,45 @@ public class TaggingPanel extends ComponentWithoutSettings } } }); - + closeButton = new Button(stringMessages.close()); closeButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); - + closeButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { hideDialog(); } }); - - mainPanel.add(customTagButtonsTable); + + mainPanel.add(customTagButtonsTable); mainPanel.add(inputPanel); mainPanel.add(addCustomTagButton); mainPanel.add(closeButton); - + setWidget(mainPanel); } - + private void hideDialog() { this.hide(); } } - - private final class EditTagButtonDialog extends DialogBox { + + private final class EditTagButtonDialog extends DialogBox{ private final Button saveButton, cancelButton; private final TagCreationInputPanel inputPanel; private final VerticalPanel mainPanel; private final HorizontalPanel saveAndClosePanel; - - public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, - StringMessages stringMessages) { + + public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, StringMessages stringMessages) { setText(stringMessages.tagEditCustomTagButton()); mainPanel = new VerticalPanel(); - + inputPanel = new TagCreationInputPanel(stringMessages); inputPanel.setTagValue(tagButton.getTag()); inputPanel.setCommentValue(tagButton.getComment()); inputPanel.setImageURLValue(tagButton.getImageURL()); - + saveButton = new Button("save"); saveButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); saveButton.addClickHandler(new ClickHandler() { @@ -524,10 +524,10 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtonsTable.redraw(); hideDialog(); } - + }); - - cancelButton = new Button(stringMessages.cancel()); + + cancelButton = new Button(stringMessages.cancel()); cancelButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); cancelButton.addClickHandler(new ClickHandler() { @Override @@ -535,23 +535,22 @@ public class TaggingPanel extends ComponentWithoutSettings hideDialog(); } }); - + saveAndClosePanel = new HorizontalPanel(); saveAndClosePanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); saveAndClosePanel.add(saveButton); saveAndClosePanel.add(cancelButton); - + mainPanel.add(inputPanel); mainPanel.add(saveAndClosePanel); setWidget(mainPanel); } - + private void hideDialog() { this.hide(); } } - private final HeaderPanel panel; private final TagCreationPanel tagCreationPanel; private final Panel filterbarPanel; @@ -601,7 +600,7 @@ public class TaggingPanel extends ComponentWithoutSettings initializePanel(); } - + public TaggingPanel(Component parent, ComponentContext context, StringMessages stringMessages, SailingServiceAsync sailingService, UserService userService, Timer timer, RaceTimesInfoProvider raceTimesInfoProvider, String leaderboardName, RaceColumnDTO raceColumn, @@ -709,7 +708,6 @@ public class TaggingPanel extends ComponentWithoutSettings tagListProvider.refresh(); } - @Override public void raceTimesInfosReceived(Map raceTimesInfo, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) { @@ -739,47 +737,40 @@ public class TaggingPanel extends ComponentWithoutSettings } }); } - @Override public void onUserStatusChange(UserDTO user, boolean preAuthenticated) { updateContent(); } - @Override public String getId() { return "TaggingPanel"; } - @Override public String getLocalizedShortName() { return stringMessages.tagPanel(); } - @Override public Widget getEntryWidget() { return panel; } - @Override public boolean isVisible() { return panel.isVisible(); } - @Override public void setVisible(boolean visibility) { panel.setVisible(visibility); } - @Override public String getDependentCssClassName() { return "tags"; } -} +} From 43ec9838e44a5528fcc03e1b7b7de147a16ae582 Mon Sep 17 00:00:00 2001 From: D067890 Date: Mon, 13 Aug 2018 11:25:57 +0200 Subject: [PATCH 112/292] bug4104: Tag searching is now supported --- .../gwt/ui/raceboard/TagFilterPanel.java | 63 +++++++++++++++++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java index 5073d827029..f7b63cc41f8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java @@ -1,5 +1,10 @@ package com.sap.sailing.gwt.ui.raceboard; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; @@ -24,6 +29,9 @@ import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsDialog; import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsJsonDeSerializer; import com.sap.sailing.gwt.ui.raceboard.TagFilterPanel.TagFilterResources.TagFilterCss; import com.sap.sailing.gwt.ui.shared.TagDTO; +import com.sap.sse.common.Util; +import com.sap.sse.common.filter.AbstractListFilter; +import com.sap.sse.common.filter.Filter; import com.sap.sse.common.filter.FilterSet; import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; @@ -84,6 +92,7 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit private final FlowPanel searchBoxPanel; private final StringMessages stringMessages; private final TagListProvider tagProvider; + private final AbstractListFilter filter; private FilterSet> lastActiveTagFilterSet; @@ -101,6 +110,14 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit tagFilterSets = createAndAddDefaultTagsFilter(); storeTagsFilterSets(tagFilterSets); } + + filter = new AbstractListFilter() { + @Override + public Iterable getStrings(TagDTO tag) { + final List result = new ArrayList<>(Arrays.asList(tag.getTag().toLowerCase(), tag.getComment())); + return result; + } + }; Button submitButton = new Button(); submitButton.setStyleName(css.button()); @@ -245,9 +262,9 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit } @Override - public boolean matches(TagDTO object) { - // TODO Auto-generated method stub - return false; + public boolean matches(TagDTO tag) { + final Iterable lowercaseKeywords = Util.splitAlongWhitespaceRespectingDoubleQuotedPhrases(searchTextBox.getText().toLowerCase()); + return !Util.isEmpty(filter.applyFilter(lowercaseKeywords, Collections.singleton(tag))); } @Override @@ -284,9 +301,47 @@ public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWit return null; } + /** + * @param event ignored; may be null + */ @Override public void onKeyUp(KeyUpEvent event) { - // TODO Auto-generated method stub + String newValue = searchTextBox.getValue(); + if (newValue.trim().isEmpty()) { + removeSearchFilter(); + clearTextBoxButton.addStyleName(css.hiddenButton()); + } else { + if (newValue.length() >= 2) { + clearTextBoxButton.removeStyleName(css.hiddenButton()); + ensureSearchFilterIsSet(); + tagProvider.setTagsFilterSet(tagProvider.getTagsFilterSet()); // + } + } + } + + private void ensureSearchFilterIsSet() { + if (tagProvider.getTagsFilterSet() == null || !Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { + FilterSet> newFilterSetWithThis = new FilterSet<>(getName()); + if (tagProvider.getTagsFilterSet() != null) { + for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { + newFilterSetWithThis.addFilter(oldFilter); + } + } + newFilterSetWithThis.addFilter(this); + tagProvider.setTagsFilterSet(newFilterSetWithThis); + } + } + private void removeSearchFilter() { + if (tagProvider.getTagsFilterSet() != null + && Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { + FilterSet> newFilterSetWithThis = new FilterSet<>(tagProvider.getTagsFilterSet().getName()); + for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { + if (oldFilter != this) { + newFilterSetWithThis.addFilter(oldFilter); + } + } + tagProvider.setTagsFilterSet(newFilterSetWithThis); + } } } \ No newline at end of file From c1e075fbb0a0f9144c93430ccc87063017afc52e Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Mon, 13 Aug 2018 11:26:53 +0200 Subject: [PATCH 113/292] Bug 4104: Code formatting --- .../gwt/ui/raceboard/TaggingPanel.java | 145 +++++++++--------- 1 file changed, 73 insertions(+), 72 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 4d80057f215..abca0ea8c0f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -5,6 +5,7 @@ import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; + import com.google.gwt.cell.client.AbstractCell; import com.google.gwt.cell.client.FieldUpdater; import com.google.gwt.cell.client.ValueUpdater; @@ -77,8 +78,8 @@ public class TaggingPanel extends ComponentWithoutSettings public interface TagPanelResources extends ClientBundle { public static final TagPanelResources INSTANCE = GWT.create(TagPanelResources.class); - - //TODO image is stored in wrong folder + + // TODO image is stored in wrong folder @Source("com/sap/sailing/gwt/ui/client/images/edit.png") ImageResource editIcon(); @@ -92,7 +93,6 @@ public class TaggingPanel extends ComponentWithoutSettings String tagCreated(); String tagComment(); String tagImage(); - String button(); String footerButton(); String tagButtonTable(); @@ -102,7 +102,7 @@ public class TaggingPanel extends ComponentWithoutSettings String footerPanel(); } } - + public interface CellListResources extends CellList.Resources { public static final CellListResources INSTANCE = GWT.create(CellListResources.class); @@ -118,8 +118,7 @@ public class TaggingPanel extends ComponentWithoutSettings String cellListSelectedItem(); String cellListKeyboardSelectedItem(); } - } - + } public interface TagCellTemplate extends SafeHtmlTemplates { @Template("
{3}
(created by {4} at {5})
{6}
") @@ -200,22 +199,23 @@ public class TaggingPanel extends ComponentWithoutSettings } } } - + private class EditTagButtonsImagesBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; public static final String ACTION_EDIT = "ACTION_EDIT"; private final StringMessages stringMessages; - + public EditTagButtonsImagesBarCell(StringMessages stringMessages) { this.stringMessages = stringMessages; } - @Override protected Iterable getImageSpecs() { return Arrays.asList( - new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(TagPanelResources.INSTANCE.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); + new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), + makeImagePrototype(TagPanelResources.INSTANCE.editIcon())), + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), + makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } @@ -259,26 +259,25 @@ public class TaggingPanel extends ComponentWithoutSettings public void setComment(String comment) { this.comment = comment; } - - + } private class TagCreationPanel extends VerticalPanel { private final Panel customButtonsPanel; private final Panel standardButtonsPanel; private final TagCreationInputPanel inputPanel; - - public TagCreationPanel(StringMessages stringMessages) { + + public TagCreationPanel(StringMessages stringMessages) { setWidth("100%"); inputPanel = new TagCreationInputPanel(stringMessages); - standardButtonsPanel = new FlowPanel(); + standardButtonsPanel = new FlowPanel(); standardButtonsPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); - customButtonsPanel = new FlowPanel(); + customButtonsPanel = new FlowPanel(); customButtonsPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); add(inputPanel); add(standardButtonsPanel); add(customButtonsPanel); - + Button createTagFromTextBoxes = new Button(stringMessages.tagAddButton()); createTagFromTextBoxes.setStyleName(TagPanelResources.INSTANCE.style().button()); createTagFromTextBoxes.addClickHandler(new ClickHandler() { @@ -299,15 +298,16 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onClick(ClickEvent event) { if (isAuthorizedAndRaceLogAvailable()) { - EditCustomTagButtonsDialog editCustomTagButtonsDialog = new EditCustomTagButtonsDialog(customButtonsPanel); + EditCustomTagButtonsDialog editCustomTagButtonsDialog = new EditCustomTagButtonsDialog( + customButtonsPanel); - //scheduler is used because otherwise DialogBox would not be centered properly - Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + // scheduler is used because otherwise DialogBox would not be centered properly + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { public void execute() { editCustomTagButtonsDialog.show(); editCustomTagButtonsDialog.center(); } - }); + }); updateButtons(); } } @@ -322,31 +322,30 @@ public class TaggingPanel extends ComponentWithoutSettings }); } } - - - public class TagCreationInputPanel extends VerticalPanel{ + + public class TagCreationInputPanel extends VerticalPanel { private TextBox tagTextBox, urlTextBox; - private TextArea commentTextBox; - + private TextArea commentTextBox; + public TagCreationInputPanel(StringMessages stringMessages) { setWidth("100%"); VerticalPanel mainPanel = new VerticalPanel(); mainPanel.setWidth("100%"); - + tagTextBox = new TextBox(); tagTextBox.setWidth("100%"); tagTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelTag()); tagTextBox.setTitle(stringMessages.tagLabelTag()); tagTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelTag()); mainPanel.add(tagTextBox); - + urlTextBox = new TextBox(); urlTextBox.setWidth("100%"); urlTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelImageURL()); urlTextBox.setTitle(stringMessages.tagLabelImageURL()); urlTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); mainPanel.add(urlTextBox); - + commentTextBox = new TextArea(); commentTextBox.setWidth("100%"); commentTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelComment()); @@ -355,42 +354,42 @@ public class TaggingPanel extends ComponentWithoutSettings commentTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment()); mainPanel.add(commentTextBox); add(mainPanel); - + } - + public String getTagValue() { return tagTextBox.getValue(); } - + public String getCommentValue() { return commentTextBox.getValue(); } - + public String getImageURLValue() { return urlTextBox.getValue(); } - + public void setTagValue(String tag) { tagTextBox.setValue(tag); } - + public void setCommentValue(String comment) { commentTextBox.setValue(comment); } - + public void setImageURLValue(String imageURL) { urlTextBox.setValue(imageURL); } - + public void clearAllValues() { tagTextBox.setText(""); urlTextBox.setText(""); commentTextBox.setText(""); } } - - private class EditCustomTagButtonsDialog extends DialogBox{ - + + private class EditCustomTagButtonsDialog extends DialogBox { + private final Button closeButton; private final Panel mainPanel; private final CellTable customTagButtonsTable; @@ -424,7 +423,7 @@ public class TaggingPanel extends ComponentWithoutSettings return button.getImageURL(); } }; - + ImagesBarColumn actionsColumn = new ImagesBarColumn( new EditTagButtonsImagesBarCell(stringMessages)); actionsColumn.setFieldUpdater(new FieldUpdater() { @@ -433,37 +432,38 @@ public class TaggingPanel extends ComponentWithoutSettings if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { customTagButtons.remove(button); customButtonsPanel.remove(button); - customTagButtonsTable.setRowData(customTagButtons); - } - else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { - EditTagButtonDialog editCustomTagButtonDialog = new EditTagButtonDialog(button, customTagButtonsTable, stringMessages); - //scheduler is used because otherwise DialogBox would not be centered properly + customTagButtonsTable.setRowData(customTagButtons); + } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { + EditTagButtonDialog editCustomTagButtonDialog = new EditTagButtonDialog(button, + customTagButtonsTable, stringMessages); + // scheduler is used because otherwise DialogBox would not be centered properly - Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { public void execute() { editCustomTagButtonDialog.show(); editCustomTagButtonDialog.center(); } - }); - } + }); + } } }); - + customTagButtonsTable.addColumn(tagColumn, stringMessages.tagLabelTag()); customTagButtonsTable.addColumn(commentColumn, stringMessages.tagLabelComment()); customTagButtonsTable.addColumn(imageURLColumn, stringMessages.tagLabelImageURL()); customTagButtonsTable.addColumn(actionsColumn, "Actions"); customTagButtonsTable.setRowData(customTagButtons); - + inputPanel = new TagCreationInputPanel(stringMessages); - + addCustomTagButton = new Button(stringMessages.tagAddCustomTagButton()); addCustomTagButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); addCustomTagButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (inputPanel.getTagValue().length() > 0) { - TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), inputPanel.getImageURLValue(), inputPanel.getCommentValue()); + TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), + inputPanel.getImageURLValue(), inputPanel.getCommentValue()); inputPanel.clearAllValues(); customTagButtons.add(tagButton); customButtonsPanel.add(tagButton); @@ -473,45 +473,46 @@ public class TaggingPanel extends ComponentWithoutSettings } } }); - + closeButton = new Button(stringMessages.close()); closeButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); - + closeButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { hideDialog(); } }); - - mainPanel.add(customTagButtonsTable); + + mainPanel.add(customTagButtonsTable); mainPanel.add(inputPanel); mainPanel.add(addCustomTagButton); mainPanel.add(closeButton); - + setWidget(mainPanel); } - + private void hideDialog() { this.hide(); } } - - private final class EditTagButtonDialog extends DialogBox{ + + private final class EditTagButtonDialog extends DialogBox { private final Button saveButton, cancelButton; private final TagCreationInputPanel inputPanel; private final VerticalPanel mainPanel; private final HorizontalPanel saveAndClosePanel; - - public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, StringMessages stringMessages) { + + public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, + StringMessages stringMessages) { setText(stringMessages.tagEditCustomTagButton()); mainPanel = new VerticalPanel(); - + inputPanel = new TagCreationInputPanel(stringMessages); inputPanel.setTagValue(tagButton.getTag()); inputPanel.setCommentValue(tagButton.getComment()); inputPanel.setImageURLValue(tagButton.getImageURL()); - + saveButton = new Button("save"); saveButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); saveButton.addClickHandler(new ClickHandler() { @@ -524,10 +525,10 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtonsTable.redraw(); hideDialog(); } - + }); - - cancelButton = new Button(stringMessages.cancel()); + + cancelButton = new Button(stringMessages.cancel()); cancelButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); cancelButton.addClickHandler(new ClickHandler() { @Override @@ -535,17 +536,17 @@ public class TaggingPanel extends ComponentWithoutSettings hideDialog(); } }); - + saveAndClosePanel = new HorizontalPanel(); saveAndClosePanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); saveAndClosePanel.add(saveButton); saveAndClosePanel.add(cancelButton); - + mainPanel.add(inputPanel); mainPanel.add(saveAndClosePanel); setWidget(mainPanel); } - + private void hideDialog() { this.hide(); } From 7ed118aa8dc146018106f5c0dc805dbdb2b8e05b Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Mon, 13 Aug 2018 11:53:27 +0200 Subject: [PATCH 114/292] Bug 4104: Hide buttons to add new tags when user is not logged in --- .../main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java | 1 + .../main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css | 1 + 2 files changed, 2 insertions(+) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index abca0ea8c0f..3c7cc7efaf9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -704,6 +704,7 @@ public class TaggingPanel extends ComponentWithoutSettings } private void updateContent() { + tagCreationPanel.setVisible(userService.getCurrentUser() != null); tagListProvider.updateFilteredTags(); tagCellList.setVisibleRange(0, tagListProvider.getFilteredTagsListSize()); tagListProvider.refresh(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css index 84edb7da168..07644714185 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css @@ -10,6 +10,7 @@ b { right: 0; margin: 6px; margin-top: 10px; + margin-bottom: 0; } .tag { From 07a20792626875d0bd4e39e453cd11f9812032ee Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Mon, 13 Aug 2018 11:53:52 +0200 Subject: [PATCH 115/292] Bug 4104: Removed exception when user clicked on a tag --- .../java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 3c7cc7efaf9..415391b1068 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -193,7 +193,8 @@ public class TaggingPanel extends ComponentWithoutSettings if (!Element.is(eventTarget)) { return; } - if (parent.getElementsByTagName("button").getItem(0).isOrHasChild(Element.as(eventTarget))) { + Element button = parent.getElementsByTagName("button").getItem(0); + if (button != null && button.isOrHasChild(Element.as(eventTarget))) { removeTagFromRaceLog(tag); } } From 83933eb517c9aaa04ea9a21f50d441e7ec0dcb11 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Mon, 13 Aug 2018 14:27:09 +0200 Subject: [PATCH 116/292] Bug 4104: Changed translations (DE) and fixed some texts where no translations files were used. --- .../sailing/gwt/ui/client/StringMessages.java | 5 +-- .../gwt/ui/client/StringMessages.properties | 13 +++---- .../ui/client/StringMessages_de.properties | 23 ++++++----- .../gwt/ui/raceboard/TaggingPanel.java | 38 +++++++------------ 4 files changed, 33 insertions(+), 46 deletions(-) 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 713abea657b..f41039d002f 100755 --- 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 @@ -2100,7 +2100,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String tagPanel(); String tagCreated(String author, String time); String tagNoTagsFound(); - String tagAddButton(); + String tagAddTag(); String tagAddedSuccessfully(); String tagNotAdded(); String tagNotLoaded(); @@ -2114,10 +2114,9 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String tagLabelImageURL(); String tagCreateTag(); String tagEditCustomTagButtons(); - String tagEditCustomTagsButtonDialogHeader(); String tagAddCustomTagButton(); String tagNotSpecified(); - String tagFilterDialogHeader(); String tagEditFilter(); String tagEditCustomTagButton(); + String tagSaveCustomTagButton(); } 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 d6e7a73857d..c3f90f4dbe5 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 @@ -2095,23 +2095,22 @@ tag=Tag tagPanel=Tags tagCreated=(created by {0} at {1}) tagNoTagsFound=No tags found! -tagAddButton=Add new Tag -tagAddedSuccessfully=Added new tag successfully +tagAddTag=Add tag +tagAddedSuccessfully=Added tag successfully tagNotAdded=Could not add new tag! tagNotLoaded=Could not load tags! tagNotLoggedIn=Please log in to add new tags! tagFilterExplanation=The filter will show all tags matching the criterias: tagSelectedTags=Selected Tags tagsFilter=Tags Filter -tagSearchTags=Search Tags +tagSearchTags=Search tagLabelTag=Tag tagLabelComment=Comment tagLabelImageURL=Image URL tagCreateTag=Create tag tagEditCustomTagButtons=Edit tag buttons -tagEditCustomTagsButtonDialogHeader=Edit tag buttons tagAddCustomTagButton=Add tag button -tagNotSpecified=Tag must not be empty -tagFilterDialogHeader=Tag filters +tagNotSpecified=Tag must not be empty! tagEditFilter=Edit filter -tagEditCustomTagButton=Edit tag button \ No newline at end of file +tagEditCustomTagButton=Edit tag button +tagSaveCustomTagButton=Save 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 1d7e2719bcf..81dfef10d11 100755 --- 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 @@ -2088,25 +2088,24 @@ swissTimingUpdateUsername=Benutzername zum Versenden der Updates swissTimingUpdatePassword=Passwort zum Versenden der Updates tag=Tag tagPanel=Tags -tagCreated=(erstellt von {0} um {1}) +tagCreated=(erstellt von {0} am {1}) tagNoTagsFound=Keine Tags gefunden! -tagAddButton=Neuen Tag-Button hinzufügen -tagAddedSuccessfully=Neuen Tag erfolgreich hinzugefügt +tagAddTag=Tag hinzufügen +tagAddedSuccessfully=Tag erfolgreich hinzugefügt tagNotAdded=Neuer Tag konnte nicht gespeichert werden! tagNotLoaded=Tags konnten nicht geladen werden! tagNotLoggedIn=Bitte loggen Sie sich ein um einem Rennen Tags hinzuzufügen! tagFilterExplanation=Der Filter filtert alle Tags, welche die nachfolgenden Kriterien erfüllen: tagSelectedTags=Ausgewählte Tags -tagsFilter=Tags Filter -tagSearchTags=Suche Tags +tagsFilter=Tag Filter +tagSearchTags=Suchen tagLabelTag=Tag tagLabelComment=Comment tagLabelImageURL=Bild URL -tagCreateTag=Fuege Tag hinzu -tagEditCustomTagButtons=Bearbeite Tag Buttons -tagEditCustomTagsButtonDialogHeader=Bearbeite Tag Buttons -tagAddCustomTagButton=Füge Tag Button hinzu -tagNotSpecified=Tag muss spezifiziert sein, gebe bitte einen Wert für Tag an -tagFilterDialogHeader=Tag Filters +tagCreateTag=Tag hinzufügen +tagEditCustomTagButtons=Tag Buttons bearbeiten +tagAddCustomTagButton=Tag Button hinzufügen +tagNotSpecified=Tag darf nicht leer sein! tagEditFilter=Bearbeite Filter -tagEditCustomTagButton=Bearbeite Tag Button \ No newline at end of file +tagEditCustomTagButton=Bearbeite Tag Button +tagSaveCustomTagButton=Speichern diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 415391b1068..159bdcbba39 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -17,6 +17,7 @@ import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; import com.google.gwt.resources.client.ImageResource; @@ -55,7 +56,6 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.TagListProvider; import com.sap.sailing.gwt.ui.client.shared.controls.ImagesBarCell; -import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.raceboard.TaggingPanel.TagPanelResources.TagPanelStyle; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.TagDTO; @@ -121,13 +121,13 @@ public class TaggingPanel extends ComponentWithoutSettings } public interface TagCellTemplate extends SafeHtmlTemplates { - @Template("
{3}
(created by {4} at {5})
{6}
") - SafeHtml cell(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, SafeHtml author, - SafeHtml createdAt, SafeHtml content); + @Template("
{3}
{4}
{5}
") + SafeHtml cell(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, SafeHtml createdAt, + SafeHtml content); - @Template("
{3}
(created by {4} at {5})
{6}
") + @Template("
{3}
{4}
{5}
") SafeHtml cellRemovable(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, - SafeHtml author, SafeHtml createdAt, SafeHtml content); + SafeHtml createdAt, SafeHtml content); @Template("
{3}
") SafeHtml contentWithCommentWithImage(String styleTagImage, String styleTagComment, SafeUri imageURL, @@ -156,9 +156,7 @@ public class TaggingPanel extends ComponentWithoutSettings } SafeHtml safeTag = SafeHtmlUtils.fromString(tag.getTag()); - SafeHtml safeAuthor = SafeHtmlUtils.fromString(tag.getUsername()); - SafeHtml safeCreatedAt = SafeHtmlUtils - .fromString(DateAndTimeFormatterUtil.shortTimeFormatter.render(tag.getRaceTimepoint().asDate())); + SafeHtml safeCreated = SafeHtmlUtils.fromString(stringMessages.tagCreated(tag.getUsername(), DateTimeFormat.getFormat("E d/M/y, HH:mm").format(tag.getRaceTimepoint().asDate()))); SafeHtml safeComment = SafeHtmlUtils.fromString(tag.getComment()); SafeUri trustedImageURL = UriUtils.fromTrustedString(tag.getImageURL()); @@ -176,10 +174,10 @@ public class TaggingPanel extends ComponentWithoutSettings if (userService.getCurrentUser() != null && tag.getUsername().equals(userService.getCurrentUser().getName())) { cell = tagCellTemplate.cellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), safeTag, safeAuthor, safeCreatedAt, content); + tagPanelStyle.tagCreated(), safeTag, safeCreated, content); } else { cell = tagCellTemplate.cell(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), tagPanelStyle.tagCreated(), - safeTag, safeAuthor, safeCreatedAt, content); + safeTag, safeCreated, content); } htmlBuilder.append(cell); } @@ -279,7 +277,7 @@ public class TaggingPanel extends ComponentWithoutSettings add(standardButtonsPanel); add(customButtonsPanel); - Button createTagFromTextBoxes = new Button(stringMessages.tagAddButton()); + Button createTagFromTextBoxes = new Button(stringMessages.tagAddTag()); createTagFromTextBoxes.setStyleName(TagPanelResources.INSTANCE.style().button()); createTagFromTextBoxes.addClickHandler(new ClickHandler() { @Override @@ -399,7 +397,7 @@ public class TaggingPanel extends ComponentWithoutSettings public EditCustomTagButtonsDialog(Panel customButtonsPanel) { setGlassEnabled(true); - setText(stringMessages.tagEditCustomTagsButtonDialogHeader()); + setText(stringMessages.tagEditCustomTagButtons()); mainPanel = new VerticalPanel(); mainPanel.setWidth("100px"); @@ -514,7 +512,7 @@ public class TaggingPanel extends ComponentWithoutSettings inputPanel.setCommentValue(tagButton.getComment()); inputPanel.setImageURLValue(tagButton.getImageURL()); - saveButton = new Button("save"); + saveButton = new Button(stringMessages.tagSaveCustomTagButton()); saveButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); saveButton.addClickHandler(new ClickHandler() { @@ -669,7 +667,7 @@ public class TaggingPanel extends ComponentWithoutSettings } }); } else { - Notification.notify(stringMessages.tagNotSpecified(), NotificationType.ERROR); + Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); } } @@ -693,15 +691,7 @@ public class TaggingPanel extends ComponentWithoutSettings } private boolean isAuthorizedAndRaceLogAvailable() { - if (leaderboardName == null || raceColumn == null || fleet == null) { - Notification.notify(stringMessages.tagNotAdded(), NotificationType.ERROR); - return false; - } - if (userService.getCurrentUser() == null) { - Notification.notify(stringMessages.tagNotLoggedIn(), NotificationType.WARNING); - return false; - } - return true; + return !(userService.getCurrentUser() == null || leaderboardName == null || raceColumn == null && fleet == null); } private void updateContent() { From fb012b1cd8468a79f876260426c55e88fb17a57c Mon Sep 17 00:00:00 2001 From: D067890 Date: Mon, 13 Aug 2018 14:52:02 +0200 Subject: [PATCH 117/292] bug4104: Started working on preview of tags --- .../gwt/ui/raceboard/TaggingPanel.java | 65 +++++++++++++++---- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index a46677ffc5c..c132b1be686 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -3,6 +3,7 @@ package com.sap.sailing.gwt.ui.raceboard; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.Iterator; import java.util.List; import java.util.Map; import com.google.gwt.cell.client.AbstractCell; @@ -322,28 +323,58 @@ public class TaggingPanel extends ComponentWithoutSettings } } + public class TagPreviewPanel extends Panel { + private final CellList tagPreviewCellList; + private TagDTO previewTag; + private List listContainingPreviewTag; + private final TagCreationInputPanel inputField; + + public TagPreviewPanel(TagCreationInputPanel inputField) { + tagPreviewCellList = new CellList(new TagCell(), CellListResources.INSTANCE); + this.inputField = inputField; + add(tagPreviewCellList); + renderPreview(); + } + + public void renderPreview() { + previewTag = new TagDTO(inputField.getTagValue(), inputField.getCommentValue(), inputField.getImageURLValue(), "Author", new MillisecondsTimePoint(timer.getTime()), new MillisecondsTimePoint(timer.getTime())); + listContainingPreviewTag = new ArrayList(); + listContainingPreviewTag.add(previewTag); + tagPreviewCellList.setRowData(listContainingPreviewTag); + } + + @Override + public Iterator iterator() { + return null; + } + + @Override + public boolean remove(Widget child) { + return false; + } + + } + public class TagCreationInputPanel extends VerticalPanel { private TextBox tagTextBox, urlTextBox; private TextArea commentTextBox; public TagCreationInputPanel(StringMessages stringMessages) { setWidth("100%"); - VerticalPanel mainPanel = new VerticalPanel(); - mainPanel.setWidth("100%"); tagTextBox = new TextBox(); tagTextBox.setWidth("100%"); tagTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelTag()); tagTextBox.setTitle(stringMessages.tagLabelTag()); tagTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelTag()); - mainPanel.add(tagTextBox); + add(tagTextBox); urlTextBox = new TextBox(); urlTextBox.setWidth("100%"); urlTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelImageURL()); urlTextBox.setTitle(stringMessages.tagLabelImageURL()); urlTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); - mainPanel.add(urlTextBox); + add(urlTextBox); commentTextBox = new TextArea(); commentTextBox.setWidth("100%"); @@ -351,8 +382,7 @@ public class TaggingPanel extends ComponentWithoutSettings commentTextBox.setVisibleLines(4); commentTextBox.setTitle(stringMessages.tagLabelComment()); commentTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment()); - mainPanel.add(commentTextBox); - add(mainPanel); + add(commentTextBox); } @@ -497,15 +527,18 @@ public class TaggingPanel extends ComponentWithoutSettings } private final class EditTagButtonDialog extends DialogBox { - private final Button saveButton, cancelButton; + private final HorizontalPanel mainPanel; + private final TagPreviewPanel tagPreviewPanel; + private final VerticalPanel leftPanel; private final TagCreationInputPanel inputPanel; - private final VerticalPanel mainPanel; private final HorizontalPanel saveAndClosePanel; + private final Button saveButton, cancelButton; - public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, - StringMessages stringMessages) { + + public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, StringMessages stringMessages) { setText(stringMessages.tagEditCustomTagButton()); - mainPanel = new VerticalPanel(); + mainPanel = new HorizontalPanel(); + leftPanel = new VerticalPanel(); inputPanel = new TagCreationInputPanel(stringMessages); inputPanel.setTagValue(tagButton.getTag()); @@ -524,7 +557,6 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtonsTable.redraw(); hideDialog(); } - }); cancelButton = new Button(stringMessages.cancel()); @@ -535,14 +567,19 @@ public class TaggingPanel extends ComponentWithoutSettings hideDialog(); } }); + + tagPreviewPanel = new TagPreviewPanel(inputPanel); saveAndClosePanel = new HorizontalPanel(); saveAndClosePanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); saveAndClosePanel.add(saveButton); saveAndClosePanel.add(cancelButton); - mainPanel.add(inputPanel); - mainPanel.add(saveAndClosePanel); + leftPanel.add(inputPanel); + leftPanel.add(saveAndClosePanel); + + mainPanel.add(leftPanel); + mainPanel.add(tagPreviewPanel); setWidget(mainPanel); } From 8cef7408f32d36a0044cdc61f02088e2d999b7c9 Mon Sep 17 00:00:00 2001 From: D067890 Date: Mon, 13 Aug 2018 16:51:09 +0200 Subject: [PATCH 118/292] bug4104: Filter icon is now displayed on the right --- .../java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css index 534106fb7c8..8b3ea132603 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css @@ -1,5 +1,4 @@ .tagFilterContainer { - max-width: 425px; width: 100%; height: 2.25em; background-color: #FFFFFF; @@ -17,7 +16,7 @@ border: 1px solid #ccc; background-color: #eaeaea; border-radius: 4px; - margin-right: 6em; + margin-right: 2.9em; } .searchInput { @@ -67,7 +66,7 @@ } .filterButton { - right: 4.4em; + right: 0.8em; top: 0.2em; } From 171e7a67442abdd441cc7a72dbe334db2354462a Mon Sep 17 00:00:00 2001 From: D067890 Date: Mon, 13 Aug 2018 17:26:14 +0200 Subject: [PATCH 119/292] bug4104 :Added first TagPreviewPanel --- .../gwt/ui/raceboard/TaggingPanel.java | 86 ++++++++++++++----- .../gwt/ui/raceboard/tagging-panel.css | 4 + 2 files changed, 67 insertions(+), 23 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index e37a40db2f7..eca01890ce7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -18,6 +18,8 @@ import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.logical.shared.ValueChangeEvent; +import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; @@ -101,6 +103,7 @@ public class TaggingPanel extends ComponentWithoutSettings String inputPanelComment(); String inputPanelImageURL(); String footerPanel(); + String tagPreviewPanel(); } } @@ -323,16 +326,41 @@ public class TaggingPanel extends ComponentWithoutSettings } } - public class TagPreviewPanel extends Panel { + public class TagPreviewPanel extends VerticalPanel { private final CellList tagPreviewCellList; private TagDTO previewTag; private List listContainingPreviewTag; private final TagCreationInputPanel inputField; public TagPreviewPanel(TagCreationInputPanel inputField) { - tagPreviewCellList = new CellList(new TagCell(), CellListResources.INSTANCE); this.inputField = inputField; + tagPreviewCellList = new CellList(new TagCell(), CellListResources.INSTANCE); + + setStyleName(TagPanelResources.INSTANCE.style().tagPreviewPanel()); + add(tagPreviewCellList); + + inputField.getTagTextBox().addValueChangeHandler(new ValueChangeHandler() { + @Override + public void onValueChange(ValueChangeEvent event) { + renderPreview(); + } + + }); + inputField.getImageURLTextBox().addValueChangeHandler(new ValueChangeHandler() { + @Override + public void onValueChange(ValueChangeEvent event) { + renderPreview(); + } + + }); + inputField.getCommentTextArea().addValueChangeHandler(new ValueChangeHandler() { + @Override + public void onValueChange(ValueChangeEvent event) { + renderPreview(); + } + + }); renderPreview(); } @@ -356,8 +384,8 @@ public class TaggingPanel extends ComponentWithoutSettings } public class TagCreationInputPanel extends VerticalPanel { - private TextBox tagTextBox, urlTextBox; - private TextArea commentTextBox; + private TextBox tagTextBox, imageURLTextBox; + private TextArea commentTextArea; public TagCreationInputPanel(StringMessages stringMessages) { setWidth("100%"); @@ -369,33 +397,45 @@ public class TaggingPanel extends ComponentWithoutSettings tagTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelTag()); add(tagTextBox); - urlTextBox = new TextBox(); - urlTextBox.setWidth("100%"); - urlTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelImageURL()); - urlTextBox.setTitle(stringMessages.tagLabelImageURL()); - urlTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); - add(urlTextBox); + imageURLTextBox = new TextBox(); + imageURLTextBox.setWidth("100%"); + imageURLTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelImageURL()); + imageURLTextBox.setTitle(stringMessages.tagLabelImageURL()); + imageURLTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); + add(imageURLTextBox); - commentTextBox = new TextArea(); - commentTextBox.setWidth("100%"); - commentTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelComment()); - commentTextBox.setVisibleLines(4); - commentTextBox.setTitle(stringMessages.tagLabelComment()); - commentTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment()); - add(commentTextBox); + commentTextArea = new TextArea(); + commentTextArea.setWidth("100%"); + commentTextArea.setStyleName(TagPanelResources.INSTANCE.style().inputPanelComment()); + commentTextArea.setVisibleLines(4); + commentTextArea.setTitle(stringMessages.tagLabelComment()); + commentTextArea.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment()); + add(commentTextArea); } + public TextBox getTagTextBox() { + return tagTextBox; + } + + public TextBox getImageURLTextBox() { + return imageURLTextBox; + } + + public TextArea getCommentTextArea() { + return commentTextArea; + } + public String getTagValue() { return tagTextBox.getValue(); } public String getCommentValue() { - return commentTextBox.getValue(); + return commentTextArea.getValue(); } public String getImageURLValue() { - return urlTextBox.getValue(); + return imageURLTextBox.getValue(); } public void setTagValue(String tag) { @@ -403,17 +443,17 @@ public class TaggingPanel extends ComponentWithoutSettings } public void setCommentValue(String comment) { - commentTextBox.setValue(comment); + commentTextArea.setValue(comment); } public void setImageURLValue(String imageURL) { - urlTextBox.setValue(imageURL); + imageURLTextBox.setValue(imageURL); } public void clearAllValues() { tagTextBox.setText(""); - urlTextBox.setText(""); - commentTextBox.setText(""); + imageURLTextBox.setText(""); + commentTextArea.setText(""); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css index 07644714185..dedb996acd1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css @@ -13,6 +13,10 @@ b { margin-bottom: 0; } +.tagPreviewPanel{ + margin: 5px; +} + .tag { box-shadow: 2px 2px 3px lightgrey; margin-bottom: 5px; From 9c401d5669fa9268b97e76f196f1bc4bd4277db1 Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 14 Aug 2018 09:16:51 +0200 Subject: [PATCH 120/292] bug4104: Updated edit tag button dialog --- .../sailing/gwt/ui/client/StringMessages.java | 1 + .../gwt/ui/client/StringMessages.properties | 1 + .../ui/client/StringMessages_de.properties | 1 + .../gwt/ui/raceboard/TaggingPanel.java | 20 +++++++++++++------ 4 files changed, 17 insertions(+), 6 deletions(-) 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 f41039d002f..d9a8d203430 100755 --- 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 @@ -2119,4 +2119,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String tagEditFilter(); String tagEditCustomTagButton(); String tagSaveCustomTagButton(); + String tagPreview(); } 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 c3f90f4dbe5..7d918b15a9f 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 @@ -2114,3 +2114,4 @@ tagNotSpecified=Tag must not be empty! tagEditFilter=Edit filter tagEditCustomTagButton=Edit tag button tagSaveCustomTagButton=Save +tagPreview=Tag preview: \ 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 81dfef10d11..5e8667a6131 100755 --- 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 @@ -2109,3 +2109,4 @@ tagNotSpecified=Tag darf nicht leer sein! tagEditFilter=Bearbeite Filter tagEditCustomTagButton=Bearbeite Tag Button tagSaveCustomTagButton=Speichern +tagPreview=Tag Vorschau: \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index eca01890ce7..f379980324b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -331,13 +331,15 @@ public class TaggingPanel extends ComponentWithoutSettings private TagDTO previewTag; private List listContainingPreviewTag; private final TagCreationInputPanel inputField; + private final Label previewLabel; public TagPreviewPanel(TagCreationInputPanel inputField) { this.inputField = inputField; tagPreviewCellList = new CellList(new TagCell(), CellListResources.INSTANCE); + previewLabel = new Label(stringMessages.tagPreview()); setStyleName(TagPanelResources.INSTANCE.style().tagPreviewPanel()); - + add(previewLabel); add(tagPreviewCellList); inputField.getTagTextBox().addValueChangeHandler(new ValueChangeHandler() { @@ -591,11 +593,17 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onClick(ClickEvent event) { - tagButton.setTag(inputPanel.getTagValue()); - tagButton.setComment(inputPanel.getCommentValue()); - tagButton.setImageURL(inputPanel.getImageURLValue()); - customTagButtonsTable.redraw(); - hideDialog(); + if(!inputPanel.getTagValue().isEmpty()) { + tagButton.setText(inputPanel.getTagValue()); + tagButton.setTag(inputPanel.getTagValue()); + tagButton.setComment(inputPanel.getCommentValue()); + tagButton.setImageURL(inputPanel.getImageURLValue()); + customTagButtonsTable.redraw(); + hideDialog(); + } + else { + Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); + } } }); From 2cb8b90519f14277411f9e1835a83736645aa860 Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 14 Aug 2018 11:02:34 +0200 Subject: [PATCH 121/292] bug4104: Fixed not centering problem --- .../gwt/ui/raceboard/TaggingPanel.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index f379980324b..016b49d9752 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -336,7 +336,9 @@ public class TaggingPanel extends ComponentWithoutSettings public TagPreviewPanel(TagCreationInputPanel inputField) { this.inputField = inputField; tagPreviewCellList = new CellList(new TagCell(), CellListResources.INSTANCE); + tagPreviewCellList.setVisibleRange(0, 1); previewLabel = new Label(stringMessages.tagPreview()); + listContainingPreviewTag = new ArrayList(); setStyleName(TagPanelResources.INSTANCE.style().tagPreviewPanel()); add(previewLabel); @@ -367,22 +369,11 @@ public class TaggingPanel extends ComponentWithoutSettings } public void renderPreview() { - previewTag = new TagDTO(inputField.getTagValue(), inputField.getCommentValue(), inputField.getImageURLValue(), "Author", new MillisecondsTimePoint(timer.getTime()), new MillisecondsTimePoint(timer.getTime())); - listContainingPreviewTag = new ArrayList(); + listContainingPreviewTag.removeAll(listContainingPreviewTag); + previewTag = new TagDTO(inputField.getTagValue(), inputField.getCommentValue(), inputField.getImageURLValue(), "Author", new MillisecondsTimePoint(timer.getTime()), new MillisecondsTimePoint(timer.getTime())); listContainingPreviewTag.add(previewTag); tagPreviewCellList.setRowData(listContainingPreviewTag); } - - @Override - public Iterator iterator() { - return null; - } - - @Override - public boolean remove(Widget child) { - return false; - } - } public class TagCreationInputPanel extends VerticalPanel { @@ -466,6 +457,7 @@ public class TaggingPanel extends ComponentWithoutSettings private final CellTable customTagButtonsTable; private final TagCreationInputPanel inputPanel; private final Button addCustomTagButton; + private final TagPreviewPanel tagPreviewPanel; public EditCustomTagButtonsDialog(Panel customButtonsPanel) { setGlassEnabled(true); @@ -554,10 +546,13 @@ public class TaggingPanel extends ComponentWithoutSettings hideDialog(); } }); + + tagPreviewPanel = new TagPreviewPanel(inputPanel); mainPanel.add(customTagButtonsTable); mainPanel.add(inputPanel); mainPanel.add(addCustomTagButton); + mainPanel.add(tagPreviewPanel); mainPanel.add(closeButton); setWidget(mainPanel); From 305ae7e04194fdacfcb45cb4b46abef22c5bf4ab Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Tue, 14 Aug 2018 11:05:07 +0200 Subject: [PATCH 122/292] Bug 4104: Fixed translations & hide tag button table when no buttons are defined by the current user. --- .../sailing/gwt/ui/client/StringMessages.java | 1 + .../gwt/ui/client/StringMessages.properties | 1 + .../gwt/ui/client/StringMessages_de.properties | 3 ++- .../sailing/gwt/ui/raceboard/TaggingPanel.java | 16 +++++++++++----- 4 files changed, 15 insertions(+), 6 deletions(-) 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 f41039d002f..e8b1480fb61 100755 --- 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 @@ -2112,6 +2112,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String tagLabelTag(); String tagLabelComment(); String tagLabelImageURL(); + String tagLabelAction(); String tagCreateTag(); String tagEditCustomTagButtons(); String tagAddCustomTagButton(); 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 c3f90f4dbe5..a7cd789d6b8 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 @@ -2107,6 +2107,7 @@ tagSearchTags=Search tagLabelTag=Tag tagLabelComment=Comment tagLabelImageURL=Image URL +tagLabelAction=Action tagCreateTag=Create tag tagEditCustomTagButtons=Edit tag buttons tagAddCustomTagButton=Add tag button 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 81dfef10d11..b3a579e94c5 100755 --- 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 @@ -2100,8 +2100,9 @@ tagSelectedTags=Ausgewählte Tags tagsFilter=Tag Filter tagSearchTags=Suchen tagLabelTag=Tag -tagLabelComment=Comment +tagLabelComment=Kommentar tagLabelImageURL=Bild URL +tagLabelAction=Aktion tagCreateTag=Tag hinzufügen tagEditCustomTagButtons=Tag Buttons bearbeiten tagAddCustomTagButton=Tag Button hinzufügen diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 159bdcbba39..30f36d62ecf 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -396,6 +396,8 @@ public class TaggingPanel extends ComponentWithoutSettings private final Button addCustomTagButton; public EditCustomTagButtonsDialog(Panel customButtonsPanel) { + TagPanelStyle style = TagPanelResources.INSTANCE.style(); + setGlassEnabled(true); setText(stringMessages.tagEditCustomTagButtons()); @@ -450,13 +452,13 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtonsTable.addColumn(tagColumn, stringMessages.tagLabelTag()); customTagButtonsTable.addColumn(commentColumn, stringMessages.tagLabelComment()); customTagButtonsTable.addColumn(imageURLColumn, stringMessages.tagLabelImageURL()); - customTagButtonsTable.addColumn(actionsColumn, "Actions"); - customTagButtonsTable.setRowData(customTagButtons); + customTagButtonsTable.addColumn(actionsColumn, stringMessages.tagLabelAction()); + setRowData(customTagButtons); inputPanel = new TagCreationInputPanel(stringMessages); addCustomTagButton = new Button(stringMessages.tagAddCustomTagButton()); - addCustomTagButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); + addCustomTagButton.setStyleName(style.footerButton()); addCustomTagButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -466,7 +468,7 @@ public class TaggingPanel extends ComponentWithoutSettings inputPanel.clearAllValues(); customTagButtons.add(tagButton); customButtonsPanel.add(tagButton); - customTagButtonsTable.setRowData(customTagButtons); + setRowData(customTagButtons); } else { Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); } @@ -494,6 +496,11 @@ public class TaggingPanel extends ComponentWithoutSettings private void hideDialog() { this.hide(); } + + private void setRowData(List buttons) { + customTagButtonsTable.setRowData(buttons); + customTagButtonsTable.setVisible(buttons.size() > 0); + } } private final class EditTagButtonDialog extends DialogBox { @@ -765,5 +772,4 @@ public class TaggingPanel extends ComponentWithoutSettings public String getDependentCssClassName() { return "tags"; } - } From fc3fe05f5d06d4b5f0b1663b5e37e23d8100cea8 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Tue, 14 Aug 2018 11:06:45 +0200 Subject: [PATCH 123/292] Bug 4104: Moved TagFilterPanel to TaggingPanel --- .../gwt/ui/raceboard/TagFilterPanel.java | 292 ------------------ .../gwt/ui/raceboard/TaggingPanel.java | 265 ++++++++++++++++ 2 files changed, 265 insertions(+), 292 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java deleted file mode 100644 index 5073d827029..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java +++ /dev/null @@ -1,292 +0,0 @@ -package com.sap.sailing.gwt.ui.raceboard; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONParser; -import com.google.gwt.json.client.JSONValue; -import com.google.gwt.resources.client.ClientBundle; -import com.google.gwt.resources.client.CssResource; -import com.google.gwt.resources.client.ImageResource; -import com.google.gwt.storage.client.Storage; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.TextBox; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.client.TagListProvider; -import com.sap.sailing.gwt.ui.client.shared.filter.FilterUIFactory; -import com.sap.sailing.gwt.ui.client.shared.filter.FilterWithUI; -import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSets; -import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsDialog; -import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsJsonDeSerializer; -import com.sap.sailing.gwt.ui.raceboard.TagFilterPanel.TagFilterResources.TagFilterCss; -import com.sap.sailing.gwt.ui.shared.TagDTO; -import com.sap.sse.common.filter.FilterSet; -import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; - -/** - * - * @author Julian Rendl (D067890) - * - */ -public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWithUI { - - public interface TagFilterResources extends ClientBundle { - public static final TagFilterResources INSTANCE = GWT.create(TagFilterResources.class); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Clear.png") - ImageResource clearButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_CompetitorsFilter_INACTIVE.png") - ImageResource filterInactiveButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_CompetitorsFilter_ACTIVE.png") - ImageResource filterActiveButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Search.png") - ImageResource searchButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Settings.png") - ImageResource settingsButton(); - - @Source("tagging-filter.css") - TagFilterCss css(); - - public interface TagFilterCss extends CssResource { - String button(); - String hiddenButton(); - String clearButton(); - String searchButton(); - String settingsButton(); - String filterButton(); - String tagFilterContainer(); - String searchBox(); - String searchInput(); - String filterInactiveButtonBackgroundImage(); - String filterActiveButtonBackgroundImage(); - String clearButtonBackgroundImage(); - String searchButtonBackgroundImage(); - String settingsButtonBackgroundImage(); - } - - } - - private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailingAnalytics.raceBoard.tagsFilterSets"; - - private final static TagFilterCss css = TagFilterResources.INSTANCE.css(); - private final TextBox searchTextBox; - private final Button clearTextBoxButton; - private final Button filterSettingsButton; - private final TagsFilterSets tagFilterSets; - private final FlowPanel searchBoxPanel; - private final StringMessages stringMessages; - private final TagListProvider tagProvider; - - private FilterSet> lastActiveTagFilterSet; - - public TagFilterPanel(StringMessages stringMessages, TagListProvider tagProvider) { - css.ensureInjected(); - this.stringMessages = stringMessages; - this.tagProvider = tagProvider; - this.setStyleName(css.tagFilterContainer()); - - TagsFilterSets loadedTagsFilterSets = loadTagsFilterSets(); - if (loadedTagsFilterSets != null) { - tagFilterSets = loadedTagsFilterSets; - tagProvider.setTagsFilterSet(tagFilterSets.getActiveFilterSetWithGeneralizedType()); - } else { - tagFilterSets = createAndAddDefaultTagsFilter(); - storeTagsFilterSets(tagFilterSets); - } - - Button submitButton = new Button(); - submitButton.setStyleName(css.button()); - submitButton.addStyleName(css.searchButton()); - submitButton.addStyleName(css.searchButtonBackgroundImage()); - - searchTextBox = new TextBox(); - searchTextBox.getElement().setAttribute("placeholder", stringMessages.tagSearchTags()); - searchTextBox.addKeyUpHandler(this); - searchTextBox.setStyleName(css.searchInput()); - - clearTextBoxButton = new Button(); - clearTextBoxButton.setStyleName(css.button()); - clearTextBoxButton.addStyleName(css.clearButton()); - clearTextBoxButton.addStyleName(css.clearButtonBackgroundImage()); - clearTextBoxButton.addStyleName(css.hiddenButton()); - clearTextBoxButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - clearSelection(); - } - }); - - filterSettingsButton = new Button(""); - filterSettingsButton.setStyleName(css.button()); - filterSettingsButton.addStyleName(css.filterButton()); - filterSettingsButton.setTitle(stringMessages.tagsFilter()); - filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); - filterSettingsButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - showEditTagsFiltersDialog(); - } - }); - - searchBoxPanel = new FlowPanel(); - searchBoxPanel.setStyleName(css.searchBox()); - searchBoxPanel.add(submitButton); - searchBoxPanel.add(searchTextBox); - searchBoxPanel.add(clearTextBoxButton); - add(searchBoxPanel); - add(filterSettingsButton); - } - - private void showEditTagsFiltersDialog() { - TagsFilterSetsDialog tagsFilterSetsDialog = new TagsFilterSetsDialog(tagFilterSets, stringMessages, - new DialogCallback() { - @Override - public void ok(final TagsFilterSets newTagsFilterSets) { - tagFilterSets.getFilterSets().clear(); - tagFilterSets.getFilterSets().addAll(newTagsFilterSets.getFilterSets()); - tagFilterSets.setActiveFilterSet(newTagsFilterSets.getActiveFilterSet()); - - tagProvider.setTagsFilterSet(newTagsFilterSets.getActiveFilterSetWithGeneralizedType()); - tagProvider.updateFilteredTags(); - tagProvider.refresh(); - updateTagsFilterControlState(newTagsFilterSets); - storeTagsFilterSets(newTagsFilterSets); - } - - @Override - public void cancel() { - } - - }); - - tagsFilterSetsDialog.show(); - } - - /** - * Updates the tags filter checkbox state by setting its check mark and updating its label according to the current - * filter selected - */ - private void updateTagsFilterControlState(TagsFilterSets filterSets) { - String tagsFilterTitle = stringMessages.tagsFilter(); - FilterSet> activeFilterSet = filterSets.getActiveFilterSet(); - if (activeFilterSet != null) { - if (lastActiveTagFilterSet == null) { - filterSettingsButton.removeStyleName(css.filterInactiveButtonBackgroundImage()); - filterSettingsButton.addStyleName(css.filterActiveButtonBackgroundImage()); - } - lastActiveTagFilterSet = activeFilterSet; - } else { - if (lastActiveTagFilterSet != null) { - filterSettingsButton.removeStyleName(css.filterActiveButtonBackgroundImage()); - filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); - } - lastActiveTagFilterSet = null; - } - if (lastActiveTagFilterSet != null) { - filterSettingsButton.setTitle(tagsFilterTitle + " (" + lastActiveTagFilterSet.getName() + ")"); - } else { - filterSettingsButton.setTitle(tagsFilterTitle); - } - } - - private TagsFilterSets loadTagsFilterSets() { - TagsFilterSets result = null; - Storage localStorage = Storage.getLocalStorageIfSupported(); - if (localStorage != null) { - try { - String jsonAsLocalStore = localStorage.getItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY); - if (jsonAsLocalStore != null && !jsonAsLocalStore.isEmpty()) { - TagsFilterSetsJsonDeSerializer deserializer = new TagsFilterSetsJsonDeSerializer(); - JSONValue value = JSONParser.parseStrict(jsonAsLocalStore); - if (value.isObject() != null) { - result = deserializer.deserialize((JSONObject) value); - } - } - } catch (Exception e) { - // exception during loading of tag filters from local storage - } - } - return result; - } - - private void storeTagsFilterSets(TagsFilterSets newTagsFilterSets) { - Storage localStorage = Storage.getLocalStorageIfSupported(); - if (localStorage != null) { - // delete old value - localStorage.removeItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY); - - // store the tags filter set - TagsFilterSetsJsonDeSerializer serializer = new TagsFilterSetsJsonDeSerializer(); - JSONObject jsonObject = serializer.serialize(newTagsFilterSets); - localStorage.setItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY, jsonObject.toString()); - } - } - - private TagsFilterSets createAndAddDefaultTagsFilter() { - TagsFilterSets filterSets = new TagsFilterSets(); - - //TODO add standard filters here - - return filterSets; - } - - private void clearSelection() { - searchTextBox.setText(""); - clearTextBoxButton.addStyleName(css.hiddenButton()); - onKeyUp(null); - } - - @Override - public boolean matches(TagDTO object) { - // TODO Auto-generated method stub - return false; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String validate(StringMessages stringMessages) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getLocalizedName(StringMessages stringMessages) { - return getName(); - } - - @Override - public String getLocalizedDescription(StringMessages stringMessages) { - return getName(); - } - - @Override - public FilterWithUI copy() { - // TODO Auto-generated method stub - return null; - } - - @Override - public FilterUIFactory createUIFactory() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void onKeyUp(KeyUpEvent event) { - // TODO Auto-generated method stub - - } -} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 30f36d62ecf..8bc3fda1968 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -17,7 +17,12 @@ import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.KeyUpEvent; +import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONParser; +import com.google.gwt.json.client.JSONValue; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; import com.google.gwt.resources.client.ImageResource; @@ -27,6 +32,7 @@ import com.google.gwt.safehtml.shared.SafeHtmlBuilder; import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.safehtml.shared.SafeUri; import com.google.gwt.safehtml.shared.UriUtils; +import com.google.gwt.storage.client.Storage; import com.google.gwt.user.cellview.client.CellList; import com.google.gwt.user.cellview.client.CellTable; import com.google.gwt.user.cellview.client.TextColumn; @@ -56,14 +62,22 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.TagListProvider; import com.sap.sailing.gwt.ui.client.shared.controls.ImagesBarCell; +import com.sap.sailing.gwt.ui.client.shared.filter.FilterUIFactory; +import com.sap.sailing.gwt.ui.client.shared.filter.FilterWithUI; +import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSets; +import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsDialog; +import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsJsonDeSerializer; +import com.sap.sailing.gwt.ui.raceboard.TaggingPanel.TagFilterResources.TagFilterCss; import com.sap.sailing.gwt.ui.raceboard.TaggingPanel.TagPanelResources.TagPanelStyle; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.TagDTO; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.filter.FilterSet; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.Notification; import com.sap.sse.gwt.client.Notification.NotificationType; +import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; import com.sap.sse.gwt.client.player.Timer; import com.sap.sse.gwt.client.shared.components.Component; import com.sap.sse.gwt.client.shared.components.ComponentWithoutSettings; @@ -103,6 +117,46 @@ public class TaggingPanel extends ComponentWithoutSettings } } + public interface TagFilterResources extends ClientBundle { + public static final TagFilterResources INSTANCE = GWT.create(TagFilterResources.class); + + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Clear.png") + ImageResource clearButton(); + + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_CompetitorsFilter_INACTIVE.png") + ImageResource filterInactiveButton(); + + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_CompetitorsFilter_ACTIVE.png") + ImageResource filterActiveButton(); + + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Search.png") + ImageResource searchButton(); + + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Settings.png") + ImageResource settingsButton(); + + @Source("tagging-filter.css") + TagFilterCss css(); + + public interface TagFilterCss extends CssResource { + String button(); + String hiddenButton(); + String clearButton(); + String searchButton(); + String settingsButton(); + String filterButton(); + String tagFilterContainer(); + String searchBox(); + String searchInput(); + String filterInactiveButtonBackgroundImage(); + String filterActiveButtonBackgroundImage(); + String clearButtonBackgroundImage(); + String searchButtonBackgroundImage(); + String settingsButtonBackgroundImage(); + } + + } + public interface CellListResources extends CellList.Resources { public static final CellListResources INSTANCE = GWT.create(CellListResources.class); @@ -502,6 +556,217 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtonsTable.setVisible(buttons.size() > 0); } } + + private class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWithUI { + private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailingAnalytics.raceBoard.tagsFilterSets"; + + private final TagFilterCss css = TagFilterResources.INSTANCE.css(); + private final TextBox searchTextBox; + private final Button clearTextBoxButton; + private final Button filterSettingsButton; + private final TagsFilterSets tagFilterSets; + private final FlowPanel searchBoxPanel; + private final StringMessages stringMessages; + private final TagListProvider tagProvider; + + private FilterSet> lastActiveTagFilterSet; + + public TagFilterPanel(StringMessages stringMessages, TagListProvider tagProvider) { + css.ensureInjected(); + this.stringMessages = stringMessages; + this.tagProvider = tagProvider; + this.setStyleName(css.tagFilterContainer()); + + TagsFilterSets loadedTagsFilterSets = loadTagsFilterSets(); + if (loadedTagsFilterSets != null) { + tagFilterSets = loadedTagsFilterSets; + tagProvider.setTagsFilterSet(tagFilterSets.getActiveFilterSetWithGeneralizedType()); + } else { + tagFilterSets = createAndAddDefaultTagsFilter(); + storeTagsFilterSets(tagFilterSets); + } + + Button submitButton = new Button(); + submitButton.setStyleName(css.button()); + submitButton.addStyleName(css.searchButton()); + submitButton.addStyleName(css.searchButtonBackgroundImage()); + + searchTextBox = new TextBox(); + searchTextBox.getElement().setAttribute("placeholder", stringMessages.tagSearchTags()); + searchTextBox.addKeyUpHandler(this); + searchTextBox.setStyleName(css.searchInput()); + + clearTextBoxButton = new Button(); + clearTextBoxButton.setStyleName(css.button()); + clearTextBoxButton.addStyleName(css.clearButton()); + clearTextBoxButton.addStyleName(css.clearButtonBackgroundImage()); + clearTextBoxButton.addStyleName(css.hiddenButton()); + clearTextBoxButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + clearSelection(); + } + }); + + filterSettingsButton = new Button(""); + filterSettingsButton.setStyleName(css.button()); + filterSettingsButton.addStyleName(css.filterButton()); + filterSettingsButton.setTitle(stringMessages.tagsFilter()); + filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); + filterSettingsButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + showEditTagsFiltersDialog(); + } + }); + + searchBoxPanel = new FlowPanel(); + searchBoxPanel.setStyleName(css.searchBox()); + searchBoxPanel.add(submitButton); + searchBoxPanel.add(searchTextBox); + searchBoxPanel.add(clearTextBoxButton); + add(searchBoxPanel); + add(filterSettingsButton); + } + + private void showEditTagsFiltersDialog() { + TagsFilterSetsDialog tagsFilterSetsDialog = new TagsFilterSetsDialog(tagFilterSets, stringMessages, + new DialogCallback() { + @Override + public void ok(final TagsFilterSets newTagsFilterSets) { + tagFilterSets.getFilterSets().clear(); + tagFilterSets.getFilterSets().addAll(newTagsFilterSets.getFilterSets()); + tagFilterSets.setActiveFilterSet(newTagsFilterSets.getActiveFilterSet()); + + tagProvider.setTagsFilterSet(newTagsFilterSets.getActiveFilterSetWithGeneralizedType()); + tagProvider.updateFilteredTags(); + tagProvider.refresh(); + updateTagsFilterControlState(newTagsFilterSets); + storeTagsFilterSets(newTagsFilterSets); + } + + @Override + public void cancel() { + } + + }); + + tagsFilterSetsDialog.show(); + } + + /** + * Updates the tags filter checkbox state by setting its check mark and updating its label according to the current + * filter selected + */ + private void updateTagsFilterControlState(TagsFilterSets filterSets) { + String tagsFilterTitle = stringMessages.tagsFilter(); + FilterSet> activeFilterSet = filterSets.getActiveFilterSet(); + if (activeFilterSet != null) { + if (lastActiveTagFilterSet == null) { + filterSettingsButton.removeStyleName(css.filterInactiveButtonBackgroundImage()); + filterSettingsButton.addStyleName(css.filterActiveButtonBackgroundImage()); + } + lastActiveTagFilterSet = activeFilterSet; + } else { + if (lastActiveTagFilterSet != null) { + filterSettingsButton.removeStyleName(css.filterActiveButtonBackgroundImage()); + filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); + } + lastActiveTagFilterSet = null; + } + if (lastActiveTagFilterSet != null) { + filterSettingsButton.setTitle(tagsFilterTitle + " (" + lastActiveTagFilterSet.getName() + ")"); + } else { + filterSettingsButton.setTitle(tagsFilterTitle); + } + } + + private TagsFilterSets loadTagsFilterSets() { + TagsFilterSets result = null; + Storage localStorage = Storage.getLocalStorageIfSupported(); + if (localStorage != null) { + try { + String jsonAsLocalStore = localStorage.getItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY); + if (jsonAsLocalStore != null && !jsonAsLocalStore.isEmpty()) { + TagsFilterSetsJsonDeSerializer deserializer = new TagsFilterSetsJsonDeSerializer(); + JSONValue value = JSONParser.parseStrict(jsonAsLocalStore); + if (value.isObject() != null) { + result = deserializer.deserialize((JSONObject) value); + } + } + } catch (Exception e) { + // exception during loading of tag filters from local storage + } + } + return result; + } + + private void storeTagsFilterSets(TagsFilterSets newTagsFilterSets) { + Storage localStorage = Storage.getLocalStorageIfSupported(); + if (localStorage != null) { + // delete old value + localStorage.removeItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY); + + // store the tags filter set + TagsFilterSetsJsonDeSerializer serializer = new TagsFilterSetsJsonDeSerializer(); + JSONObject jsonObject = serializer.serialize(newTagsFilterSets); + localStorage.setItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY, jsonObject.toString()); + } + } + + private TagsFilterSets createAndAddDefaultTagsFilter() { + TagsFilterSets filterSets = new TagsFilterSets(); + + //TODO add standard filters here + + return filterSets; + } + + private void clearSelection() { + searchTextBox.setText(""); + clearTextBoxButton.addStyleName(css.hiddenButton()); + onKeyUp(null); + } + + @Override + public boolean matches(TagDTO object) { + return false; + } + + @Override + public String getName() { + return null; + } + + @Override + public String validate(StringMessages stringMessages) { + return null; + } + + @Override + public String getLocalizedName(StringMessages stringMessages) { + return getName(); + } + + @Override + public String getLocalizedDescription(StringMessages stringMessages) { + return getName(); + } + + @Override + public FilterWithUI copy() { + return null; + } + + @Override + public FilterUIFactory createUIFactory() { + return null; + } + + @Override + public void onKeyUp(KeyUpEvent event) { + } + } private final class EditTagButtonDialog extends DialogBox { private final Button saveButton, cancelButton; From f55f8366b51390d0453b034242c2af894d118668 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Tue, 14 Aug 2018 12:02:46 +0200 Subject: [PATCH 124/292] Bug 4104: Merged tagging-filter.css into tagging-panel.css --- .../gwt/ui/raceboard/TaggingPanel.java | 83 ++++++------ .../gwt/ui/raceboard/tagging-filter.css | 117 ----------------- .../gwt/ui/raceboard/tagging-panel.css | 119 ++++++++++++++++++ 3 files changed, 156 insertions(+), 163 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 8bc3fda1968..6fd38bf5c5d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -67,7 +67,6 @@ import com.sap.sailing.gwt.ui.client.shared.filter.FilterWithUI; import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSets; import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsDialog; import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsJsonDeSerializer; -import com.sap.sailing.gwt.ui.raceboard.TaggingPanel.TagFilterResources.TagFilterCss; import com.sap.sailing.gwt.ui.raceboard.TaggingPanel.TagPanelResources.TagPanelStyle; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.TagDTO; @@ -97,29 +96,6 @@ public class TaggingPanel extends ComponentWithoutSettings @Source("com/sap/sailing/gwt/ui/client/images/edit.png") ImageResource editIcon(); - @Source("tagging-panel.css") - public TagPanelStyle style(); - - public interface TagPanelStyle extends CssResource { - String tagPanel(); - String tag(); - String tagHeading(); - String tagCreated(); - String tagComment(); - String tagImage(); - String button(); - String footerButton(); - String tagButtonTable(); - String inputPanelTag(); - String inputPanelComment(); - String inputPanelImageURL(); - String footerPanel(); - } - } - - public interface TagFilterResources extends ClientBundle { - public static final TagFilterResources INSTANCE = GWT.create(TagFilterResources.class); - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Clear.png") ImageResource clearButton(); @@ -135,26 +111,41 @@ public class TaggingPanel extends ComponentWithoutSettings @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Settings.png") ImageResource settingsButton(); - @Source("tagging-filter.css") - TagFilterCss css(); + @Source("tagging-panel.css") + public TagPanelStyle style(); - public interface TagFilterCss extends CssResource { + public interface TagPanelStyle extends CssResource { + // tags + String tag(); + String tagPanel(); + String tagHeading(); + String tagCreated(); + String tagComment(); + String tagImage(); String button(); - String hiddenButton(); - String clearButton(); - String searchButton(); - String settingsButton(); - String filterButton(); + String footerButton(); + String tagButtonTable(); + String inputPanelTag(); + String inputPanelComment(); + String inputPanelImageURL(); + String footerPanel(); + + // filter tags + String tagFilterButton(); + String tagFilterHiddenButton(); + String tagFilterClearButton(); + String tagFilterSearchButton(); + String tagFilterSettingsButton(); + String tagFilterFilterButton(); String tagFilterContainer(); - String searchBox(); - String searchInput(); + String tagFilterSearchBox(); + String tagFilterSearchInput(); String filterInactiveButtonBackgroundImage(); String filterActiveButtonBackgroundImage(); String clearButtonBackgroundImage(); String searchButtonBackgroundImage(); String settingsButtonBackgroundImage(); } - } public interface CellListResources extends CellList.Resources { @@ -560,7 +551,7 @@ public class TaggingPanel extends ComponentWithoutSettings private class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWithUI { private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailingAnalytics.raceBoard.tagsFilterSets"; - private final TagFilterCss css = TagFilterResources.INSTANCE.css(); + private final TagPanelStyle css = TagPanelResources.INSTANCE.style(); private final TextBox searchTextBox; private final Button clearTextBoxButton; private final Button filterSettingsButton; @@ -587,20 +578,20 @@ public class TaggingPanel extends ComponentWithoutSettings } Button submitButton = new Button(); - submitButton.setStyleName(css.button()); - submitButton.addStyleName(css.searchButton()); + submitButton.setStyleName(css.tagFilterButton()); + submitButton.addStyleName(css.tagFilterSearchButton()); submitButton.addStyleName(css.searchButtonBackgroundImage()); searchTextBox = new TextBox(); searchTextBox.getElement().setAttribute("placeholder", stringMessages.tagSearchTags()); searchTextBox.addKeyUpHandler(this); - searchTextBox.setStyleName(css.searchInput()); + searchTextBox.setStyleName(css.tagFilterSearchInput()); clearTextBoxButton = new Button(); - clearTextBoxButton.setStyleName(css.button()); - clearTextBoxButton.addStyleName(css.clearButton()); + clearTextBoxButton.setStyleName(css.tagFilterButton()); + clearTextBoxButton.addStyleName(css.tagFilterClearButton()); clearTextBoxButton.addStyleName(css.clearButtonBackgroundImage()); - clearTextBoxButton.addStyleName(css.hiddenButton()); + clearTextBoxButton.addStyleName(css.tagFilterHiddenButton()); clearTextBoxButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -609,8 +600,8 @@ public class TaggingPanel extends ComponentWithoutSettings }); filterSettingsButton = new Button(""); - filterSettingsButton.setStyleName(css.button()); - filterSettingsButton.addStyleName(css.filterButton()); + filterSettingsButton.setStyleName(css.tagFilterButton()); + filterSettingsButton.addStyleName(css.tagFilterFilterButton()); filterSettingsButton.setTitle(stringMessages.tagsFilter()); filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); filterSettingsButton.addClickHandler(new ClickHandler() { @@ -621,7 +612,7 @@ public class TaggingPanel extends ComponentWithoutSettings }); searchBoxPanel = new FlowPanel(); - searchBoxPanel.setStyleName(css.searchBox()); + searchBoxPanel.setStyleName(css.tagFilterSearchBox()); searchBoxPanel.add(submitButton); searchBoxPanel.add(searchTextBox); searchBoxPanel.add(clearTextBoxButton); @@ -724,7 +715,7 @@ public class TaggingPanel extends ComponentWithoutSettings private void clearSelection() { searchTextBox.setText(""); - clearTextBoxButton.addStyleName(css.hiddenButton()); + clearTextBoxButton.addStyleName(css.tagFilterHiddenButton()); onKeyUp(null); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css deleted file mode 100644 index 534106fb7c8..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-filter.css +++ /dev/null @@ -1,117 +0,0 @@ -.tagFilterContainer { - max-width: 425px; - width: 100%; - height: 2.25em; - background-color: #FFFFFF; - margin-left: 0px; - margin-right: 0px; - margin-top: 5px; - font-size: 1rem; - position: relative; - overflow: hidden; - border: none; - outline: 0; -} - -.searchBox { - border: 1px solid #ccc; - background-color: #eaeaea; - border-radius: 4px; - margin-right: 6em; -} - -.searchInput { - font-size: .933333333333333em; - height: 2.142857142857143em; - width: 70%; - border: none; - background-color: #eaeaea; - padding: 0; - margin-left: 2.4em; - margin-right: 0px; - margin-bottom: 1px; - outline: 0 !important; -} - -.button { - position: absolute; - top: .4em; - width: 2em; - height: 2em; - background-repeat: no-repeat; - background-position: center; - border: none; - -webkit-border-radius: 4px; - border-radius: 4px; - text-indent: -9999em; - -webkit-transition: background-color .2s; - -moz-transition: background-color .2s; - -o-transition: background-color .2s; - -ms-transition: background-color .2s; - transition: background-color .2s; - cursor: pointer; -} - -.button:focus, .button:hover { - background-color: #e2e2e2; -} - -.clearButton { - right: 7.3em; - top: 0.2em; -} - -.settingsButton { - right: 2.4em; - top: 0.2em; -} - -.filterButton { - right: 4.4em; - top: 0.2em; -} - -.searchButton { - top: 0.2em; - left: 0.2em; - opacity: 0.3; -} - -.hiddenButton { - display: none; -} - -@sprite .clearButtonBackgroundImage { - gwt-image: "clearButton"; - width: 2em; - height: 2em; - background-size: contain; -} - -@sprite .filterInactiveButtonBackgroundImage { - gwt-image: "filterInactiveButton"; - width: 2em; - height: 2em; - background-size: contain; -} - -@sprite .filterActiveButtonBackgroundImage { - gwt-image: "filterActiveButton"; - width: 2em; - height: 2em; - background-size: contain; -} - -@sprite .searchButtonBackgroundImage { - gwt-image: "searchButton"; - width: 2em; - height: 2em; - background-size: contain; -} - -@sprite .settingsButtonBackgroundImage { - gwt-image: "settingsButton"; - width: 2em; - height: 2em; - background-size: contain; -} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css index 07644714185..80f54f51457 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css @@ -108,4 +108,123 @@ b { resize: none; margin-bottom: 5px; border-radius: 0px 0px 4px 4px; +} + +/**************************** Tag filtering ****************************/ +.tagFilterContainer { + max-width: 425px; + width: 100%; + height: 2.25em; + background-color: #FFFFFF; + margin-left: 0px; + margin-right: 0px; + margin-top: 5px; + font-size: 1rem; + position: relative; + overflow: hidden; + border: none; + outline: 0; +} + +.tagFilterSearchBox { + border: 1px solid #ccc; + background-color: #eaeaea; + border-radius: 4px; + margin-right: 6em; +} + +.tagFilterSearchInput { + font-size: .933333333333333em; + height: 2.142857142857143em; + width: 70%; + border: none; + background-color: #eaeaea; + padding: 0; + margin-left: 2.4em; + margin-right: 0px; + margin-bottom: 1px; + outline: 0 !important; +} + +.tagFilterButton { + position: absolute; + top: .4em; + width: 2em; + height: 2em; + background-repeat: no-repeat; + background-position: center; + border: none; + -webkit-border-radius: 4px; + border-radius: 4px; + text-indent: -9999em; + -webkit-transition: background-color .2s; + -moz-transition: background-color .2s; + -o-transition: background-color .2s; + -ms-transition: background-color .2s; + transition: background-color .2s; + cursor: pointer; +} + +.tagFilterButton:focus, .tagFilterButton:hover { + background-color: #e2e2e2; +} + +.tagFilterClearButton { + right: 7.3em; + top: 0.2em; +} + +.tagFilterSettingsButton { + right: 2.4em; + top: 0.2em; +} + +.tagFilterFilterButton { + right: 4.4em; + top: 0.2em; +} + +.tagFilterSearchButton { + top: 0.2em; + left: 0.2em; + opacity: 0.3; +} + +.tagFilterHiddenButton { + display: none; +} + +@sprite .clearButtonBackgroundImage { + gwt-image: "clearButton"; + width: 2em; + height: 2em; + background-size: contain; +} + +@sprite .filterInactiveButtonBackgroundImage { + gwt-image: "filterInactiveButton"; + width: 2em; + height: 2em; + background-size: contain; +} + +@sprite .filterActiveButtonBackgroundImage { + gwt-image: "filterActiveButton"; + width: 2em; + height: 2em; + background-size: contain; +} + +@sprite .searchButtonBackgroundImage { + gwt-image: "searchButton"; + width: 2em; + height: 2em; + background-size: contain; +} + +@sprite .settingsButtonBackgroundImage { + gwt-image: "settingsButton"; + width: 2em; + height: 2em; + background-size: contain; } \ No newline at end of file From 744b883aeebc7dc1a2028af0f21ebeba7105ea5c Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 14 Aug 2018 12:53:18 +0200 Subject: [PATCH 125/292] bug4104: Readded search functionality --- .../gwt/ui/raceboard/TaggingPanel.java | 60 ++++++++++++++++++- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index fa3537aa516..b0ff1881083 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -2,6 +2,7 @@ package com.sap.sailing.gwt.ui.raceboard; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; @@ -73,6 +74,9 @@ import com.sap.sailing.gwt.ui.raceboard.TaggingPanel.TagPanelResources.TagPanelS import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.TagDTO; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; +import com.sap.sse.common.filter.AbstractListFilter; +import com.sap.sse.common.filter.Filter; import com.sap.sse.common.filter.FilterSet; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.gwt.client.IconResources; @@ -625,6 +629,7 @@ public class TaggingPanel extends ComponentWithoutSettings private final FlowPanel searchBoxPanel; private final StringMessages stringMessages; private final TagListProvider tagProvider; + private final AbstractListFilter filter; private FilterSet> lastActiveTagFilterSet; @@ -642,6 +647,14 @@ public class TaggingPanel extends ComponentWithoutSettings tagFilterSets = createAndAddDefaultTagsFilter(); storeTagsFilterSets(tagFilterSets); } + + filter = new AbstractListFilter() { + @Override + public Iterable getStrings(TagDTO tag) { + final List result = new ArrayList<>(Arrays.asList(tag.getTag().toLowerCase(), tag.getComment())); + return result; + } + }; Button submitButton = new Button(); submitButton.setStyleName(css.tagFilterButton()); @@ -786,8 +799,9 @@ public class TaggingPanel extends ComponentWithoutSettings } @Override - public boolean matches(TagDTO object) { - return false; + public boolean matches(TagDTO tag) { + final Iterable lowercaseKeywords = Util.splitAlongWhitespaceRespectingDoubleQuotedPhrases(searchTextBox.getText().toLowerCase()); + return !Util.isEmpty(filter.applyFilter(lowercaseKeywords, Collections.singleton(tag))); } @Override @@ -819,9 +833,49 @@ public class TaggingPanel extends ComponentWithoutSettings public FilterUIFactory createUIFactory() { return null; } - + + /** + * @param event ignored; may be null + */ @Override public void onKeyUp(KeyUpEvent event) { + String newValue = searchTextBox.getValue(); + if (newValue.trim().isEmpty()) { + removeSearchFilter(); + clearTextBoxButton.addStyleName(css.tagFilterHiddenButton()); + } else { + if (newValue.length() >= 2) { + clearTextBoxButton.removeStyleName(css.tagFilterHiddenButton()); + ensureSearchFilterIsSet(); + tagProvider.setTagsFilterSet(tagProvider.getTagsFilterSet()); // + } + } + } + + private void ensureSearchFilterIsSet() { + if (tagProvider.getTagsFilterSet() == null || !Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { + FilterSet> newFilterSetWithThis = new FilterSet<>(getName()); + if (tagProvider.getTagsFilterSet() != null) { + for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { + newFilterSetWithThis.addFilter(oldFilter); + } + } + newFilterSetWithThis.addFilter(this); + tagProvider.setTagsFilterSet(newFilterSetWithThis); + } + } + + private void removeSearchFilter() { + if (tagProvider.getTagsFilterSet() != null + && Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { + FilterSet> newFilterSetWithThis = new FilterSet<>(tagProvider.getTagsFilterSet().getName()); + for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { + if (oldFilter != this) { + newFilterSetWithThis.addFilter(oldFilter); + } + } + tagProvider.setTagsFilterSet(newFilterSetWithThis); + } } } From cb42b2e06a067e19b5af67633fd61d9f0da3848e Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Tue, 14 Aug 2018 14:23:50 +0200 Subject: [PATCH 126/292] Bug 4104: Removed unsed Panel which got merged with TaggingPanel in previous commit. --- .../gwt/ui/raceboard/TagFilterPanel.java | 347 ------------------ 1 file changed, 347 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java deleted file mode 100644 index f7b63cc41f8..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java +++ /dev/null @@ -1,347 +0,0 @@ -package com.sap.sailing.gwt.ui.raceboard; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONParser; -import com.google.gwt.json.client.JSONValue; -import com.google.gwt.resources.client.ClientBundle; -import com.google.gwt.resources.client.CssResource; -import com.google.gwt.resources.client.ImageResource; -import com.google.gwt.storage.client.Storage; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.TextBox; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.client.TagListProvider; -import com.sap.sailing.gwt.ui.client.shared.filter.FilterUIFactory; -import com.sap.sailing.gwt.ui.client.shared.filter.FilterWithUI; -import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSets; -import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsDialog; -import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsJsonDeSerializer; -import com.sap.sailing.gwt.ui.raceboard.TagFilterPanel.TagFilterResources.TagFilterCss; -import com.sap.sailing.gwt.ui.shared.TagDTO; -import com.sap.sse.common.Util; -import com.sap.sse.common.filter.AbstractListFilter; -import com.sap.sse.common.filter.Filter; -import com.sap.sse.common.filter.FilterSet; -import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; - -/** - * - * @author Julian Rendl (D067890) - * - */ -public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWithUI { - - public interface TagFilterResources extends ClientBundle { - public static final TagFilterResources INSTANCE = GWT.create(TagFilterResources.class); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Clear.png") - ImageResource clearButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_CompetitorsFilter_INACTIVE.png") - ImageResource filterInactiveButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_CompetitorsFilter_ACTIVE.png") - ImageResource filterActiveButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Search.png") - ImageResource searchButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Settings.png") - ImageResource settingsButton(); - - @Source("tagging-filter.css") - TagFilterCss css(); - - public interface TagFilterCss extends CssResource { - String button(); - String hiddenButton(); - String clearButton(); - String searchButton(); - String settingsButton(); - String filterButton(); - String tagFilterContainer(); - String searchBox(); - String searchInput(); - String filterInactiveButtonBackgroundImage(); - String filterActiveButtonBackgroundImage(); - String clearButtonBackgroundImage(); - String searchButtonBackgroundImage(); - String settingsButtonBackgroundImage(); - } - - } - - private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailingAnalytics.raceBoard.tagsFilterSets"; - - private final static TagFilterCss css = TagFilterResources.INSTANCE.css(); - private final TextBox searchTextBox; - private final Button clearTextBoxButton; - private final Button filterSettingsButton; - private final TagsFilterSets tagFilterSets; - private final FlowPanel searchBoxPanel; - private final StringMessages stringMessages; - private final TagListProvider tagProvider; - private final AbstractListFilter filter; - - private FilterSet> lastActiveTagFilterSet; - - public TagFilterPanel(StringMessages stringMessages, TagListProvider tagProvider) { - css.ensureInjected(); - this.stringMessages = stringMessages; - this.tagProvider = tagProvider; - this.setStyleName(css.tagFilterContainer()); - - TagsFilterSets loadedTagsFilterSets = loadTagsFilterSets(); - if (loadedTagsFilterSets != null) { - tagFilterSets = loadedTagsFilterSets; - tagProvider.setTagsFilterSet(tagFilterSets.getActiveFilterSetWithGeneralizedType()); - } else { - tagFilterSets = createAndAddDefaultTagsFilter(); - storeTagsFilterSets(tagFilterSets); - } - - filter = new AbstractListFilter() { - @Override - public Iterable getStrings(TagDTO tag) { - final List result = new ArrayList<>(Arrays.asList(tag.getTag().toLowerCase(), tag.getComment())); - return result; - } - }; - - Button submitButton = new Button(); - submitButton.setStyleName(css.button()); - submitButton.addStyleName(css.searchButton()); - submitButton.addStyleName(css.searchButtonBackgroundImage()); - - searchTextBox = new TextBox(); - searchTextBox.getElement().setAttribute("placeholder", stringMessages.tagSearchTags()); - searchTextBox.addKeyUpHandler(this); - searchTextBox.setStyleName(css.searchInput()); - - clearTextBoxButton = new Button(); - clearTextBoxButton.setStyleName(css.button()); - clearTextBoxButton.addStyleName(css.clearButton()); - clearTextBoxButton.addStyleName(css.clearButtonBackgroundImage()); - clearTextBoxButton.addStyleName(css.hiddenButton()); - clearTextBoxButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - clearSelection(); - } - }); - - filterSettingsButton = new Button(""); - filterSettingsButton.setStyleName(css.button()); - filterSettingsButton.addStyleName(css.filterButton()); - filterSettingsButton.setTitle(stringMessages.tagsFilter()); - filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); - filterSettingsButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - showEditTagsFiltersDialog(); - } - }); - - searchBoxPanel = new FlowPanel(); - searchBoxPanel.setStyleName(css.searchBox()); - searchBoxPanel.add(submitButton); - searchBoxPanel.add(searchTextBox); - searchBoxPanel.add(clearTextBoxButton); - add(searchBoxPanel); - add(filterSettingsButton); - } - - private void showEditTagsFiltersDialog() { - TagsFilterSetsDialog tagsFilterSetsDialog = new TagsFilterSetsDialog(tagFilterSets, stringMessages, - new DialogCallback() { - @Override - public void ok(final TagsFilterSets newTagsFilterSets) { - tagFilterSets.getFilterSets().clear(); - tagFilterSets.getFilterSets().addAll(newTagsFilterSets.getFilterSets()); - tagFilterSets.setActiveFilterSet(newTagsFilterSets.getActiveFilterSet()); - - tagProvider.setTagsFilterSet(newTagsFilterSets.getActiveFilterSetWithGeneralizedType()); - tagProvider.updateFilteredTags(); - tagProvider.refresh(); - updateTagsFilterControlState(newTagsFilterSets); - storeTagsFilterSets(newTagsFilterSets); - } - - @Override - public void cancel() { - } - - }); - - tagsFilterSetsDialog.show(); - } - - /** - * Updates the tags filter checkbox state by setting its check mark and updating its label according to the current - * filter selected - */ - private void updateTagsFilterControlState(TagsFilterSets filterSets) { - String tagsFilterTitle = stringMessages.tagsFilter(); - FilterSet> activeFilterSet = filterSets.getActiveFilterSet(); - if (activeFilterSet != null) { - if (lastActiveTagFilterSet == null) { - filterSettingsButton.removeStyleName(css.filterInactiveButtonBackgroundImage()); - filterSettingsButton.addStyleName(css.filterActiveButtonBackgroundImage()); - } - lastActiveTagFilterSet = activeFilterSet; - } else { - if (lastActiveTagFilterSet != null) { - filterSettingsButton.removeStyleName(css.filterActiveButtonBackgroundImage()); - filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); - } - lastActiveTagFilterSet = null; - } - if (lastActiveTagFilterSet != null) { - filterSettingsButton.setTitle(tagsFilterTitle + " (" + lastActiveTagFilterSet.getName() + ")"); - } else { - filterSettingsButton.setTitle(tagsFilterTitle); - } - } - - private TagsFilterSets loadTagsFilterSets() { - TagsFilterSets result = null; - Storage localStorage = Storage.getLocalStorageIfSupported(); - if (localStorage != null) { - try { - String jsonAsLocalStore = localStorage.getItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY); - if (jsonAsLocalStore != null && !jsonAsLocalStore.isEmpty()) { - TagsFilterSetsJsonDeSerializer deserializer = new TagsFilterSetsJsonDeSerializer(); - JSONValue value = JSONParser.parseStrict(jsonAsLocalStore); - if (value.isObject() != null) { - result = deserializer.deserialize((JSONObject) value); - } - } - } catch (Exception e) { - // exception during loading of tag filters from local storage - } - } - return result; - } - - private void storeTagsFilterSets(TagsFilterSets newTagsFilterSets) { - Storage localStorage = Storage.getLocalStorageIfSupported(); - if (localStorage != null) { - // delete old value - localStorage.removeItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY); - - // store the tags filter set - TagsFilterSetsJsonDeSerializer serializer = new TagsFilterSetsJsonDeSerializer(); - JSONObject jsonObject = serializer.serialize(newTagsFilterSets); - localStorage.setItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY, jsonObject.toString()); - } - } - - private TagsFilterSets createAndAddDefaultTagsFilter() { - TagsFilterSets filterSets = new TagsFilterSets(); - - //TODO add standard filters here - - return filterSets; - } - - private void clearSelection() { - searchTextBox.setText(""); - clearTextBoxButton.addStyleName(css.hiddenButton()); - onKeyUp(null); - } - - @Override - public boolean matches(TagDTO tag) { - final Iterable lowercaseKeywords = Util.splitAlongWhitespaceRespectingDoubleQuotedPhrases(searchTextBox.getText().toLowerCase()); - return !Util.isEmpty(filter.applyFilter(lowercaseKeywords, Collections.singleton(tag))); - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String validate(StringMessages stringMessages) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getLocalizedName(StringMessages stringMessages) { - return getName(); - } - - @Override - public String getLocalizedDescription(StringMessages stringMessages) { - return getName(); - } - - @Override - public FilterWithUI copy() { - // TODO Auto-generated method stub - return null; - } - - @Override - public FilterUIFactory createUIFactory() { - // TODO Auto-generated method stub - return null; - } - - /** - * @param event ignored; may be null - */ - @Override - public void onKeyUp(KeyUpEvent event) { - String newValue = searchTextBox.getValue(); - if (newValue.trim().isEmpty()) { - removeSearchFilter(); - clearTextBoxButton.addStyleName(css.hiddenButton()); - } else { - if (newValue.length() >= 2) { - clearTextBoxButton.removeStyleName(css.hiddenButton()); - ensureSearchFilterIsSet(); - tagProvider.setTagsFilterSet(tagProvider.getTagsFilterSet()); // - } - } - } - - private void ensureSearchFilterIsSet() { - if (tagProvider.getTagsFilterSet() == null || !Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { - FilterSet> newFilterSetWithThis = new FilterSet<>(getName()); - if (tagProvider.getTagsFilterSet() != null) { - for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { - newFilterSetWithThis.addFilter(oldFilter); - } - } - newFilterSetWithThis.addFilter(this); - tagProvider.setTagsFilterSet(newFilterSetWithThis); - } - } - - private void removeSearchFilter() { - if (tagProvider.getTagsFilterSet() != null - && Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { - FilterSet> newFilterSetWithThis = new FilterSet<>(tagProvider.getTagsFilterSet().getName()); - for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { - if (oldFilter != this) { - newFilterSetWithThis.addFilter(oldFilter); - } - } - tagProvider.setTagsFilterSet(newFilterSetWithThis); - } - } -} \ No newline at end of file From a897609c733e11b2e30adcdf44b15c42d0515a1c Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 14 Aug 2018 15:39:28 +0200 Subject: [PATCH 127/292] bug4104: updated tag button edit dialog --- .../gwt/ui/raceboard/TagFilterPanel.java | 347 ------------------ .../gwt/ui/raceboard/TaggingPanel.java | 175 +++++---- 2 files changed, 82 insertions(+), 440 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java deleted file mode 100644 index f7b63cc41f8..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TagFilterPanel.java +++ /dev/null @@ -1,347 +0,0 @@ -package com.sap.sailing.gwt.ui.raceboard; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONParser; -import com.google.gwt.json.client.JSONValue; -import com.google.gwt.resources.client.ClientBundle; -import com.google.gwt.resources.client.CssResource; -import com.google.gwt.resources.client.ImageResource; -import com.google.gwt.storage.client.Storage; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.TextBox; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.client.TagListProvider; -import com.sap.sailing.gwt.ui.client.shared.filter.FilterUIFactory; -import com.sap.sailing.gwt.ui.client.shared.filter.FilterWithUI; -import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSets; -import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsDialog; -import com.sap.sailing.gwt.ui.client.shared.filter.TagsFilterSetsJsonDeSerializer; -import com.sap.sailing.gwt.ui.raceboard.TagFilterPanel.TagFilterResources.TagFilterCss; -import com.sap.sailing.gwt.ui.shared.TagDTO; -import com.sap.sse.common.Util; -import com.sap.sse.common.filter.AbstractListFilter; -import com.sap.sse.common.filter.Filter; -import com.sap.sse.common.filter.FilterSet; -import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; - -/** - * - * @author Julian Rendl (D067890) - * - */ -public class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWithUI { - - public interface TagFilterResources extends ClientBundle { - public static final TagFilterResources INSTANCE = GWT.create(TagFilterResources.class); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Clear.png") - ImageResource clearButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_CompetitorsFilter_INACTIVE.png") - ImageResource filterInactiveButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_CompetitorsFilter_ACTIVE.png") - ImageResource filterActiveButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Search.png") - ImageResource searchButton(); - - @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Settings.png") - ImageResource settingsButton(); - - @Source("tagging-filter.css") - TagFilterCss css(); - - public interface TagFilterCss extends CssResource { - String button(); - String hiddenButton(); - String clearButton(); - String searchButton(); - String settingsButton(); - String filterButton(); - String tagFilterContainer(); - String searchBox(); - String searchInput(); - String filterInactiveButtonBackgroundImage(); - String filterActiveButtonBackgroundImage(); - String clearButtonBackgroundImage(); - String searchButtonBackgroundImage(); - String settingsButtonBackgroundImage(); - } - - } - - private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailingAnalytics.raceBoard.tagsFilterSets"; - - private final static TagFilterCss css = TagFilterResources.INSTANCE.css(); - private final TextBox searchTextBox; - private final Button clearTextBoxButton; - private final Button filterSettingsButton; - private final TagsFilterSets tagFilterSets; - private final FlowPanel searchBoxPanel; - private final StringMessages stringMessages; - private final TagListProvider tagProvider; - private final AbstractListFilter filter; - - private FilterSet> lastActiveTagFilterSet; - - public TagFilterPanel(StringMessages stringMessages, TagListProvider tagProvider) { - css.ensureInjected(); - this.stringMessages = stringMessages; - this.tagProvider = tagProvider; - this.setStyleName(css.tagFilterContainer()); - - TagsFilterSets loadedTagsFilterSets = loadTagsFilterSets(); - if (loadedTagsFilterSets != null) { - tagFilterSets = loadedTagsFilterSets; - tagProvider.setTagsFilterSet(tagFilterSets.getActiveFilterSetWithGeneralizedType()); - } else { - tagFilterSets = createAndAddDefaultTagsFilter(); - storeTagsFilterSets(tagFilterSets); - } - - filter = new AbstractListFilter() { - @Override - public Iterable getStrings(TagDTO tag) { - final List result = new ArrayList<>(Arrays.asList(tag.getTag().toLowerCase(), tag.getComment())); - return result; - } - }; - - Button submitButton = new Button(); - submitButton.setStyleName(css.button()); - submitButton.addStyleName(css.searchButton()); - submitButton.addStyleName(css.searchButtonBackgroundImage()); - - searchTextBox = new TextBox(); - searchTextBox.getElement().setAttribute("placeholder", stringMessages.tagSearchTags()); - searchTextBox.addKeyUpHandler(this); - searchTextBox.setStyleName(css.searchInput()); - - clearTextBoxButton = new Button(); - clearTextBoxButton.setStyleName(css.button()); - clearTextBoxButton.addStyleName(css.clearButton()); - clearTextBoxButton.addStyleName(css.clearButtonBackgroundImage()); - clearTextBoxButton.addStyleName(css.hiddenButton()); - clearTextBoxButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - clearSelection(); - } - }); - - filterSettingsButton = new Button(""); - filterSettingsButton.setStyleName(css.button()); - filterSettingsButton.addStyleName(css.filterButton()); - filterSettingsButton.setTitle(stringMessages.tagsFilter()); - filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); - filterSettingsButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - showEditTagsFiltersDialog(); - } - }); - - searchBoxPanel = new FlowPanel(); - searchBoxPanel.setStyleName(css.searchBox()); - searchBoxPanel.add(submitButton); - searchBoxPanel.add(searchTextBox); - searchBoxPanel.add(clearTextBoxButton); - add(searchBoxPanel); - add(filterSettingsButton); - } - - private void showEditTagsFiltersDialog() { - TagsFilterSetsDialog tagsFilterSetsDialog = new TagsFilterSetsDialog(tagFilterSets, stringMessages, - new DialogCallback() { - @Override - public void ok(final TagsFilterSets newTagsFilterSets) { - tagFilterSets.getFilterSets().clear(); - tagFilterSets.getFilterSets().addAll(newTagsFilterSets.getFilterSets()); - tagFilterSets.setActiveFilterSet(newTagsFilterSets.getActiveFilterSet()); - - tagProvider.setTagsFilterSet(newTagsFilterSets.getActiveFilterSetWithGeneralizedType()); - tagProvider.updateFilteredTags(); - tagProvider.refresh(); - updateTagsFilterControlState(newTagsFilterSets); - storeTagsFilterSets(newTagsFilterSets); - } - - @Override - public void cancel() { - } - - }); - - tagsFilterSetsDialog.show(); - } - - /** - * Updates the tags filter checkbox state by setting its check mark and updating its label according to the current - * filter selected - */ - private void updateTagsFilterControlState(TagsFilterSets filterSets) { - String tagsFilterTitle = stringMessages.tagsFilter(); - FilterSet> activeFilterSet = filterSets.getActiveFilterSet(); - if (activeFilterSet != null) { - if (lastActiveTagFilterSet == null) { - filterSettingsButton.removeStyleName(css.filterInactiveButtonBackgroundImage()); - filterSettingsButton.addStyleName(css.filterActiveButtonBackgroundImage()); - } - lastActiveTagFilterSet = activeFilterSet; - } else { - if (lastActiveTagFilterSet != null) { - filterSettingsButton.removeStyleName(css.filterActiveButtonBackgroundImage()); - filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); - } - lastActiveTagFilterSet = null; - } - if (lastActiveTagFilterSet != null) { - filterSettingsButton.setTitle(tagsFilterTitle + " (" + lastActiveTagFilterSet.getName() + ")"); - } else { - filterSettingsButton.setTitle(tagsFilterTitle); - } - } - - private TagsFilterSets loadTagsFilterSets() { - TagsFilterSets result = null; - Storage localStorage = Storage.getLocalStorageIfSupported(); - if (localStorage != null) { - try { - String jsonAsLocalStore = localStorage.getItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY); - if (jsonAsLocalStore != null && !jsonAsLocalStore.isEmpty()) { - TagsFilterSetsJsonDeSerializer deserializer = new TagsFilterSetsJsonDeSerializer(); - JSONValue value = JSONParser.parseStrict(jsonAsLocalStore); - if (value.isObject() != null) { - result = deserializer.deserialize((JSONObject) value); - } - } - } catch (Exception e) { - // exception during loading of tag filters from local storage - } - } - return result; - } - - private void storeTagsFilterSets(TagsFilterSets newTagsFilterSets) { - Storage localStorage = Storage.getLocalStorageIfSupported(); - if (localStorage != null) { - // delete old value - localStorage.removeItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY); - - // store the tags filter set - TagsFilterSetsJsonDeSerializer serializer = new TagsFilterSetsJsonDeSerializer(); - JSONObject jsonObject = serializer.serialize(newTagsFilterSets); - localStorage.setItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY, jsonObject.toString()); - } - } - - private TagsFilterSets createAndAddDefaultTagsFilter() { - TagsFilterSets filterSets = new TagsFilterSets(); - - //TODO add standard filters here - - return filterSets; - } - - private void clearSelection() { - searchTextBox.setText(""); - clearTextBoxButton.addStyleName(css.hiddenButton()); - onKeyUp(null); - } - - @Override - public boolean matches(TagDTO tag) { - final Iterable lowercaseKeywords = Util.splitAlongWhitespaceRespectingDoubleQuotedPhrases(searchTextBox.getText().toLowerCase()); - return !Util.isEmpty(filter.applyFilter(lowercaseKeywords, Collections.singleton(tag))); - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String validate(StringMessages stringMessages) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getLocalizedName(StringMessages stringMessages) { - return getName(); - } - - @Override - public String getLocalizedDescription(StringMessages stringMessages) { - return getName(); - } - - @Override - public FilterWithUI copy() { - // TODO Auto-generated method stub - return null; - } - - @Override - public FilterUIFactory createUIFactory() { - // TODO Auto-generated method stub - return null; - } - - /** - * @param event ignored; may be null - */ - @Override - public void onKeyUp(KeyUpEvent event) { - String newValue = searchTextBox.getValue(); - if (newValue.trim().isEmpty()) { - removeSearchFilter(); - clearTextBoxButton.addStyleName(css.hiddenButton()); - } else { - if (newValue.length() >= 2) { - clearTextBoxButton.removeStyleName(css.hiddenButton()); - ensureSearchFilterIsSet(); - tagProvider.setTagsFilterSet(tagProvider.getTagsFilterSet()); // - } - } - } - - private void ensureSearchFilterIsSet() { - if (tagProvider.getTagsFilterSet() == null || !Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { - FilterSet> newFilterSetWithThis = new FilterSet<>(getName()); - if (tagProvider.getTagsFilterSet() != null) { - for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { - newFilterSetWithThis.addFilter(oldFilter); - } - } - newFilterSetWithThis.addFilter(this); - tagProvider.setTagsFilterSet(newFilterSetWithThis); - } - } - - private void removeSearchFilter() { - if (tagProvider.getTagsFilterSet() != null - && Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { - FilterSet> newFilterSetWithThis = new FilterSet<>(tagProvider.getTagsFilterSet().getName()); - for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { - if (oldFilter != this) { - newFilterSetWithThis.addFilter(oldFilter); - } - } - tagProvider.setTagsFilterSet(newFilterSetWithThis); - } - } -} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index b0ff1881083..4e54f7141bc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -15,6 +15,7 @@ import com.google.gwt.core.shared.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.EventTarget; import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.dom.client.Style.Overflow; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; @@ -44,7 +45,6 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HeaderPanel; -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.ScrollPanel; @@ -421,6 +421,8 @@ public class TaggingPanel extends ComponentWithoutSettings previewTag = new TagDTO(inputField.getTagValue(), inputField.getCommentValue(), inputField.getImageURLValue(), "Author", new MillisecondsTimePoint(timer.getTime()), new MillisecondsTimePoint(timer.getTime())); listContainingPreviewTag.add(previewTag); tagPreviewCellList.setRowData(listContainingPreviewTag); + + setVisible(!inputField.getTagValue().isEmpty()); } } @@ -500,22 +502,25 @@ public class TaggingPanel extends ComponentWithoutSettings private class EditCustomTagButtonsDialog extends DialogBox { - private final Button closeButton; + private final Button closeButton, saveChangesButton, cancelChangesButton; private final Panel mainPanel; private final CellTable customTagButtonsTable; private final TagCreationInputPanel inputPanel; private final Button addCustomTagButton; private final TagPreviewPanel tagPreviewPanel; + private final FlowPanel controlButttonPanel; + private TagButton selectedTagButton = null; public EditCustomTagButtonsDialog(Panel customButtonsPanel) { - TagPanelStyle style = TagPanelResources.INSTANCE.style(); - + TagPanelStyle style = TagPanelResources.INSTANCE.style(); setGlassEnabled(true); setText(stringMessages.tagEditCustomTagButtons()); + setWidth("350px"); mainPanel = new VerticalPanel(); - mainPanel.setWidth("100px"); - + mainPanel.setWidth("100%"); + + //Table with tag buttons customTagButtonsTable = new CellTable(); customTagButtonsTable.setStyleName(TagPanelResources.INSTANCE.style().tagButtonTable()); TextColumn tagColumn = new TextColumn() { @@ -524,18 +529,18 @@ public class TaggingPanel extends ComponentWithoutSettings return button.getTag(); } }; - TextColumn commentColumn = new TextColumn() { - @Override - public String getValue(TagButton button) { - return button.getComment(); - } - }; TextColumn imageURLColumn = new TextColumn() { @Override public String getValue(TagButton button) { return button.getImageURL(); } }; + TextColumn commentColumn = new TextColumn() { + @Override + public String getValue(TagButton button) { + return button.getComment(); + } + }; ImagesBarColumn actionsColumn = new ImagesBarColumn( new EditTagButtonsImagesBarCell(stringMessages)); @@ -547,28 +552,35 @@ public class TaggingPanel extends ComponentWithoutSettings customButtonsPanel.remove(button); customTagButtonsTable.setRowData(customTagButtons); } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { - EditTagButtonDialog editCustomTagButtonDialog = new EditTagButtonDialog(button, - customTagButtonsTable, stringMessages); - // scheduler is used because otherwise DialogBox would not be centered properly + selectedTagButton = button; - Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { - public void execute() { - editCustomTagButtonDialog.show(); - editCustomTagButtonDialog.center(); - } - }); + inputPanel.setTagValue(button.getTag()); + inputPanel.setImageURLValue(button.getImageURL()); + inputPanel.setCommentValue(button.getComment()); + + tagPreviewPanel.renderPreview(); + + saveChangesButton.setVisible(true); + cancelChangesButton.setVisible(true); + addCustomTagButton.setVisible(false); + customTagButtonsTable.setVisible(false); } } }); customTagButtonsTable.addColumn(tagColumn, stringMessages.tagLabelTag()); - customTagButtonsTable.addColumn(commentColumn, stringMessages.tagLabelComment()); customTagButtonsTable.addColumn(imageURLColumn, stringMessages.tagLabelImageURL()); + customTagButtonsTable.addColumn(commentColumn, stringMessages.tagLabelComment()); customTagButtonsTable.addColumn(actionsColumn, stringMessages.tagLabelAction()); setRowData(customTagButtons); + //input panel inputPanel = new TagCreationInputPanel(stringMessages); + //contol buttons + controlButttonPanel = new FlowPanel(); + controlButttonPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); + addCustomTagButton = new Button(stringMessages.tagAddCustomTagButton()); addCustomTagButton.setStyleName(style.footerButton()); addCustomTagButton.addClickHandler(new ClickHandler() { @@ -577,7 +589,9 @@ public class TaggingPanel extends ComponentWithoutSettings if (inputPanel.getTagValue().length() > 0) { TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), inputPanel.getImageURLValue(), inputPanel.getCommentValue()); - inputPanel.clearAllValues(); + inputPanel.clearAllValues(); + tagPreviewPanel.renderPreview(); + customTagButtons.add(tagButton); customButtonsPanel.add(tagButton); setRowData(customTagButtons); @@ -586,22 +600,65 @@ public class TaggingPanel extends ComponentWithoutSettings } } }); + + saveChangesButton = new Button(stringMessages.save()); + saveChangesButton.setVisible(false); + saveChangesButton.setStyleName(style.footerButton()); + saveChangesButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + if (inputPanel.getTagValue().length() > 0) { + selectedTagButton.setText(inputPanel.getTagValue()); + selectedTagButton.setTag(inputPanel.getTagValue()); + selectedTagButton.setComment(inputPanel.getCommentValue()); + selectedTagButton.setImageURL(inputPanel.getImageURLValue()); + inputPanel.clearAllValues(); + tagPreviewPanel.renderPreview(); + customTagButtonsTable.redraw(); + + saveChangesButton.setVisible(false); + cancelChangesButton.setVisible(false); + addCustomTagButton.setVisible(true); + selectedTagButton = null; + setRowData(customTagButtons); + } else { + Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); + } + } + }); + + cancelChangesButton = new Button(stringMessages.cancel()); + cancelChangesButton.setVisible(false); + cancelChangesButton.setStyleName(style.footerButton()); + cancelChangesButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + inputPanel.clearAllValues(); + tagPreviewPanel.renderPreview(); + saveChangesButton.setVisible(false); + cancelChangesButton.setVisible(false); + addCustomTagButton.setVisible(true); + setRowData(customTagButtons); + } + }); closeButton = new Button(stringMessages.close()); closeButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); - closeButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { hideDialog(); } }); + controlButttonPanel.add(addCustomTagButton); + controlButttonPanel.add(cancelChangesButton); + controlButttonPanel.add(saveChangesButton); tagPreviewPanel = new TagPreviewPanel(inputPanel); mainPanel.add(customTagButtonsTable); mainPanel.add(inputPanel); - mainPanel.add(addCustomTagButton); + mainPanel.add(controlButttonPanel); mainPanel.add(tagPreviewPanel); mainPanel.add(closeButton); @@ -879,74 +936,6 @@ public class TaggingPanel extends ComponentWithoutSettings } } - private final class EditTagButtonDialog extends DialogBox { - private final HorizontalPanel mainPanel; - private final TagPreviewPanel tagPreviewPanel; - private final VerticalPanel leftPanel; - private final TagCreationInputPanel inputPanel; - private final HorizontalPanel saveAndClosePanel; - private final Button saveButton, cancelButton; - - - public EditTagButtonDialog(TagButton tagButton, CellTable customTagButtonsTable, StringMessages stringMessages) { - setText(stringMessages.tagEditCustomTagButton()); - mainPanel = new HorizontalPanel(); - leftPanel = new VerticalPanel(); - - inputPanel = new TagCreationInputPanel(stringMessages); - inputPanel.setTagValue(tagButton.getTag()); - inputPanel.setCommentValue(tagButton.getComment()); - inputPanel.setImageURLValue(tagButton.getImageURL()); - - saveButton = new Button(stringMessages.tagSaveCustomTagButton()); - saveButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); - saveButton.addClickHandler(new ClickHandler() { - - @Override - public void onClick(ClickEvent event) { - if(!inputPanel.getTagValue().isEmpty()) { - tagButton.setText(inputPanel.getTagValue()); - tagButton.setTag(inputPanel.getTagValue()); - tagButton.setComment(inputPanel.getCommentValue()); - tagButton.setImageURL(inputPanel.getImageURLValue()); - customTagButtonsTable.redraw(); - hideDialog(); - } - else { - Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); - } - } - }); - - cancelButton = new Button(stringMessages.cancel()); - cancelButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); - cancelButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - hideDialog(); - } - }); - - tagPreviewPanel = new TagPreviewPanel(inputPanel); - - saveAndClosePanel = new HorizontalPanel(); - saveAndClosePanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); - saveAndClosePanel.add(saveButton); - saveAndClosePanel.add(cancelButton); - - leftPanel.add(inputPanel); - leftPanel.add(saveAndClosePanel); - - mainPanel.add(leftPanel); - mainPanel.add(tagPreviewPanel); - setWidget(mainPanel); - } - - private void hideDialog() { - this.hide(); - } - } - private final HeaderPanel panel; private final TagCreationPanel tagCreationPanel; private final Panel filterbarPanel; From 5f60e5e33119c191c9c2a7ac6394a97a8805d56e Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Tue, 14 Aug 2018 15:48:42 +0200 Subject: [PATCH 128/292] Bug 4104: Added permission check in backend & allows admin to delete tags from other users. --- .../sailing/gwt/ui/client/SailingService.java | 2 +- .../gwt/ui/client/SailingServiceAsync.java | 2 +- .../sailing/gwt/ui/client/StringMessages.java | 3 ++ .../gwt/ui/client/StringMessages.properties | 5 ++- .../ui/client/StringMessages_de.properties | 5 ++- .../gwt/ui/raceboard/TaggingPanel.java | 37 +++++++++++------- .../gwt/ui/server/SailingServiceImpl.java | 38 ++++++++++++++----- .../stringmessages/StringMessages.properties | 5 ++- .../StringMessages_de.properties | 5 ++- 9 files changed, 72 insertions(+), 30 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 3956703e8d7..4bd6aeed9a9 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 @@ -539,7 +539,7 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS */ void addCourseDefinitionToRaceLog(String leaderboardName, String raceColumnName, String fleetName, List> course) throws NotFoundException; - void addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, + SuccessInfo addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, String imageURL, TimePoint raceTimepoint); SuccessInfo removeTagFromRaceLog(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index 679b21c7108..63a028fb1ad 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -728,7 +728,7 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan List> course, AsyncCallback callback); void addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, - String imageURL, TimePoint raceTimepoint, AsyncCallback asyncCallback); + String imageURL, TimePoint raceTimepoint, AsyncCallback asyncCallback); void removeTagFromRaceLog(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag, AsyncCallback asyncCallback); 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 8e7c801f37c..f16a955e84c 100755 --- 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 @@ -2103,8 +2103,11 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String tagAddTag(); String tagAddedSuccessfully(); String tagNotAdded(); + String tagNotAddedReason(String reason); String tagNotLoaded(); String tagNotLoggedIn(); + String tagNotRemoved(); + String tagRemovedSuccessfully(); String tagFilterExplanation(); String tagSelectedTags(); String tagsFilter(); 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 868c0c92425..2eef32796d1 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 @@ -2098,8 +2098,11 @@ tagNoTagsFound=No tags found! tagAddTag=Add tag tagAddedSuccessfully=Added tag successfully tagNotAdded=Could not add new tag! +tagNotAddedReason=Could not add new tag! Reason: {0} tagNotLoaded=Could not load tags! tagNotLoggedIn=Please log in to add new tags! +tagNotRemoved=Could not remove tag! +tagRemovedSuccessfully=Successfully removed tag tagFilterExplanation=The filter will show all tags matching the criterias: tagSelectedTags=Selected Tags tagsFilter=Tags Filter @@ -2115,4 +2118,4 @@ tagNotSpecified=Tag must not be empty! tagEditFilter=Edit filter tagEditCustomTagButton=Edit tag button tagSaveCustomTagButton=Save -tagPreview=Tag preview: \ No newline at end of file +tagPreview=Tag preview: 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 f6734136af5..fecad35cc5e 100755 --- 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 @@ -2092,9 +2092,12 @@ tagCreated=(erstellt von {0} am {1}) tagNoTagsFound=Keine Tags gefunden! tagAddTag=Tag hinzufügen tagAddedSuccessfully=Tag erfolgreich hinzugefügt -tagNotAdded=Neuer Tag konnte nicht gespeichert werden! +tagNotAdded=Tag konnte nicht gespeichert werden! +tagNotAddedReason=Tag konnte nicht gespeichert werden! Grund: {0} tagNotLoaded=Tags konnten nicht geladen werden! tagNotLoggedIn=Bitte loggen Sie sich ein um einem Rennen Tags hinzuzufügen! +tagNotRemoved=Tag konnte nicht entfernt werden! +tagRemovedSuccessfully=Tag erfolgreich entfernt tagFilterExplanation=Der Filter filtert alle Tags, welche die nachfolgenden Kriterien erfüllen: tagSelectedTags=Ausgewählte Tags tagsFilter=Tag Filter diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index b0ff1881083..1e3c2bf64a0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -224,7 +224,7 @@ public class TaggingPanel extends ComponentWithoutSettings SafeHtml cell; if (userService.getCurrentUser() != null - && tag.getUsername().equals(userService.getCurrentUser().getName())) { + && (tag.getUsername().equals(userService.getCurrentUser().getName()) || userService.getCurrentUser().hasRole("admin"))) { cell = tagCellTemplate.cellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), tagPanelStyle.tagCreated(), safeTag, safeCreated, content); } else { @@ -334,7 +334,7 @@ public class TaggingPanel extends ComponentWithoutSettings createTagFromTextBoxes.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - if (isAuthorizedAndRaceLogAvailable()) { + if (isLoggedInAndRaceLogAvailable()) { addTagToRaceLog(inputPanel.getTagValue(), inputPanel.getCommentValue(), inputPanel.getImageURLValue()); inputPanel.clearAllValues(); @@ -348,7 +348,7 @@ public class TaggingPanel extends ComponentWithoutSettings editCustomTagButtons.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - if (isAuthorizedAndRaceLogAvailable()) { + if (isLoggedInAndRaceLogAvailable()) { EditCustomTagButtonsDialog editCustomTagButtonsDialog = new EditCustomTagButtonsDialog( customButtonsPanel); @@ -1048,18 +1048,22 @@ public class TaggingPanel extends ComponentWithoutSettings } private void addTagToRaceLog(String tag, String comment, String imageURL) { - if (isAuthorizedAndRaceLogAvailable()) { + if (isLoggedInAndRaceLogAvailable()) { if (tag.length() > 0) { sailingService.addTagToRaceLog(leaderboardName, raceColumn.getName(), fleet.getName(), tag, comment, - imageURL, new MillisecondsTimePoint(timer.getTime()), new AsyncCallback() { + imageURL, new MillisecondsTimePoint(timer.getTime()), new AsyncCallback() { @Override public void onFailure(Throwable caught) { - Notification.notify(stringMessages.tagNotAdded(), NotificationType.ERROR); + Notification.notify(stringMessages.tagNotAddedReason(caught.toString()), NotificationType.ERROR); } @Override - public void onSuccess(Void result) { - Notification.notify(stringMessages.tagAddedSuccessfully(), NotificationType.INFO); + public void onSuccess(SuccessInfo result) { + if (result.isSuccessful()) { + Notification.notify(stringMessages.tagAddedSuccessfully(), NotificationType.INFO); + } else { + Notification.notify(stringMessages.tagNotAddedReason(result.getMessage()), NotificationType.ERROR); + } } }); } else { @@ -1074,20 +1078,25 @@ public class TaggingPanel extends ComponentWithoutSettings new AsyncCallback() { @Override public void onFailure(Throwable caught) { - Notification.notify("Could not remove tag!", NotificationType.ERROR); + Notification.notify(stringMessages.tagNotRemoved(), NotificationType.ERROR); + GWT.log(caught.toString()); } @Override public void onSuccess(SuccessInfo result) { - tagListProvider.getAllTags().remove(tag); - updateContent(); - Notification.notify("Removed tag successfully", NotificationType.SUCCESS); + if (result.isSuccessful()) { + tagListProvider.getAllTags().remove(tag); + updateContent(); + Notification.notify(stringMessages.tagRemovedSuccessfully(), NotificationType.SUCCESS); + } else { + Notification.notify(stringMessages.tagNotRemoved() + " " + result.getMessage(), NotificationType.ERROR); + } } }); } - private boolean isAuthorizedAndRaceLogAvailable() { - return !(userService.getCurrentUser() == null || leaderboardName == null || raceColumn == null && fleet == null); + private boolean isLoggedInAndRaceLogAvailable() { + return !(userService.getCurrentUser() == null || leaderboardName == null || raceColumn == null || fleet == null); } private void updateContent() { 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 3f7755a3b7e..bf63db9ac72 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 @@ -60,6 +60,8 @@ import javax.servlet.http.HttpServletRequest; import org.apache.http.client.ClientProtocolException; import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authz.AuthorizationException; +import org.apache.shiro.subject.Subject; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; @@ -6048,27 +6050,43 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, + public SuccessInfo addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, String imageURL, TimePoint raceTimepoint) { - RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); - raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, raceTimepoint, getService().getServerAuthor(), - raceLog.getCurrentPassId())); + SuccessInfo successInfo = new SuccessInfo(true, null, null, null); + try { + SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); + raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, raceTimepoint, getService().getServerAuthor(), + raceLog.getCurrentPassId())); + } catch (AuthorizationException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), null, null); + } + return successInfo; } @Override - public SuccessInfo removeTagFromRaceLog(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) { + public SuccessInfo removeTagFromRaceLog(String leaderboardName, String raceColumnName, String fleetName, + TagDTO tag) { SuccessInfo successInfo = new SuccessInfo(true, null, null, null); RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); TagFinder tagFinder = new TagFinder(raceLog, tag.getCreatedAt().minus(1), tag.getCreatedAt().plus(1)); List foundTagEvents = tagFinder.analyze(); for (RaceLogTagEvent tagEvent : foundTagEvents) { - if (tagEvent.getTag().equals(tag.getTag()) - && tagEvent.getComment().equals(tag.getComment()) + if (tagEvent.getTag().equals(tag.getTag()) && tagEvent.getComment().equals(tag.getComment()) && tagEvent.getImageURL().equals(tag.getImageURL())) { try { - raceLog.revokeEvent(tagEvent.getAuthor(), tagEvent, "Revoked"); - } catch (NotRevokableException e) { - successInfo = new SuccessInfo(false, "Could not remove tag! " + e.getMessage(), null, null); + // check if logged in user is the same user as the creator or logged in user is Administrator + Subject subject = SecurityUtils.getSubject(); + subject.checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + if ((subject.getPrincipals() != null && subject.getPrincipals().getPrimaryPrincipal().equals(tag.getUsername())) || subject.hasRole("admin")) { + raceLog.revokeEvent(tagEvent.getAuthor(), tagEvent, "Revoked"); + } else { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), null, null); + } + } catch (AuthorizationException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), null, null); + } catch (Exception e) { + successInfo = new SuccessInfo(false, e.toString(), null, null); } } } 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 47c529b9626..f8fa42958ee 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 @@ -2,4 +2,7 @@ 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 +slicingError=Error slicing race +tagNotRemoved=Could not remove tag! +tagMissingPermissions=Missing permission +tagNotLoggedIn=You are not logged in! \ 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 index 456ecd8cddf..5724a669987 100644 --- 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 @@ -2,4 +2,7 @@ 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 +slicingError=Fehler beim Schneiden des Rennens +tagNotRemoved=Tag konnte nicht geloescht werden! +tagMissingPermissions=Fehlende Berechtigung! +tagNotLoggedIn=Du ist nicht eingeloggt! \ No newline at end of file From d402126cf5b2675b70ba2e953ffc3a2fae6ff42c Mon Sep 17 00:00:00 2001 From: D067890 Date: Tue, 14 Aug 2018 16:35:39 +0200 Subject: [PATCH 129/292] bug4104: changed vertical to flow panels and did code improvements --- .../gwt/ui/raceboard/TaggingPanel.java | 54 +++++++++---------- .../gwt/ui/raceboard/tagging-panel.css | 4 ++ 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 4e54f7141bc..926a02579a0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -15,7 +15,6 @@ import com.google.gwt.core.shared.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.EventTarget; import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Style.Overflow; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; @@ -50,7 +49,6 @@ import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.ScrollPanel; import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.user.client.ui.TextBox; -import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SingleSelectionModel; @@ -278,7 +276,7 @@ public class TaggingPanel extends ComponentWithoutSettings this.tag = tag; this.imageURL = imageURL; this.comment = comment; - setStyleName(TagPanelResources.INSTANCE.style().button()); + setStyleName(TagPanelResources.INSTANCE.style().footerButton()); addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -313,10 +311,11 @@ public class TaggingPanel extends ComponentWithoutSettings } - private class TagCreationPanel extends VerticalPanel { + private class TagCreationPanel extends FlowPanel { private final Panel customButtonsPanel; private final Panel standardButtonsPanel; private final TagCreationInputPanel inputPanel; + private final Button createTagFromTextBoxes, editCustomTagButtons; public TagCreationPanel(StringMessages stringMessages) { setWidth("100%"); @@ -328,23 +327,9 @@ public class TaggingPanel extends ComponentWithoutSettings add(inputPanel); add(standardButtonsPanel); add(customButtonsPanel); - - Button createTagFromTextBoxes = new Button(stringMessages.tagAddTag()); - createTagFromTextBoxes.setStyleName(TagPanelResources.INSTANCE.style().button()); - createTagFromTextBoxes.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - if (isAuthorizedAndRaceLogAvailable()) { - addTagToRaceLog(inputPanel.getTagValue(), inputPanel.getCommentValue(), - inputPanel.getImageURLValue()); - inputPanel.clearAllValues(); - } - } - }); - standardButtonsPanel.add(createTagFromTextBoxes); - - Button editCustomTagButtons = new Button(stringMessages.tagEditCustomTagButtons()); - editCustomTagButtons.setStyleName(TagPanelResources.INSTANCE.style().button()); + + editCustomTagButtons = new Button(stringMessages.tagEditCustomTagButtons()); + editCustomTagButtons.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); editCustomTagButtons.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -363,7 +348,21 @@ public class TaggingPanel extends ComponentWithoutSettings } } }); - standardButtonsPanel.add(editCustomTagButtons); + standardButtonsPanel.add(editCustomTagButtons); + + createTagFromTextBoxes = new Button(stringMessages.tagAddTag()); + createTagFromTextBoxes.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); + createTagFromTextBoxes.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + if (isAuthorizedAndRaceLogAvailable()) { + addTagToRaceLog(inputPanel.getTagValue(), inputPanel.getCommentValue(), + inputPanel.getImageURLValue()); + inputPanel.clearAllValues(); + } + } + }); + standardButtonsPanel.add(createTagFromTextBoxes); } private void updateButtons() { @@ -374,7 +373,7 @@ public class TaggingPanel extends ComponentWithoutSettings } } - public class TagPreviewPanel extends VerticalPanel { + public class TagPreviewPanel extends FlowPanel { private final CellList tagPreviewCellList; private TagDTO previewTag; private List listContainingPreviewTag; @@ -426,7 +425,7 @@ public class TaggingPanel extends ComponentWithoutSettings } } - public class TagCreationInputPanel extends VerticalPanel { + public class TagCreationInputPanel extends FlowPanel { private TextBox tagTextBox, imageURLTextBox; private TextArea commentTextArea; @@ -434,21 +433,18 @@ public class TaggingPanel extends ComponentWithoutSettings setWidth("100%"); tagTextBox = new TextBox(); - tagTextBox.setWidth("100%"); tagTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelTag()); tagTextBox.setTitle(stringMessages.tagLabelTag()); tagTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelTag()); add(tagTextBox); imageURLTextBox = new TextBox(); - imageURLTextBox.setWidth("100%"); imageURLTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelImageURL()); imageURLTextBox.setTitle(stringMessages.tagLabelImageURL()); imageURLTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); add(imageURLTextBox); commentTextArea = new TextArea(); - commentTextArea.setWidth("100%"); commentTextArea.setStyleName(TagPanelResources.INSTANCE.style().inputPanelComment()); commentTextArea.setVisibleLines(4); commentTextArea.setTitle(stringMessages.tagLabelComment()); @@ -503,7 +499,7 @@ public class TaggingPanel extends ComponentWithoutSettings private class EditCustomTagButtonsDialog extends DialogBox { private final Button closeButton, saveChangesButton, cancelChangesButton; - private final Panel mainPanel; + private final FlowPanel mainPanel; private final CellTable customTagButtonsTable; private final TagCreationInputPanel inputPanel; private final Button addCustomTagButton; @@ -517,7 +513,7 @@ public class TaggingPanel extends ComponentWithoutSettings setText(stringMessages.tagEditCustomTagButtons()); setWidth("350px"); - mainPanel = new VerticalPanel(); + mainPanel = new FlowPanel(); mainPanel.setWidth("100%"); //Table with tag buttons diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css index 13d2b658a54..1c5db6822b4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css @@ -82,6 +82,7 @@ b { .footerPanel { float: right; + width: 100%; } .tagButtonTable { @@ -98,11 +99,13 @@ b { border-radius: 4px 4px 0px 0px; border: 1px solid #cecece; padding: 2px; + width: 100%; } .inputPanelImageURL { border: 1px solid #cecece; padding: 2px; + width: 100%; } .inputPanelComment { @@ -112,6 +115,7 @@ b { resize: none; margin-bottom: 5px; border-radius: 0px 0px 4px 4px; + width: 100%; } /**************************** Tag filtering ****************************/ From b5913ae15ae629685b1401d22fbd07fc09fc82f2 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Tue, 14 Aug 2018 17:14:34 +0200 Subject: [PATCH 130/292] Bug 4104: Code formatting --- .../gwt/ui/raceboard/TaggingPanel.java | 105 ++++++++++-------- .../gwt/ui/server/SailingServiceImpl.java | 23 ++-- 2 files changed, 74 insertions(+), 54 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 9f7fa7c73ab..96c7d3083dc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -134,7 +134,7 @@ public class TaggingPanel extends ComponentWithoutSettings String inputPanelImageURL(); String footerPanel(); String tagPreviewPanel(); - + // filter tags String tagFilterButton(); String tagFilterHiddenButton(); @@ -152,7 +152,7 @@ public class TaggingPanel extends ComponentWithoutSettings String settingsButtonBackgroundImage(); } } - + public interface CellListResources extends CellList.Resources { public static final CellListResources INSTANCE = GWT.create(CellListResources.class); @@ -206,7 +206,8 @@ public class TaggingPanel extends ComponentWithoutSettings } SafeHtml safeTag = SafeHtmlUtils.fromString(tag.getTag()); - SafeHtml safeCreated = SafeHtmlUtils.fromString(stringMessages.tagCreated(tag.getUsername(), DateTimeFormat.getFormat("E d/M/y, HH:mm").format(tag.getRaceTimepoint().asDate()))); + SafeHtml safeCreated = SafeHtmlUtils.fromString(stringMessages.tagCreated(tag.getUsername(), + DateTimeFormat.getFormat("E d/M/y, HH:mm").format(tag.getRaceTimepoint().asDate()))); SafeHtml safeComment = SafeHtmlUtils.fromString(tag.getComment()); SafeUri trustedImageURL = UriUtils.fromTrustedString(tag.getImageURL()); @@ -222,7 +223,8 @@ public class TaggingPanel extends ComponentWithoutSettings SafeHtml cell; if (userService.getCurrentUser() != null - && (tag.getUsername().equals(userService.getCurrentUser().getName()) || userService.getCurrentUser().hasRole("admin"))) { + && (tag.getUsername().equals(userService.getCurrentUser().getName()) + || userService.getCurrentUser().hasRole("admin"))) { cell = tagCellTemplate.cellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), tagPanelStyle.tagCreated(), safeTag, safeCreated, content); } else { @@ -362,7 +364,7 @@ public class TaggingPanel extends ComponentWithoutSettings } } }); - standardButtonsPanel.add(editCustomTagButtons); + standardButtonsPanel.add(editCustomTagButtons); } private void updateButtons() { @@ -386,11 +388,11 @@ public class TaggingPanel extends ComponentWithoutSettings tagPreviewCellList.setVisibleRange(0, 1); previewLabel = new Label(stringMessages.tagPreview()); listContainingPreviewTag = new ArrayList(); - + setStyleName(TagPanelResources.INSTANCE.style().tagPreviewPanel()); add(previewLabel); add(tagPreviewCellList); - + inputField.getTagTextBox().addValueChangeHandler(new ValueChangeHandler() { @Override public void onValueChange(ValueChangeEvent event) { @@ -417,10 +419,12 @@ public class TaggingPanel extends ComponentWithoutSettings public void renderPreview() { listContainingPreviewTag.removeAll(listContainingPreviewTag); - previewTag = new TagDTO(inputField.getTagValue(), inputField.getCommentValue(), inputField.getImageURLValue(), "Author", new MillisecondsTimePoint(timer.getTime()), new MillisecondsTimePoint(timer.getTime())); + previewTag = new TagDTO(inputField.getTagValue(), inputField.getCommentValue(), + inputField.getImageURLValue(), "Author", new MillisecondsTimePoint(timer.getTime()), + new MillisecondsTimePoint(timer.getTime())); listContainingPreviewTag.add(previewTag); tagPreviewCellList.setRowData(listContainingPreviewTag); - + setVisible(!inputField.getTagValue().isEmpty()); } } @@ -456,11 +460,11 @@ public class TaggingPanel extends ComponentWithoutSettings public TextBox getTagTextBox() { return tagTextBox; } - + public TextBox getImageURLTextBox() { return imageURLTextBox; } - + public TextArea getCommentTextArea() { return commentTextArea; } @@ -505,18 +509,18 @@ public class TaggingPanel extends ComponentWithoutSettings private final Button addCustomTagButton; private final TagPreviewPanel tagPreviewPanel; private final FlowPanel controlButttonPanel; - private TagButton selectedTagButton = null; + private TagButton selectedTagButton = null; public EditCustomTagButtonsDialog(Panel customButtonsPanel) { - TagPanelStyle style = TagPanelResources.INSTANCE.style(); + TagPanelStyle style = TagPanelResources.INSTANCE.style(); setGlassEnabled(true); setText(stringMessages.tagEditCustomTagButtons()); setWidth("350px"); mainPanel = new FlowPanel(); mainPanel.setWidth("100%"); - - //Table with tag buttons + + // Table with tag buttons customTagButtonsTable = new CellTable(); customTagButtonsTable.setStyleName(TagPanelResources.INSTANCE.style().tagButtonTable()); TextColumn tagColumn = new TextColumn() { @@ -553,9 +557,9 @@ public class TaggingPanel extends ComponentWithoutSettings inputPanel.setTagValue(button.getTag()); inputPanel.setImageURLValue(button.getImageURL()); inputPanel.setCommentValue(button.getComment()); - + tagPreviewPanel.renderPreview(); - + saveChangesButton.setVisible(true); cancelChangesButton.setVisible(true); addCustomTagButton.setVisible(false); @@ -570,13 +574,13 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtonsTable.addColumn(actionsColumn, stringMessages.tagLabelAction()); setRowData(customTagButtons); - //input panel + // input panel inputPanel = new TagCreationInputPanel(stringMessages); - //contol buttons + // contol buttons controlButttonPanel = new FlowPanel(); controlButttonPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); - + addCustomTagButton = new Button(stringMessages.tagAddCustomTagButton()); addCustomTagButton.setStyleName(style.footerButton()); addCustomTagButton.addClickHandler(new ClickHandler() { @@ -585,9 +589,9 @@ public class TaggingPanel extends ComponentWithoutSettings if (inputPanel.getTagValue().length() > 0) { TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), inputPanel.getImageURLValue(), inputPanel.getCommentValue()); - inputPanel.clearAllValues(); + inputPanel.clearAllValues(); tagPreviewPanel.renderPreview(); - + customTagButtons.add(tagButton); customButtonsPanel.add(tagButton); setRowData(customTagButtons); @@ -596,7 +600,7 @@ public class TaggingPanel extends ComponentWithoutSettings } } }); - + saveChangesButton = new Button(stringMessages.save()); saveChangesButton.setVisible(false); saveChangesButton.setStyleName(style.footerButton()); @@ -611,7 +615,7 @@ public class TaggingPanel extends ComponentWithoutSettings inputPanel.clearAllValues(); tagPreviewPanel.renderPreview(); customTagButtonsTable.redraw(); - + saveChangesButton.setVisible(false); cancelChangesButton.setVisible(false); addCustomTagButton.setVisible(true); @@ -622,7 +626,7 @@ public class TaggingPanel extends ComponentWithoutSettings } } }); - + cancelChangesButton = new Button(stringMessages.cancel()); cancelChangesButton.setVisible(false); cancelChangesButton.setStyleName(style.footerButton()); @@ -649,7 +653,7 @@ public class TaggingPanel extends ComponentWithoutSettings controlButttonPanel.add(addCustomTagButton); controlButttonPanel.add(cancelChangesButton); controlButttonPanel.add(saveChangesButton); - + tagPreviewPanel = new TagPreviewPanel(inputPanel); mainPanel.add(customTagButtonsTable); @@ -664,13 +668,13 @@ public class TaggingPanel extends ComponentWithoutSettings private void hideDialog() { this.hide(); } - + private void setRowData(List buttons) { customTagButtonsTable.setRowData(buttons); customTagButtonsTable.setVisible(buttons.size() > 0); } } - + private class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWithUI { private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailingAnalytics.raceBoard.tagsFilterSets"; @@ -700,11 +704,12 @@ public class TaggingPanel extends ComponentWithoutSettings tagFilterSets = createAndAddDefaultTagsFilter(); storeTagsFilterSets(tagFilterSets); } - + filter = new AbstractListFilter() { @Override public Iterable getStrings(TagDTO tag) { - final List result = new ArrayList<>(Arrays.asList(tag.getTag().toLowerCase(), tag.getComment())); + final List result = new ArrayList<>( + Arrays.asList(tag.getTag().toLowerCase(), tag.getComment())); return result; } }; @@ -778,8 +783,8 @@ public class TaggingPanel extends ComponentWithoutSettings } /** - * Updates the tags filter checkbox state by setting its check mark and updating its label according to the current - * filter selected + * Updates the tags filter checkbox state by setting its check mark and updating its label according to the + * current filter selected */ private void updateTagsFilterControlState(TagsFilterSets filterSets) { String tagsFilterTitle = stringMessages.tagsFilter(); @@ -840,7 +845,7 @@ public class TaggingPanel extends ComponentWithoutSettings private TagsFilterSets createAndAddDefaultTagsFilter() { TagsFilterSets filterSets = new TagsFilterSets(); - //TODO add standard filters here + // TODO add standard filters here return filterSets; } @@ -853,7 +858,8 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public boolean matches(TagDTO tag) { - final Iterable lowercaseKeywords = Util.splitAlongWhitespaceRespectingDoubleQuotedPhrases(searchTextBox.getText().toLowerCase()); + final Iterable lowercaseKeywords = Util + .splitAlongWhitespaceRespectingDoubleQuotedPhrases(searchTextBox.getText().toLowerCase()); return !Util.isEmpty(filter.applyFilter(lowercaseKeywords, Collections.singleton(tag))); } @@ -886,9 +892,10 @@ public class TaggingPanel extends ComponentWithoutSettings public FilterUIFactory createUIFactory() { return null; } - + /** - * @param event ignored; may be null + * @param event + * ignored; may be null */ @Override public void onKeyUp(KeyUpEvent event) { @@ -900,13 +907,14 @@ public class TaggingPanel extends ComponentWithoutSettings if (newValue.length() >= 2) { clearTextBoxButton.removeStyleName(css.tagFilterHiddenButton()); ensureSearchFilterIsSet(); - tagProvider.setTagsFilterSet(tagProvider.getTagsFilterSet()); // + tagProvider.setTagsFilterSet(tagProvider.getTagsFilterSet()); // } } } - + private void ensureSearchFilterIsSet() { - if (tagProvider.getTagsFilterSet() == null || !Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { + if (tagProvider.getTagsFilterSet() == null + || !Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { FilterSet> newFilterSetWithThis = new FilterSet<>(getName()); if (tagProvider.getTagsFilterSet() != null) { for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { @@ -921,7 +929,8 @@ public class TaggingPanel extends ComponentWithoutSettings private void removeSearchFilter() { if (tagProvider.getTagsFilterSet() != null && Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { - FilterSet> newFilterSetWithThis = new FilterSet<>(tagProvider.getTagsFilterSet().getName()); + FilterSet> newFilterSetWithThis = new FilterSet<>( + tagProvider.getTagsFilterSet().getName()); for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { if (oldFilter != this) { newFilterSetWithThis.addFilter(oldFilter); @@ -1039,15 +1048,17 @@ public class TaggingPanel extends ComponentWithoutSettings imageURL, new MillisecondsTimePoint(timer.getTime()), new AsyncCallback() { @Override public void onFailure(Throwable caught) { - Notification.notify(stringMessages.tagNotAddedReason(caught.toString()), NotificationType.ERROR); + Notification.notify(stringMessages.tagNotAddedReason(caught.toString()), + NotificationType.ERROR); } @Override public void onSuccess(SuccessInfo result) { - if (result.isSuccessful()) { + if (result.isSuccessful()) { Notification.notify(stringMessages.tagAddedSuccessfully(), NotificationType.INFO); } else { - Notification.notify(stringMessages.tagNotAddedReason(result.getMessage()), NotificationType.ERROR); + Notification.notify(stringMessages.tagNotAddedReason(result.getMessage()), + NotificationType.ERROR); } } }); @@ -1069,19 +1080,21 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onSuccess(SuccessInfo result) { - if (result.isSuccessful()) { + if (result.isSuccessful()) { tagListProvider.getAllTags().remove(tag); updateContent(); Notification.notify(stringMessages.tagRemovedSuccessfully(), NotificationType.SUCCESS); } else { - Notification.notify(stringMessages.tagNotRemoved() + " " + result.getMessage(), NotificationType.ERROR); + Notification.notify(stringMessages.tagNotRemoved() + " " + result.getMessage(), + NotificationType.ERROR); } } }); } private boolean isLoggedInAndRaceLogAvailable() { - return !(userService.getCurrentUser() == null || leaderboardName == null || raceColumn == null || fleet == null); + return !(userService.getCurrentUser() == null || leaderboardName == null || raceColumn == null + || fleet == null); } private void updateContent() { 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 bf63db9ac72..38712e77d1c 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 @@ -6053,17 +6053,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public SuccessInfo addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, String imageURL, TimePoint raceTimepoint) { SuccessInfo successInfo = new SuccessInfo(true, null, null, null); - try { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + try { + SecurityUtils.getSubject().checkPermission( + Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, raceTimepoint, getService().getServerAuthor(), raceLog.getCurrentPassId())); } catch (AuthorizationException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), null, null); + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), + null, null); } return successInfo; } - + @Override public SuccessInfo removeTagFromRaceLog(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) { @@ -6077,14 +6079,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S try { // check if logged in user is the same user as the creator or logged in user is Administrator Subject subject = SecurityUtils.getSubject(); - subject.checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); - if ((subject.getPrincipals() != null && subject.getPrincipals().getPrimaryPrincipal().equals(tag.getUsername())) || subject.hasRole("admin")) { + subject.checkPermission( + Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + if ((subject.getPrincipals() != null + && subject.getPrincipals().getPrimaryPrincipal().equals(tag.getUsername())) + || subject.hasRole("admin")) { raceLog.revokeEvent(tagEvent.getAuthor(), tagEvent, "Revoked"); } else { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), null, null); + successInfo = new SuccessInfo(false, + serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), null, null); } } catch (AuthorizationException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), null, null); + successInfo = new SuccessInfo(false, + serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), null, null); } catch (Exception e) { successInfo = new SuccessInfo(false, e.toString(), null, null); } From 6895d949f119c621a32f25b0b20bf78ae48b7823 Mon Sep 17 00:00:00 2001 From: D067890 Date: Wed, 15 Aug 2018 10:40:45 +0200 Subject: [PATCH 131/292] bug4104: Fixed overlaping of widgets Problem --- .../gwt/ui/raceboard/TaggingPanel.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 96c7d3083dc..f21730b5e97 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -548,9 +548,21 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void update(int index, TagButton button, String value) { if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { + final int heightOfTagButtonPanel = customButtonsPanel.getOffsetHeight(); + customTagButtons.remove(button); customButtonsPanel.remove(button); customTagButtonsTable.setRowData(customTagButtons); + + final int deltaHeight = customButtonsPanel.getOffsetHeight() - heightOfTagButtonPanel; + /* + * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), + * the footerWidget of the TaggingPanel has a different height, + * which in this case might cause the contentWidget to be to small. + */ + if(deltaHeight != 0) { + panel.setContentWidget(contentPanel); + } } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { selectedTagButton = button; @@ -587,6 +599,8 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onClick(ClickEvent event) { if (inputPanel.getTagValue().length() > 0) { + final int heightOfTagButtonPanel = customButtonsPanel.getOffsetHeight(); + TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), inputPanel.getImageURLValue(), inputPanel.getCommentValue()); inputPanel.clearAllValues(); @@ -595,6 +609,16 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtons.add(tagButton); customButtonsPanel.add(tagButton); setRowData(customTagButtons); + + final int deltaHeight = customButtonsPanel.getOffsetHeight() - heightOfTagButtonPanel; + /* + * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), + * the footerWidget of the TaggingPanel has a different height, + * which might cause the contentWidget to overlap the footerWidget. + */ + if(deltaHeight != 0) { + panel.setContentWidget(contentPanel); + } } else { Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); } @@ -944,7 +968,7 @@ public class TaggingPanel extends ComponentWithoutSettings private final HeaderPanel panel; private final TagCreationPanel tagCreationPanel; private final Panel filterbarPanel; - private final Panel contentPanel; + private final ScrollPanel contentPanel; private final CellList tagCellList; private final SingleSelectionModel tagSelectionModel; From 9b315a36b6d093fbc7f4cdf4ba6a3454c2aa7d85 Mon Sep 17 00:00:00 2001 From: D067890 Date: Wed, 15 Aug 2018 10:56:32 +0200 Subject: [PATCH 132/292] bug4104: Removed unnecessary Interface --- .../gwt/ui/client/TagListProvider.java | 26 ++++++---- .../sailing/gwt/ui/client/TagProvider.java | 49 ------------------- 2 files changed, 17 insertions(+), 58 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagProvider.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java index f57b75dc7fe..4058c69e91b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java @@ -10,17 +10,24 @@ import com.sap.sse.common.Util; import com.sap.sse.common.filter.Filter; import com.sap.sse.common.filter.FilterSet; -public class TagListProvider extends ListDataProvider implements TagProvider { +/** + * @author Julian Rendl(D067890) + * Used to store tags and filter sets and to apply these filters on the tags + */ +public class TagListProvider extends ListDataProvider { private List allTags = new ArrayList(); private FilterSet> currentFilterSet; - @Override + public List getAllTags() { return allTags; } - @Override + /** + * adds new tags, call {@link #updateFilteredTags() updateFilteredTags} afterwards so list of filtered tags can contain new tags + * @param list of tags which shall be added + */ public void addTags(final List tags) { if (tags != null) { for (TagDTO tag : tags) { @@ -29,19 +36,23 @@ public class TagListProvider extends ListDataProvider implements TagProv } } - @Override + /** + * adds a new tag, call {@link #updateFilteredTags() updateFilteredTags} afterwards so list of filtered tag can contain new tags + * @param tag which shall be added + */ public void addTag(final TagDTO tag) { if (tag != null) { allTags.add(tag); } } - @Override public List getFilteredTags() { return getList(); } - @Override + /** + * filter all tags by tagsFilterSet + */ public void updateFilteredTags() { List currentFilteredList = new ArrayList(getAllTags()); @@ -66,19 +77,16 @@ public class TagListProvider extends ListDataProvider implements TagProv setList(currentFilteredList); } - @Override public FilterSet> getTagsFilterSet() { return currentFilterSet; } - @Override public void setTagsFilterSet(FilterSet> tagsFilterSet) { this.currentFilterSet = tagsFilterSet; this.updateFilteredTags(); this.refresh(); } - @Override public int getFilteredTagsListSize() { return Util.size(getFilteredTags()); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagProvider.java deleted file mode 100644 index 8ca0b7bcdd9..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagProvider.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.sap.sailing.gwt.ui.client; - -import java.util.List; - -import com.sap.sailing.gwt.ui.shared.TagDTO; -import com.sap.sse.common.filter.Filter; -import com.sap.sse.common.filter.FilterSet; -/** - * - * @author D067890 - * Used to store tags and tagFilterSets - * - */ -public interface TagProvider { - - /** - * adds new tags, call {@link #updateFilteredTags() updateFilteredTags} afterwards so list of filtered tags can contain new tags - * @param list of tags which shall be added - */ - void addTags(List tags); - - - /** - * adds a new tag, call {@link #updateFilteredTags() updateFilteredTags} afterwards so list of filtered tag can contain new tags - * @param tag which shall be added - */ - void addTag(TagDTO tag); - - /** - * @return all filtered tags - */ - List getFilteredTags(); - - int getFilteredTagsListSize(); - - void setTagsFilterSet(FilterSet> tagsFilterSet); - - FilterSet> getTagsFilterSet(); - - /** - * filter all tags by tagsFilterSet - */ - void updateFilteredTags(); - - /** - * @return all tags without filtering - */ - List getAllTags(); -} \ No newline at end of file From 01456fed48ee0fee941aa9fbef3b4434902cd2ea Mon Sep 17 00:00:00 2001 From: D067890 Date: Wed, 15 Aug 2018 13:48:48 +0200 Subject: [PATCH 133/292] bug4104: Created label containing filter name, needs to be added to ui --- .../gwt/ui/client/TagListProvider.java | 26 ++++++++++++++++--- .../gwt/ui/raceboard/TaggingPanel.java | 8 ++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java index 4058c69e91b..4fba9a88866 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.List; + +import com.google.gwt.user.client.ui.Label; import com.google.gwt.view.client.ListDataProvider; import com.sap.sailing.gwt.ui.shared.TagDTO; import com.sap.sse.common.Util; @@ -17,8 +19,14 @@ import com.sap.sse.common.filter.FilterSet; public class TagListProvider extends ListDataProvider { private List allTags = new ArrayList(); - private FilterSet> currentFilterSet; + private FilterSet> currentFilterSet; + private Label filterInformationLabel; + + + public TagListProvider(Label filterInformationLabel) { + this.filterInformationLabel = filterInformationLabel; + } public List getAllTags() { return allTags; @@ -82,9 +90,19 @@ public class TagListProvider extends ListDataProvider { } public void setTagsFilterSet(FilterSet> tagsFilterSet) { - this.currentFilterSet = tagsFilterSet; - this.updateFilteredTags(); - this.refresh(); + if(filterInformationLabel != null) { + if(tagsFilterSet != null) { + filterInformationLabel.setText(tagsFilterSet.getName()); + filterInformationLabel.setVisible(true); + } + else { + filterInformationLabel.setVisible(false); + } + } + + updateFilteredTags(); + currentFilterSet = tagsFilterSet; + refresh(); } public int getFilteredTagsListSize() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index f21730b5e97..879b8adbc72 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -968,6 +968,7 @@ public class TaggingPanel extends ComponentWithoutSettings private final HeaderPanel panel; private final TagCreationPanel tagCreationPanel; private final Panel filterbarPanel; + private final Label currentFilterLabel; private final ScrollPanel contentPanel; private final CellList tagCellList; private final SingleSelectionModel tagSelectionModel; @@ -993,7 +994,9 @@ public class TaggingPanel extends ComponentWithoutSettings TagPanelResources.INSTANCE.style().ensureInjected(); CellListResources.INSTANCE.cellListStyle().ensureInjected(); - tagListProvider = new TagListProvider(); + //TODO Add this label to ui + currentFilterLabel = new Label(); + tagListProvider = new TagListProvider(currentFilterLabel); customTagButtons = new ArrayList(); panel = new HeaderPanel(); @@ -1044,7 +1047,8 @@ public class TaggingPanel extends ComponentWithoutSettings timer.setTime(tagSelectionModel.getSelectedObject().getRaceTimepoint().asMillis()); } }); - + + contentPanel.add(currentFilterLabel); contentPanel.add(tagCellList); contentPanel.getElement().getStyle().setHeight(100, Unit.PCT); contentPanel.getElement().getStyle().setPaddingTop(10, Unit.PX); From 6a17e28ce0bbc0662ba0690c02a284332df07206 Mon Sep 17 00:00:00 2001 From: D067890 Date: Wed, 15 Aug 2018 14:02:22 +0200 Subject: [PATCH 134/292] bug4104: Preview tags now cannot be deleted anymore --- .../sap/sailing/gwt/ui/raceboard/TaggingPanel.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 879b8adbc72..63a314b0902 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -194,9 +194,11 @@ public class TaggingPanel extends ComponentWithoutSettings private final TagCellTemplate tagCellTemplate = GWT.create(TagCellTemplate.class); private final TagPanelResources tagPanelRes = GWT.create(TagPanelResources.class); private final TagPanelStyle tagPanelStyle = tagPanelRes.style(); + private final boolean isPreviewCell; - public TagCell() { + public TagCell(boolean isPreviewCell) { super("click"); + this.isPreviewCell = isPreviewCell; } @Override @@ -222,7 +224,7 @@ public class TaggingPanel extends ComponentWithoutSettings } SafeHtml cell; - if (userService.getCurrentUser() != null + if (isPreviewCell && userService.getCurrentUser() != null && (tag.getUsername().equals(userService.getCurrentUser().getName()) || userService.getCurrentUser().hasRole("admin"))) { cell = tagCellTemplate.cellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), @@ -384,7 +386,7 @@ public class TaggingPanel extends ComponentWithoutSettings public TagPreviewPanel(TagCreationInputPanel inputField) { this.inputField = inputField; - tagPreviewCellList = new CellList(new TagCell(), CellListResources.INSTANCE); + tagPreviewCellList = new CellList(new TagCell(false), CellListResources.INSTANCE); tagPreviewCellList.setVisibleRange(0, 1); previewLabel = new Label(stringMessages.tagPreview()); listContainingPreviewTag = new ArrayList(); @@ -1001,7 +1003,7 @@ public class TaggingPanel extends ComponentWithoutSettings panel = new HeaderPanel(); filterbarPanel = new TagFilterPanel(stringMessages, tagListProvider); - tagCellList = new CellList(new TagCell(), CellListResources.INSTANCE); + tagCellList = new CellList(new TagCell(true), CellListResources.INSTANCE); tagSelectionModel = new SingleSelectionModel(); contentPanel = new ScrollPanel(); @@ -1048,7 +1050,7 @@ public class TaggingPanel extends ComponentWithoutSettings } }); - contentPanel.add(currentFilterLabel); + //contentPanel.add(currentFilterLabel); contentPanel.add(tagCellList); contentPanel.getElement().getStyle().setHeight(100, Unit.PCT); contentPanel.getElement().getStyle().setPaddingTop(10, Unit.PX); From 2768f8c8ed5b699eb1c6d3a05e5e1804a34cd5d9 Mon Sep 17 00:00:00 2001 From: D067890 Date: Wed, 15 Aug 2018 15:57:51 +0200 Subject: [PATCH 135/292] bug4104: removed grey footer problem --- .../java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.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/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 63a314b0902..604498202c2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -524,7 +524,7 @@ public class TaggingPanel extends ComponentWithoutSettings // Table with tag buttons customTagButtonsTable = new CellTable(); - customTagButtonsTable.setStyleName(TagPanelResources.INSTANCE.style().tagButtonTable()); + customTagButtonsTable.setStyleName(style.tagButtonTable()); TextColumn tagColumn = new TextColumn() { @Override public String getValue(TagButton button) { @@ -687,7 +687,9 @@ public class TaggingPanel extends ComponentWithoutSettings mainPanel.add(controlButttonPanel); mainPanel.add(tagPreviewPanel); mainPanel.add(closeButton); - + mainPanel.ensureDebugId("Test"); + getElement().getStyle().setBackgroundColor("white"); + setWidget(mainPanel); } From 48ae1ad57db546566c17816ebae242d113964a3b Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Thu, 16 Aug 2018 08:39:47 +0200 Subject: [PATCH 136/292] Bug 4104: Improved server side caching of tag events. --- .../abstractlog/race/RaceLogTagEvent.java | 5 ++ .../race/analyzing/impl/TagFinder.java | 54 +++++++-------- .../race/impl/RaceLogTagEventImpl.java | 65 +++++++++++++++++-- .../race/state/RaceStateChangedListener.java | 1 + .../race/state/ReadonlyRaceState.java | 3 + .../impl/BaseRaceStateChangedListener.java | 5 ++ .../state/impl/RaceStateChangedListeners.java | 7 ++ .../state/impl/ReadonlyRaceStateImpl.java | 17 +++++ .../gwt/ui/client/RaceTimesInfoProvider.java | 2 +- .../gwt/ui/raceboard/TaggingPanel.java | 24 +++++-- .../gwt/ui/server/SailingServiceImpl.java | 20 ++++-- .../com/sap/sailing/gwt/ui/shared/TagDTO.java | 34 ++++++---- 12 files changed, 175 insertions(+), 62 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java index 0cd5ad95ad0..e11528b38f2 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.abstractlog.race; import com.sap.sailing.domain.abstractlog.Revokable; +import com.sap.sse.common.TimePoint; public interface RaceLogTagEvent extends RaceLogEvent, Revokable { @@ -11,4 +12,8 @@ public interface RaceLogTagEvent extends RaceLogEvent, Revokable { String getComment(); String getImageURL(); + + void markAsRevoked(TimePoint revokedAt); + + TimePoint getRevokedAt(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/TagFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/TagFinder.java index 17fed35afaf..66e7b173c0d 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/TagFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/TagFinder.java @@ -5,49 +5,45 @@ import java.util.List; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; public class TagFinder extends RaceLogAnalyzer> { - private final TimePoint from; - private final TimePoint to; - private List tagEvents; + private final RaceLog raceLog; public TagFinder(RaceLog raceLog) { - this(raceLog, null, null); - } - - public TagFinder(RaceLog raceLog, TimePoint from) { - this(raceLog, from, null); - } - - public TagFinder(RaceLog raceLog, TimePoint from, TimePoint to) { super(raceLog); - tagEvents = new ArrayList(); - for (RaceLogEvent event : raceLog.getUnrevokedEvents()) { - if (event instanceof RaceLogTagEvent) { - tagEvents.add((RaceLogTagEvent) event); - } - } - this.from = from; - this.to = to == null ? MillisecondsTimePoint.now() : to; + this.raceLog = raceLog; } @Override protected List performAnalysis() { + Iterable raceLogEvents = getAllEvents(); List result = new ArrayList<>(); - for (RaceLogTagEvent tagEvent : tagEvents) { - if (from == null && tagEvent.getCreatedAt().before(to)) { - // from is not specified => load every tag until now - result.add(tagEvent); - } else if (from != null && tagEvent.getCreatedAt().after(from) && tagEvent.getCreatedAt().before(to)) { - // from is specified => load only tags between from and now - result.add(tagEvent); + for (RaceLogEvent raceLogEvent : raceLogEvents) { + if (raceLogEvent instanceof RaceLogTagEvent) { + // tag event is not revoked (at least until this point of time at scanning race log) + RaceLogTagEvent tagEvent = (RaceLogTagEvent) raceLogEvent; + if (!result.contains(tagEvent)) { + result.add(tagEvent); + } + } else if (raceLogEvent instanceof RaceLogRevokeEvent) { + // tag event got revoked => update it in result list or add it to result as revoked tag event + RaceLogRevokeEvent revokeEvent = (RaceLogRevokeEvent) raceLogEvent; + RaceLogEvent revokedEvent = raceLog.getEventById(revokeEvent.getRevokedEventId()); + if (revokedEvent != null && revokedEvent instanceof RaceLogTagEvent) { + RaceLogTagEvent revokedTagEvent = (RaceLogTagEvent) revokedEvent; + int index = result.indexOf(revokedTagEvent); + if (index > 0) { + result.get(index).markAsRevoked(revokeEvent.getCreatedAt()); + } else { + revokedTagEvent.markAsRevoked(revokeEvent.getCreatedAt()); + result.add(revokedTagEvent); + } + } } } return result; } - } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index 76df8659711..e9cdf4fa880 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -12,6 +12,7 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE private static final long serialVersionUID = 7213518902555323432L; private String tag, comment, imageURL, username; + private TimePoint revokedAt; public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, int pPassId) { @@ -20,6 +21,7 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE comment = pComment; imageURL = pImageURL; username = author.getName(); + revokedAt = null; } public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, TimePoint createdAt, @@ -27,8 +29,8 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE this(pTag, pComment, pImageURL, createdAt, logicalTimePoint, author, randId(), pPassId); } - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, - TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId) { + public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, int pPassId) { this(pTag, pComment, pImageURL, now(), logicalTimePoint, author, randId(), pPassId); } @@ -46,19 +48,72 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE public String getImageURL() { return imageURL; } - + @Override public String getUsername() { return username; } - + + /** + * Only sets revokedAt if tag is not revoked already and given timepoint is not null. + */ + @Override + public void markAsRevoked(TimePoint revokedAt) { + if (this.revokedAt == null && revokedAt != null) { + this.revokedAt = revokedAt; + } + } + + @Override + public TimePoint getRevokedAt() { + return revokedAt; + } + @Override public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); } - + @Override public String getShortInfo() { return "tag=" + tag + ", comment=" + comment; } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RaceLogTagEventImpl other = (RaceLogTagEventImpl) obj; + if (comment == null) { + if (other.comment != null) + return false; + } else if (!comment.equals(other.comment)) + return false; + if (imageURL == null) { + if (other.imageURL != null) + return false; + } else if (!imageURL.equals(other.imageURL)) + return false; + if (tag == null) { + if (other.tag != null) + return false; + } else if (!tag.equals(other.tag)) + return false; + if (username == null) { + if (other.username != null) + return false; + } else if (!username.equals(other.username)) + return false; + return true; + } + + @Override + public String toString() { + return "RaceLogTagEvent [tag=" + tag + ", comment=" + comment + ", imageURL=" + imageURL + ", username=" + + username + ", revokedAt=" + revokedAt + "]"; + } } \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceStateChangedListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceStateChangedListener.java index 81cd4038a1f..d2b3b276790 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceStateChangedListener.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/RaceStateChangedListener.java @@ -17,5 +17,6 @@ public interface RaceStateChangedListener { void onFinishingPositionsConfirmed(ReadonlyRaceState state); void onCourseDesignChanged(ReadonlyRaceState state); void onWindFixChanged(ReadonlyRaceState state); + void onTagEventsChanged(ReadonlyRaceState state); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/ReadonlyRaceState.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/ReadonlyRaceState.java index 3b1649bfd03..5857526a92c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/ReadonlyRaceState.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/ReadonlyRaceState.java @@ -4,6 +4,7 @@ import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventComparator; @@ -146,5 +147,7 @@ public interface ReadonlyRaceState extends RaceStateEventProcessor { * If wind has been entered, returns the most recent one. Otherwise null. */ Wind getWindFix(); + + Iterable getTagEvents(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/BaseRaceStateChangedListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/BaseRaceStateChangedListener.java index cac2cac05f8..5d7db3578c0 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/BaseRaceStateChangedListener.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/BaseRaceStateChangedListener.java @@ -63,4 +63,9 @@ public abstract class BaseRaceStateChangedListener implements RaceStateChangedLi } + @Override + public void onTagEventsChanged(ReadonlyRaceState state) { + + } + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateChangedListeners.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateChangedListeners.java index 5b51541827c..c03f3845e01 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateChangedListeners.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateChangedListeners.java @@ -111,4 +111,11 @@ public class RaceStateChangedListeners extends HashSet listener.onWindFixChanged(state); } } + + @Override + public void onTagEventsChanged(ReadonlyRaceState state) { + for (RaceStateChangedListener listener : getWorkingCopyOfListeners()) { + listener.onTagEventsChanged(state); + } + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/ReadonlyRaceStateImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/ReadonlyRaceStateImpl.java index accf15e0227..f73ac581202 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/ReadonlyRaceStateImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/ReadonlyRaceStateImpl.java @@ -13,6 +13,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.ConfirmedFinishPositioningListFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishPositioningListFinder; @@ -27,6 +28,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceStatusAnalyzer import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RacingProcedureTypeAnalyzer; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.TagFinder; import com.sap.sailing.domain.abstractlog.race.impl.WeakRaceLogChangedVisitor; import com.sap.sailing.domain.abstractlog.race.state.RaceStateChangedListener; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; @@ -167,6 +169,8 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL private final LastPublishedCourseDesignFinder courseDesignerAnalyzer; private final LastWindFixFinder lastWindFixAnalyzer; + + private final TagFinder tagAnalyzer; /** * The cached racing procedure type. If no racing procedure type specification is found in the underlying race log, @@ -197,6 +201,8 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL */ private Iterable timePointsWhenRaceStatusMayChange; + private Iterable cachedTagEvents; + private int cachedPassId; private StartTimeFinderResult cachedStartTimeFinderResult; private TimePoint cachedFinishingTime; @@ -246,6 +252,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL this.confirmedFinishPositioningListAnalyzer = new ConfirmedFinishPositioningListFinder(raceLog); this.courseDesignerAnalyzer = new LastPublishedCourseDesignFinder(raceLog, /* onlyCoursesWithValidWaypointList */ false); this.lastWindFixAnalyzer = new LastWindFixFinder(raceLog); + this.tagAnalyzer = new TagFinder(raceLog); this.raceStateToObserveListener = new BaseRaceStateChangedListener() { @Override @@ -420,6 +427,11 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL return cachedWindFix; } + @Override + public Iterable getTagEvents() { + return cachedTagEvents; + } + @Override public RegattaConfiguration getConfiguration() { return procedureFactory.getConfiguration(); @@ -562,6 +574,11 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL cachedWindFix = windFix; changedListeners.onWindFixChanged(this); } + Iterable tagEvents = tagAnalyzer.analyze(); + if (!Util.equalsWithNull(cachedTagEvents, tagEvents)) { + cachedTagEvents = tagEvents; + changedListeners.onTagEventsChanged(this); + } } /** diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesInfoProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesInfoProvider.java index 7190b3b22da..f1c47413482 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesInfoProvider.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesInfoProvider.java @@ -230,7 +230,7 @@ public class RaceTimesInfoProvider { raceTimesInfos.clear(); } - public TimePoint getLatestReceivedTag(RegattaAndRaceIdentifier raceIdentifier) { + public TimePoint getLatestReceivedTagTime(RegattaAndRaceIdentifier raceIdentifier) { return latestReceivedTagTimes.get(raceIdentifier); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 604498202c2..626d5df92f3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -18,10 +18,10 @@ import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; +import com.google.gwt.event.logical.shared.ValueChangeEvent; +import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONParser; @@ -1140,15 +1140,25 @@ public class TaggingPanel extends ComponentWithoutSettings public void raceTimesInfosReceived(Map raceTimesInfo, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) { raceTimesInfo.forEach((raceIdentifier, raceInfo) -> { - boolean addedTag = false; + boolean modifiedTags = false; boolean updatedLatestTag = false; if (raceIdentifier.equals(raceInfo.getRaceIdentifier())) { List currentTags = tagListProvider.getAllTags(); - TimePoint latestReceivedTagTime = raceTimesInfoProvider.getLatestReceivedTag(raceIdentifier); + TimePoint latestReceivedTagTime = raceTimesInfoProvider.getLatestReceivedTagTime(raceIdentifier); for (TagDTO tag : raceInfo.getTags()) { - if (!currentTags.contains(tag)) { + if (tag.getRevokedAt() != null) { + // tag got revoked + currentTags.remove(tag); + modifiedTags = true; + if (latestReceivedTagTime == null || (latestReceivedTagTime != null + && latestReceivedTagTime.before(tag.getRevokedAt()))) { + latestReceivedTagTime = tag.getRevokedAt(); + updatedLatestTag = true; + } + } else if (!currentTags.contains(tag)) { + // tag did not get revoked currentTags.add(tag); - addedTag = true; + modifiedTags = true; if (latestReceivedTagTime == null || (latestReceivedTagTime != null && latestReceivedTagTime.before(tag.getCreatedAt()))) { latestReceivedTagTime = tag.getCreatedAt(); @@ -1159,7 +1169,7 @@ public class TaggingPanel extends ComponentWithoutSettings if (updatedLatestTag) { raceTimesInfoProvider.setLatestReceivedTagTime(raceIdentifier, latestReceivedTagTime); } - if (addedTag) { + if (modifiedTags) { updateContent(); } } 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 38712e77d1c..4a9521c7f10 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 @@ -99,7 +99,6 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCours import com.sap.sailing.domain.abstractlog.race.analyzing.impl.MarkPassingDataFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.TagFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.TrackingTimesEventFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.TrackingTimesFinder; import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; @@ -2133,11 +2132,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Iterable raceLogs = trackedRace.getAttachedRaceLogs(); for (RaceLog raceLog : raceLogs) { - TagFinder tagFinder = new TagFinder(raceLog, latestReceivedTagTime); - List foundTagEvents = tagFinder.analyze(); + ReadonlyRaceState raceState = ReadonlyRaceStateImpl.getOrCreate(getService(), raceLog); + Iterable foundTagEvents = raceState.getTagEvents(); for (RaceLogTagEvent tagEvent : foundTagEvents) { - tags.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(), - tagEvent.getUsername(), tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt())); + if (latestReceivedTagTime == null + || (latestReceivedTagTime != null && tagEvent.getRevokedAt() == null + && tagEvent.getCreatedAt().after(latestReceivedTagTime)) + || (latestReceivedTagTime != null && tagEvent.getRevokedAt() != null + && tagEvent.getRevokedAt().after(latestReceivedTagTime))) { + tags.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(), + tagEvent.getUsername(), tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt(), + tagEvent.getRevokedAt())); + } } } } @@ -6071,8 +6077,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S TagDTO tag) { SuccessInfo successInfo = new SuccessInfo(true, null, null, null); RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); - TagFinder tagFinder = new TagFinder(raceLog, tag.getCreatedAt().minus(1), tag.getCreatedAt().plus(1)); - List foundTagEvents = tagFinder.analyze(); + ReadonlyRaceState raceState = ReadonlyRaceStateImpl.getOrCreate(getService(), raceLog); + Iterable foundTagEvents = raceState.getTagEvents(); for (RaceLogTagEvent tagEvent : foundTagEvents) { if (tagEvent.getTag().equals(tag.getTag()) && tagEvent.getComment().equals(tag.getComment()) && tagEvent.getImageURL().equals(tag.getImageURL())) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java index 0efa189d720..1f2abda892b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java @@ -4,24 +4,33 @@ import com.google.gwt.user.client.rpc.IsSerializable; import com.sap.sse.common.TimePoint; public class TagDTO implements IsSerializable { - + private String tag; private String comment; private String imageURL; private String username; private TimePoint raceTimepoint; private TimePoint createdAt; - + private TimePoint revokedAt; + // for GWT - public TagDTO() {} + public TagDTO() { + } + + public TagDTO(String tag, String comment, String imageURL, String username, TimePoint raceTimepoint, + TimePoint createdAt) { + this(tag, comment, imageURL, username, raceTimepoint, createdAt, null); + } - public TagDTO(String tag, String comment, String imageURL, String username, TimePoint raceTimepoint, TimePoint createdAt) { + public TagDTO(String tag, String comment, String imageURL, String username, TimePoint raceTimepoint, + TimePoint createdAt, TimePoint revokedAt) { this.tag = tag; this.comment = comment; this.imageURL = imageURL; this.username = username; this.raceTimepoint = raceTimepoint; this.createdAt = createdAt; + this.revokedAt = revokedAt; } public String getTag() { @@ -43,11 +52,15 @@ public class TagDTO implements IsSerializable { public TimePoint getRaceTimepoint() { return raceTimepoint; } - + public TimePoint getCreatedAt() { return createdAt; } + public TimePoint getRevokedAt() { + return revokedAt; + } + @Override public boolean equals(Object obj) { if (this == obj) @@ -85,15 +98,10 @@ public class TagDTO implements IsSerializable { } return true; } - + @Override public String toString() { - return "TagDTO [tag=" + tag - + ", comment=" + comment - + ", imageURL=" + imageURL - + ", username=" + username - + ", raceTimepoint=" + raceTimepoint - + ", createdAt=" + createdAt - + "]"; + return "TagDTO [tag=" + tag + ", comment=" + comment + ", imageURL=" + imageURL + ", username=" + username + + ", raceTimepoint=" + raceTimepoint + ", createdAt=" + createdAt + ", revokedAt=" + revokedAt + "]"; } } From 606f2f08b268d32af1743381b3c9d0bd49315d4c Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Thu, 16 Aug 2018 08:46:50 +0200 Subject: [PATCH 137/292] Bug 4104: Code style improvement --- .../race/impl/RaceLogTagEventImpl.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index e9cdf4fa880..b68cb310607 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -14,24 +14,24 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE private String tag, comment, imageURL, username; private TimePoint revokedAt; - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, TimePoint createdAt, - TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, int pPassId) { - super(createdAt, logicalTimePoint, author, pId, pPassId); - tag = pTag; - comment = pComment; - imageURL = pImageURL; - username = author.getName(); - revokedAt = null; + public RaceLogTagEventImpl(String tag, String comment, String imageURL, TimePoint createdAt, + TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, int passId) { + super(createdAt, logicalTimePoint, author, id, passId); + this.tag = tag; + this.comment = comment; + this.imageURL = imageURL; + this.username = author.getName(); + this.revokedAt = null; } - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, TimePoint createdAt, - TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId) { - this(pTag, pComment, pImageURL, createdAt, logicalTimePoint, author, randId(), pPassId); + public RaceLogTagEventImpl(String tag, String comment, String imageURL, TimePoint createdAt, + TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId) { + this(tag, comment, imageURL, createdAt, logicalTimePoint, author, randId(), passId); } - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, int pPassId) { - this(pTag, pComment, pImageURL, now(), logicalTimePoint, author, randId(), pPassId); + public RaceLogTagEventImpl(String tag, String comment, String imageURL, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, int passId) { + this(tag, comment, imageURL, now(), logicalTimePoint, author, randId(), passId); } @Override From 17ab6427cc016f755e6d58b659e787d35ad1d14a Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Thu, 16 Aug 2018 09:18:40 +0200 Subject: [PATCH 138/292] Bug 4104: Only send tags which are not revoked to client at first request --- .../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 4a9521c7f10..4b3953ff63e 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 @@ -2135,7 +2135,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S ReadonlyRaceState raceState = ReadonlyRaceStateImpl.getOrCreate(getService(), raceLog); Iterable foundTagEvents = raceState.getTagEvents(); for (RaceLogTagEvent tagEvent : foundTagEvents) { - if (latestReceivedTagTime == null + if ((latestReceivedTagTime == null && tagEvent.getRevokedAt() == null) || (latestReceivedTagTime != null && tagEvent.getRevokedAt() == null && tagEvent.getCreatedAt().after(latestReceivedTagTime)) || (latestReceivedTagTime != null && tagEvent.getRevokedAt() != null From ea032e6cc25a20d95c718a66d9c1d53d067b3d4c Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Thu, 16 Aug 2018 09:47:48 +0200 Subject: [PATCH 139/292] Bug 4104: Fixed compile error regarding tag caching on Android --- .../app/ui/fragments/raceinfo/RaceSummaryFragment.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/RaceSummaryFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/RaceSummaryFragment.java index 80ff797ccb7..404a183b39d 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/RaceSummaryFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/RaceSummaryFragment.java @@ -261,6 +261,12 @@ public class RaceSummaryFragment extends BaseFragment { public void onWindFixChanged(ReadonlyRaceState state) { showData(); } + + + @Override + public void onTagEventsChanged(ReadonlyRaceState state) { + // TODO: add android support for tags + } } } From 67e68fb905118e6a55c04be6a38801e724aaa9f0 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Thu, 16 Aug 2018 11:27:11 +0200 Subject: [PATCH 140/292] Bug 4104: Remove test debug id --- .../main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 626d5df92f3..51cbb02438f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -687,7 +687,6 @@ public class TaggingPanel extends ComponentWithoutSettings mainPanel.add(controlButttonPanel); mainPanel.add(tagPreviewPanel); mainPanel.add(closeButton); - mainPanel.ensureDebugId("Test"); getElement().getStyle().setBackgroundColor("white"); setWidget(mainPanel); From 208f5663ed8cac1ab0c49b757ca89d1677281883 Mon Sep 17 00:00:00 2001 From: D067890 Date: Thu, 16 Aug 2018 11:47:57 +0200 Subject: [PATCH 141/292] bug4104: Tags contain boolean isPublic field --- .../impl/DomainObjectFactoryImpl.java | 7 ++-- .../domain/persistence/impl/FieldNames.java | 2 +- .../abstractlog/race/RaceLogTagEvent.java | 2 ++ .../race/impl/RaceLogTagEventImpl.java | 20 +++++++---- .../sailing/gwt/ui/client/SailingService.java | 2 +- .../gwt/ui/client/SailingServiceAsync.java | 2 +- .../gwt/ui/raceboard/TaggingPanel.java | 34 +++++++++++------- .../gwt/ui/server/SailingServiceImpl.java | 8 ++--- .../com/sap/sailing/gwt/ui/shared/TagDTO.java | 13 +++++-- .../sap/sailing/gwt/ui/client/images/lock.png | Bin 0 -> 374 bytes .../sailing/gwt/ui/client/images/unlock.png | Bin 0 -> 346 bytes .../impl/RaceLogTagEventDeserializer.java | 3 +- .../impl/RaceLogTagEventSerializer.java | 2 ++ .../racelog/RaceLogEventDeserializerTest.java | 3 +- .../racelog/RaceLogEventSerializerTest.java | 2 +- 15 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/lock.png create mode 100644 java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/unlock.png 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 9f11480f5b8..df0875cf51d 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 @@ -1592,7 +1592,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { resultEvent = loadRaceLogUseCompetitorsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogTagEvent.class.getSimpleName())) { - resultEvent = loadRaceLogTagEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + resultEvent = loadRaceLogTagEvent(createdAt, author, logicalTimePoint, id, passId, dbObject); }else { throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass)); } @@ -1770,12 +1770,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } private RaceLogEvent loadRaceLogTagEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + TimePoint logicalTimePoint, Serializable id, Integer passId, DBObject dbObject) { String tag = (String) dbObject.get(FieldNames.RACE_LOG_TAG.name()); String comment = (String) dbObject.get(FieldNames.RACE_LOG_COMMENT.name()); String imageURL = (String) dbObject.get(FieldNames.RACE_LOG_IMAGE_URL.name()); - return new RaceLogTagEventImpl(tag, comment, imageURL, createdAt, logicalTimePoint, author, id, passId); + boolean isPublic = (boolean) dbObject.get(FieldNames.RACE_LOG_IS_PUBLIC.name()); + return new RaceLogTagEventImpl(tag, comment, imageURL, isPublic, createdAt, logicalTimePoint, author, id, passId); } private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java index 35bebcb9fa6..6b664ae22b4 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java @@ -105,7 +105,7 @@ public enum FieldNames { RACE_LOG_REVOKED_EVENT_SHORT_INFO, RACE_LOG_REVOKED_REASON, RACE_LOG_DEVICE_MAPPING_EVENT_ID, RACE_LOG_CLOSING_TIMEPOINT, TIMEPOINT_OF_FIXED_MARKPASSING, INDEX_OF_PASSED_WAYPOINT,INDEX_OF_FIRST_SUPPRESSED_WAYPOINT, MARK, RACE_LOG_COMPETITOR_ID, RACE_LOG_BOAT_ID, RACE_LOG_DEPDENDENT_ON_FLEET, RACE_LOG_DEPDENDENT_ON_RACECOLUMN, RACE_LOG_DEPDENDENT_ON_REGATTALIKE, - RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS, RACE_LOG_TAG, RACE_LOG_COMMENT, RACE_LOG_IMAGE_URL, + RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS, RACE_LOG_TAG, RACE_LOG_COMMENT, RACE_LOG_IMAGE_URL, RACE_LOG_IS_PUBLIC, /** @deprecated Replaced by {@link #REGATTA_LOG_FROM}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_FROM, /** @deprecated Replaced by {@link #REGATTA_LOG_TO}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_TO, /** @deprecated Replaced by a regatta log entry with type {@link #REGATTA_LOG_MARK} */ @Deprecated RACE_LOG_MARK, diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java index 0cd5ad95ad0..edc273a7f65 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java @@ -11,4 +11,6 @@ public interface RaceLogTagEvent extends RaceLogEvent, Revokable { String getComment(); String getImageURL(); + + boolean isPublic(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index 76df8659711..33881d23c95 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -11,25 +11,28 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE private static final long serialVersionUID = 7213518902555323432L; - private String tag, comment, imageURL, username; + private final String tag, comment, imageURL, username; - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, TimePoint createdAt, + private final boolean visibleForPublic; + + public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, boolean pVisibleForPublic, TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, int pPassId) { super(createdAt, logicalTimePoint, author, pId, pPassId); tag = pTag; comment = pComment; imageURL = pImageURL; username = author.getName(); + visibleForPublic = pVisibleForPublic; } - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, TimePoint createdAt, + public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, boolean visibleForPublic, TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId) { - this(pTag, pComment, pImageURL, createdAt, logicalTimePoint, author, randId(), pPassId); + this(pTag, pComment, pImageURL, visibleForPublic, createdAt, logicalTimePoint, author, randId(), pPassId); } - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, + public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, boolean visibleForPublic, TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId) { - this(pTag, pComment, pImageURL, now(), logicalTimePoint, author, randId(), pPassId); + this(pTag, pComment, pImageURL, visibleForPublic, now(), logicalTimePoint, author, randId(), pPassId); } @Override @@ -61,4 +64,9 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE public String getShortInfo() { return "tag=" + tag + ", comment=" + comment; } + + @Override + public boolean isPublic() { + return visibleForPublic; + } } \ No newline at end of file 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 4bd6aeed9a9..a45a081d9f6 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 @@ -540,7 +540,7 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS void addCourseDefinitionToRaceLog(String leaderboardName, String raceColumnName, String fleetName, List> course) throws NotFoundException; SuccessInfo addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, - String imageURL, TimePoint raceTimepoint); + String imageURL, boolean isPublic, TimePoint raceTimepoint); SuccessInfo removeTagFromRaceLog(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index 63a028fb1ad..ac022a446c6 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -728,7 +728,7 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan List> course, AsyncCallback callback); void addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, - String imageURL, TimePoint raceTimepoint, AsyncCallback asyncCallback); + String imageURL, boolean isPublic, TimePoint raceTimepoint, AsyncCallback asyncCallback); void removeTagFromRaceLog(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag, AsyncCallback asyncCallback); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 604498202c2..0ee5198a4b8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -99,6 +99,12 @@ public class TaggingPanel extends ComponentWithoutSettings // TODO image is stored in wrong folder @Source("com/sap/sailing/gwt/ui/client/images/edit.png") ImageResource editIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/unlock.png") + ImageResource publicIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/lock.png") + ImageResource privateIcon(); @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Clear.png") ImageResource clearButton(); @@ -171,13 +177,14 @@ public class TaggingPanel extends ComponentWithoutSettings } public interface TagCellTemplate extends SafeHtmlTemplates { - @Template("
{3}
{4}
{5}
") + @Template("
{3}
{4}
{5}
") SafeHtml cell(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, SafeHtml createdAt, - SafeHtml content); + SafeHtml content, SafeUri safeUri); - @Template("
{3}
{4}
{5}
") + @Template("
{3}
{4}
{5}
") SafeHtml cellRemovable(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, - SafeHtml createdAt, SafeHtml content); + SafeHtml createdAt, SafeHtml content, SafeUri safeUri); + @Template("
{3}
") SafeHtml contentWithCommentWithImage(String styleTagImage, String styleTagComment, SafeUri imageURL, @@ -212,8 +219,11 @@ public class TaggingPanel extends ComponentWithoutSettings DateTimeFormat.getFormat("E d/M/y, HH:mm").format(tag.getRaceTimepoint().asDate()))); SafeHtml safeComment = SafeHtmlUtils.fromString(tag.getComment()); SafeUri trustedImageURL = UriUtils.fromTrustedString(tag.getImageURL()); + + SafeUri safeIsPublicImageUri = tag.isPublic() ? TagPanelResources.INSTANCE.publicIcon().getSafeUri() : TagPanelResources.INSTANCE.privateIcon().getSafeUri(); SafeHtml content = SafeHtmlUtils.EMPTY_SAFE_HTML; + if (tag.getComment().length() > 0 && tag.getImageURL().length() <= 0) { content = tagCellTemplate.contentWithCommentWithoutImage(tagPanelStyle.tagComment(), safeComment); } else if (tag.getComment().length() <= 0 && tag.getImageURL().length() > 0) { @@ -224,14 +234,14 @@ public class TaggingPanel extends ComponentWithoutSettings } SafeHtml cell; - if (isPreviewCell && userService.getCurrentUser() != null + if (!isPreviewCell && userService.getCurrentUser() != null && (tag.getUsername().equals(userService.getCurrentUser().getName()) || userService.getCurrentUser().hasRole("admin"))) { cell = tagCellTemplate.cellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), safeTag, safeCreated, content); + tagPanelStyle.tagCreated(), safeTag, safeCreated, content, safeIsPublicImageUri); } else { cell = tagCellTemplate.cell(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), tagPanelStyle.tagCreated(), - safeTag, safeCreated, content); + safeTag, safeCreated, content, safeIsPublicImageUri); } htmlBuilder.append(cell); } @@ -386,7 +396,7 @@ public class TaggingPanel extends ComponentWithoutSettings public TagPreviewPanel(TagCreationInputPanel inputField) { this.inputField = inputField; - tagPreviewCellList = new CellList(new TagCell(false), CellListResources.INSTANCE); + tagPreviewCellList = new CellList(new TagCell(true), CellListResources.INSTANCE); tagPreviewCellList.setVisibleRange(0, 1); previewLabel = new Label(stringMessages.tagPreview()); listContainingPreviewTag = new ArrayList(); @@ -422,8 +432,8 @@ public class TaggingPanel extends ComponentWithoutSettings public void renderPreview() { listContainingPreviewTag.removeAll(listContainingPreviewTag); previewTag = new TagDTO(inputField.getTagValue(), inputField.getCommentValue(), - inputField.getImageURLValue(), "Author", new MillisecondsTimePoint(timer.getTime()), - new MillisecondsTimePoint(timer.getTime())); + inputField.getImageURLValue(), "Author", new MillisecondsTimePoint(timer.getTime()), + new MillisecondsTimePoint(timer.getTime()), true); listContainingPreviewTag.add(previewTag); tagPreviewCellList.setRowData(listContainingPreviewTag); @@ -1005,7 +1015,7 @@ public class TaggingPanel extends ComponentWithoutSettings panel = new HeaderPanel(); filterbarPanel = new TagFilterPanel(stringMessages, tagListProvider); - tagCellList = new CellList(new TagCell(true), CellListResources.INSTANCE); + tagCellList = new CellList(new TagCell(false), CellListResources.INSTANCE); tagSelectionModel = new SingleSelectionModel(); contentPanel = new ScrollPanel(); @@ -1077,7 +1087,7 @@ public class TaggingPanel extends ComponentWithoutSettings if (isLoggedInAndRaceLogAvailable()) { if (tag.length() > 0) { sailingService.addTagToRaceLog(leaderboardName, raceColumn.getName(), fleet.getName(), tag, comment, - imageURL, new MillisecondsTimePoint(timer.getTime()), new AsyncCallback() { + imageURL, true, new MillisecondsTimePoint(timer.getTime()), new AsyncCallback() { @Override public void onFailure(Throwable caught) { Notification.notify(stringMessages.tagNotAddedReason(caught.toString()), 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 38712e77d1c..012e2f0cfd0 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 @@ -2137,7 +2137,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S List foundTagEvents = tagFinder.analyze(); for (RaceLogTagEvent tagEvent : foundTagEvents) { tags.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(), - tagEvent.getUsername(), tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt())); + tagEvent.getUsername(), tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt(), tagEvent.isPublic())); } } } @@ -6051,13 +6051,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public SuccessInfo addTagToRaceLog(String leaderboardName, String raceColumnName, String fleetName, String tag, - String comment, String imageURL, TimePoint raceTimepoint) { + String comment, String imageURL, boolean isPublic, TimePoint raceTimepoint) { SuccessInfo successInfo = new SuccessInfo(true, null, null, null); try { SecurityUtils.getSubject().checkPermission( Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); - raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, raceTimepoint, getService().getServerAuthor(), + raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, isPublic, raceTimepoint, getService().getServerAuthor(), raceLog.getCurrentPassId())); } catch (AuthorizationException e) { successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), @@ -7866,7 +7866,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public void visit(RaceLogTagEvent event) { // TODO check if if condition is correct D067890 if (hasStartTime && isLatestPass(event)) { - raceLog.add(new RaceLogTagEventImpl(event.getTag(), event.getComment(), event.getImageURL(), event.getCreatedAt(), event.getLogicalTimePoint(), + raceLog.add(new RaceLogTagEventImpl(event.getTag(), event.getComment(), event.getImageURL(), event.isPublic(), event.getCreatedAt(), event.getLogicalTimePoint(), event.getAuthor(), raceLog.getCurrentPassId())); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java index 0efa189d720..8fe0858fd70 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java @@ -9,19 +9,21 @@ public class TagDTO implements IsSerializable { private String comment; private String imageURL; private String username; + private boolean isPublic; private TimePoint raceTimepoint; private TimePoint createdAt; // for GWT public TagDTO() {} - public TagDTO(String tag, String comment, String imageURL, String username, TimePoint raceTimepoint, TimePoint createdAt) { + public TagDTO(String tag, String comment, String imageURL, String username, TimePoint raceTimepoint, TimePoint createdAt, boolean isPublic) { this.tag = tag; this.comment = comment; this.imageURL = imageURL; this.username = username; this.raceTimepoint = raceTimepoint; this.createdAt = createdAt; + this.isPublic = isPublic; } public String getTag() { @@ -39,6 +41,10 @@ public class TagDTO implements IsSerializable { public String getUsername() { return username; } + + public boolean isPublic() { + return isPublic; + } public TimePoint getRaceTimepoint() { return raceTimepoint; @@ -83,6 +89,9 @@ public class TagDTO implements IsSerializable { } else if (!username.equals(other.username)) { return false; } + if (isPublic() != other.isPublic()) { + return false; + } return true; } @@ -94,6 +103,6 @@ public class TagDTO implements IsSerializable { + ", username=" + username + ", raceTimepoint=" + raceTimepoint + ", createdAt=" + createdAt - + "]"; + + ", isPublic_]" + isPublic; } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/lock.png b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/lock.png new file mode 100644 index 0000000000000000000000000000000000000000..4aab2e0202eeebac336e263bd0d3f9e26045b84f GIT binary patch literal 374 zcmV-+0g3*JP)MH4w46{ zLv{h!fd7C0foK~Ez7JrVfi^G#ZCwZy1F;u^_#knRJV+hTwQvJi!2V!n`iEpF|EyWF zV6I?5Qq0eQ1+ZWfOj8GHQb!d_UzWyz%K%oOEx*td|7XAtK=O<*1Ac=TGoxlPAk(-2 zNFLcWObiqP7F-g@w%~IW#V!CDAcf1X#DodRfKQaV;0L}CCnga8;!7xm06>5N03pY6 Unqqs4_W%F@07*qoM6N<$f=LaKvH$=8 literal 0 HcmV?d00001 diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/unlock.png b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/unlock.png new file mode 100644 index 0000000000000000000000000000000000000000..36e90c81e9ec94b2da86ea29f0caad417879fd71 GIT binary patch literal 346 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucL5ULAh?3y^w370~qEv>0#LT=By}Z;C1rt33 zJ>#Bd(*uBNPJ6mIhFJLT?Q`ThWFX+0d~xoA2j{Fi+>53^F3I&*+#%}ng7r=%gLvL< z(Y25N%s7&H%f)r$hm23p&u5DYnqG){erBE}cft9?dKoc0N)lddk-J=Iy707_@%yty zZYK<<*M6}1aJW_Iv}@pk7|R0pbI+%#i0lv&6F+leU+)#KQ_~)ltu;>Gz;6`Sa6$ZM z%tgPQ{6AvEo=GHJ)MXC{I&fG;^WcFteL%O+6hF?hQAxvX competitorSerializer) { super(competitorSerializer); @@ -30,6 +31,7 @@ public class RaceLogTagEventSerializer extends BaseRaceLogEventSerializer{ result.put(FIELD_TAG, tagEvent.getTag()); result.put(FIELD_COMMENT, tagEvent.getComment()); result.put(FIELD_URL, tagEvent.getImageURL()); + result.put(FIELD_IS_PUBLIC, tagEvent.isPublic()); return result; } } \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogEventDeserializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogEventDeserializerTest.java index d71bfea922d..468c175dd65 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogEventDeserializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogEventDeserializerTest.java @@ -132,7 +132,7 @@ public class RaceLogEventDeserializerTest { @Test public void testSerializationAndDeserializationForRaceLogTagEvent() throws Exception{ - RaceLogTagEventImpl originalEvent = new RaceLogTagEventImpl("tag", "comment", "url", timePoint, timePoint2, author, UUID.randomUUID(), 3); + RaceLogTagEventImpl originalEvent = new RaceLogTagEventImpl("tag", "comment", "url", false, timePoint, timePoint2, author, UUID.randomUUID(), 3); RaceLogEventSerializer serializer = (RaceLogEventSerializer) RaceLogEventSerializer.create(CompetitorJsonSerializer.create()); JSONObject object = serializer.serialize(originalEvent); @@ -156,5 +156,6 @@ public class RaceLogEventDeserializerTest { assertEquals(originalEvent.getComment(), newEvent.getComment()); assertEquals(originalEvent.getImageURL(), newEvent.getImageURL()); assertEquals(originalEvent.getUsername(), newEvent.getUsername()); + assertEquals(originalEvent.isPublic(), newEvent.isPublic()); } } \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index a7a99a96558..91901e44dad 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -256,7 +256,7 @@ public class RaceLogEventSerializerTest { @Test public void testTagSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = new RaceLogTagEventImpl("", "", "", MillisecondsTimePoint.now(), author, 0); + RaceLogEvent event = new RaceLogTagEventImpl("", "", "", true, MillisecondsTimePoint.now(), author, 0); serializer.serialize(event); verify(tagEventSerializer).serialize(event); } From c79f6d2cee6df755b4b49e3ec0c4458b7c612fe5 Mon Sep 17 00:00:00 2001 From: D067890 Date: Thu, 16 Aug 2018 13:38:16 +0200 Subject: [PATCH 142/292] bug4104: While creating tag or button you can set isVisibleForPublic --- .../abstractlog/race/RaceLogTagEvent.java | 2 +- .../race/impl/RaceLogTagEventImpl.java | 2 +- .../sailing/gwt/ui/client/StringMessages.java | 2 + .../gwt/ui/client/StringMessages.properties | 1 + .../ui/client/StringMessages_de.properties | 3 +- .../gwt/ui/raceboard/TaggingPanel.java | 182 ++++++++++++------ .../gwt/ui/raceboard/tagging-panel.css | 13 +- .../gwt/ui/server/SailingServiceImpl.java | 4 +- .../com/sap/sailing/gwt/ui/shared/TagDTO.java | 14 +- .../impl/RaceLogTagEventSerializer.java | 2 +- .../racelog/RaceLogEventDeserializerTest.java | 2 +- 11 files changed, 150 insertions(+), 77 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java index edc273a7f65..40fdaa85587 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java @@ -12,5 +12,5 @@ public interface RaceLogTagEvent extends RaceLogEvent, Revokable { String getImageURL(); - boolean isPublic(); + boolean isVisibleForPublic(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index 33881d23c95..50f3e8ab670 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -66,7 +66,7 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE } @Override - public boolean isPublic() { + public boolean isVisibleForPublic() { return visibleForPublic; } } \ 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.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index f16a955e84c..f8428cf38e8 100755 --- 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 @@ -5,6 +5,7 @@ import java.util.UUID; import com.google.gwt.core.client.GWT; import com.google.gwt.i18n.client.LocalizableResource.DefaultLocale; import com.google.gwt.json.client.JSONValue; +import com.google.gwt.safehtml.shared.SafeHtml; import com.sap.sailing.domain.common.i18n.CommonStringMessages; import com.sap.sse.gwt.client.DefaultRule_0_1_n; import com.sap.sse.gwt.client.DefaultRule_1_0n; @@ -2124,4 +2125,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String tagEditCustomTagButton(); String tagSaveCustomTagButton(); String tagPreview(); + String tagVisibleForPublicCheckBox(); } 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 2eef32796d1..e66079c90f9 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 @@ -2119,3 +2119,4 @@ tagEditFilter=Edit filter tagEditCustomTagButton=Edit tag button tagSaveCustomTagButton=Save tagPreview=Tag preview: +tagVisibleForPublicCheckBox=Visible for public \ 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 fecad35cc5e..543a3fe00af 100755 --- 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 @@ -2113,4 +2113,5 @@ tagNotSpecified=Tag darf nicht leer sein! tagEditFilter=Bearbeite Filter tagEditCustomTagButton=Bearbeite Tag Button tagSaveCustomTagButton=Speichern -tagPreview=Tag Vorschau: \ No newline at end of file +tagPreview=Tag Vorschau: +tagVisibleForPublicCheckBox=Für alle sichtbar \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 0ee5198a4b8..70ffd70fe35 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -41,6 +41,7 @@ import com.google.gwt.user.cellview.client.CellTable; import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HeaderPanel; @@ -99,10 +100,10 @@ public class TaggingPanel extends ComponentWithoutSettings // TODO image is stored in wrong folder @Source("com/sap/sailing/gwt/ui/client/images/edit.png") ImageResource editIcon(); - + @Source("com/sap/sailing/gwt/ui/client/images/unlock.png") ImageResource publicIcon(); - + @Source("com/sap/sailing/gwt/ui/client/images/lock.png") ImageResource privateIcon(); @@ -127,35 +128,63 @@ public class TaggingPanel extends ComponentWithoutSettings public interface TagPanelStyle extends CssResource { // tags String tag(); + String tagPanel(); + String tagHeading(); + String tagCreated(); + String tagComment(); + String tagImage(); + String button(); + String footerButton(); + String tagButtonTable(); + String inputPanelTag(); + String inputPanelComment(); + String inputPanelImageURL(); + String footerPanel(); + String tagPreviewPanel(); // filter tags String tagFilterButton(); + String tagFilterHiddenButton(); + String tagFilterClearButton(); + String tagFilterSearchButton(); + String tagFilterSettingsButton(); + String tagFilterFilterButton(); + String tagFilterContainer(); + String tagFilterSearchBox(); + String tagFilterSearchInput(); + String filterInactiveButtonBackgroundImage(); + String filterActiveButtonBackgroundImage(); + String clearButtonBackgroundImage(); + String searchButtonBackgroundImage(); + String settingsButtonBackgroundImage(); + + String inputPanelIsVisibleForPublic(); } } @@ -168,10 +197,15 @@ public class TaggingPanel extends ComponentWithoutSettings public interface CellListStyle extends CellList.Style { String cellListEventItem(); + String cellListWidget(); + String cellListEvenItem(); + String cellListOddItem(); + String cellListSelectedItem(); + String cellListKeyboardSelectedItem(); } } @@ -184,7 +218,6 @@ public class TaggingPanel extends ComponentWithoutSettings @Template("
{3}
{4}
{5}
") SafeHtml cellRemovable(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, SafeHtml createdAt, SafeHtml content, SafeUri safeUri); - @Template("
{3}
") SafeHtml contentWithCommentWithImage(String styleTagImage, String styleTagComment, SafeUri imageURL, @@ -219,11 +252,12 @@ public class TaggingPanel extends ComponentWithoutSettings DateTimeFormat.getFormat("E d/M/y, HH:mm").format(tag.getRaceTimepoint().asDate()))); SafeHtml safeComment = SafeHtmlUtils.fromString(tag.getComment()); SafeUri trustedImageURL = UriUtils.fromTrustedString(tag.getImageURL()); - - SafeUri safeIsPublicImageUri = tag.isPublic() ? TagPanelResources.INSTANCE.publicIcon().getSafeUri() : TagPanelResources.INSTANCE.privateIcon().getSafeUri(); + + SafeUri safeIsVisibelForPublicImageUri = tag.isVisibleForPublic() ? TagPanelResources.INSTANCE.publicIcon().getSafeUri() + : TagPanelResources.INSTANCE.privateIcon().getSafeUri(); SafeHtml content = SafeHtmlUtils.EMPTY_SAFE_HTML; - + if (tag.getComment().length() > 0 && tag.getImageURL().length() <= 0) { content = tagCellTemplate.contentWithCommentWithoutImage(tagPanelStyle.tagComment(), safeComment); } else if (tag.getComment().length() <= 0 && tag.getImageURL().length() > 0) { @@ -238,10 +272,10 @@ public class TaggingPanel extends ComponentWithoutSettings && (tag.getUsername().equals(userService.getCurrentUser().getName()) || userService.getCurrentUser().hasRole("admin"))) { cell = tagCellTemplate.cellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), safeTag, safeCreated, content, safeIsPublicImageUri); + tagPanelStyle.tagCreated(), safeTag, safeCreated, content, safeIsVisibelForPublicImageUri); } else { cell = tagCellTemplate.cell(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), tagPanelStyle.tagCreated(), - safeTag, safeCreated, content, safeIsPublicImageUri); + safeTag, safeCreated, content, safeIsVisibelForPublicImageUri); } htmlBuilder.append(cell); } @@ -284,17 +318,19 @@ public class TaggingPanel extends ComponentWithoutSettings private class TagButton extends Button { private String tag, imageURL, comment; + private boolean visibleForPublic; - public TagButton(String buttonName, String tag, String imageURL, String comment) { + public TagButton(String buttonName, String tag, String imageURL, String comment, boolean visibleForPublic) { super(buttonName); this.tag = tag; this.imageURL = imageURL; this.comment = comment; + this.visibleForPublic = visibleForPublic; setStyleName(TagPanelResources.INSTANCE.style().footerButton()); addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - addTagToRaceLog(getTag(), getComment(), getImageURL()); + addTagToRaceLog(getTag(), getComment(), getImageURL(), isVisibleForPublic()); } }); } @@ -310,6 +346,10 @@ public class TaggingPanel extends ComponentWithoutSettings public String getComment() { return comment; } + + public boolean isVisibleForPublic() { + return visibleForPublic; + } public void setTag(String tag) { this.tag = tag; @@ -348,8 +388,8 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onClick(ClickEvent event) { if (isLoggedInAndRaceLogAvailable()) { - addTagToRaceLog(inputPanel.getTagValue(), inputPanel.getCommentValue(), - inputPanel.getImageURLValue()); + addTagToRaceLog(inputPanel.getTag(), inputPanel.getComment(), + inputPanel.getImageURL(), inputPanel.isVisibleForPublic()); inputPanel.clearAllValues(); } } @@ -426,47 +466,59 @@ public class TaggingPanel extends ComponentWithoutSettings } }); + inputField.getVisibleForPublicCheckBox().addValueChangeHandler(new ValueChangeHandler() { + @Override + public void onValueChange(ValueChangeEvent event) { + renderPreview(); + } + }); renderPreview(); } public void renderPreview() { listContainingPreviewTag.removeAll(listContainingPreviewTag); - previewTag = new TagDTO(inputField.getTagValue(), inputField.getCommentValue(), - inputField.getImageURLValue(), "Author", new MillisecondsTimePoint(timer.getTime()), - new MillisecondsTimePoint(timer.getTime()), true); + previewTag = new TagDTO(inputField.getTag(), inputField.getComment(), + inputField.getImageURL(), "Author", new MillisecondsTimePoint(timer.getTime()), + new MillisecondsTimePoint(timer.getTime()), inputField.isVisibleForPublic()); listContainingPreviewTag.add(previewTag); tagPreviewCellList.setRowData(listContainingPreviewTag); - setVisible(!inputField.getTagValue().isEmpty()); + setVisible(!inputField.getTag().isEmpty()); } } public class TagCreationInputPanel extends FlowPanel { - private TextBox tagTextBox, imageURLTextBox; - private TextArea commentTextArea; + private final TextBox tagTextBox, imageURLTextBox; + private final TextArea commentTextArea; + private final CheckBox visibleForPublicCheckBox; + private final TagPanelStyle style; public TagCreationInputPanel(StringMessages stringMessages) { + style = TagPanelResources.INSTANCE.style(); setWidth("100%"); tagTextBox = new TextBox(); - tagTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelTag()); + tagTextBox.setStyleName(style.inputPanelTag()); tagTextBox.setTitle(stringMessages.tagLabelTag()); tagTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelTag()); add(tagTextBox); imageURLTextBox = new TextBox(); - imageURLTextBox.setStyleName(TagPanelResources.INSTANCE.style().inputPanelImageURL()); + imageURLTextBox.setStyleName(style.inputPanelImageURL()); imageURLTextBox.setTitle(stringMessages.tagLabelImageURL()); imageURLTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelImageURL()); add(imageURLTextBox); commentTextArea = new TextArea(); - commentTextArea.setStyleName(TagPanelResources.INSTANCE.style().inputPanelComment()); + commentTextArea.setStyleName(style.inputPanelComment()); commentTextArea.setVisibleLines(4); commentTextArea.setTitle(stringMessages.tagLabelComment()); commentTextArea.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment()); add(commentTextArea); - + + visibleForPublicCheckBox = new CheckBox(stringMessages.tagVisibleForPublicCheckBox()); + visibleForPublicCheckBox.setStyleName(style.inputPanelIsVisibleForPublic()); + add(visibleForPublicCheckBox); } public TextBox getTagTextBox() { @@ -480,28 +532,36 @@ public class TaggingPanel extends ComponentWithoutSettings public TextArea getCommentTextArea() { return commentTextArea; } + + public CheckBox getVisibleForPublicCheckBox() { + return visibleForPublicCheckBox; + } - public String getTagValue() { + public String getTag() { return tagTextBox.getValue(); } - public String getCommentValue() { + public String getComment() { return commentTextArea.getValue(); } - public String getImageURLValue() { + public String getImageURL() { return imageURLTextBox.getValue(); } + + public boolean isVisibleForPublic() { + return visibleForPublicCheckBox.getValue(); + } - public void setTagValue(String tag) { + public void setTag(String tag) { tagTextBox.setValue(tag); } - public void setCommentValue(String comment) { + public void setComment(String comment) { commentTextArea.setValue(comment); } - public void setImageURLValue(String imageURL) { + public void setImageURL(String imageURL) { imageURLTextBox.setValue(imageURL); } @@ -561,26 +621,26 @@ public class TaggingPanel extends ComponentWithoutSettings public void update(int index, TagButton button, String value) { if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { final int heightOfTagButtonPanel = customButtonsPanel.getOffsetHeight(); - + customTagButtons.remove(button); customButtonsPanel.remove(button); customTagButtonsTable.setRowData(customTagButtons); - + final int deltaHeight = customButtonsPanel.getOffsetHeight() - heightOfTagButtonPanel; - /* - * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), - * the footerWidget of the TaggingPanel has a different height, - * which in this case might cause the contentWidget to be to small. - */ - if(deltaHeight != 0) { + /* + * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), the + * footerWidget of the TaggingPanel has a different height, which in this case might cause the + * contentWidget to be to small. + */ + if (deltaHeight != 0) { panel.setContentWidget(contentPanel); } } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { selectedTagButton = button; - inputPanel.setTagValue(button.getTag()); - inputPanel.setImageURLValue(button.getImageURL()); - inputPanel.setCommentValue(button.getComment()); + inputPanel.setTag(button.getTag()); + inputPanel.setImageURL(button.getImageURL()); + inputPanel.setComment(button.getComment()); tagPreviewPanel.renderPreview(); @@ -610,25 +670,25 @@ public class TaggingPanel extends ComponentWithoutSettings addCustomTagButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - if (inputPanel.getTagValue().length() > 0) { + if (inputPanel.getTag().length() > 0) { final int heightOfTagButtonPanel = customButtonsPanel.getOffsetHeight(); - - TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), - inputPanel.getImageURLValue(), inputPanel.getCommentValue()); + + TagButton tagButton = new TagButton(inputPanel.getTag(), inputPanel.getTag(), + inputPanel.getImageURL(), inputPanel.getComment(), inputPanel.isVisibleForPublic()); inputPanel.clearAllValues(); tagPreviewPanel.renderPreview(); customTagButtons.add(tagButton); customButtonsPanel.add(tagButton); setRowData(customTagButtons); - + final int deltaHeight = customButtonsPanel.getOffsetHeight() - heightOfTagButtonPanel; - /* - * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), - * the footerWidget of the TaggingPanel has a different height, - * which might cause the contentWidget to overlap the footerWidget. - */ - if(deltaHeight != 0) { + /* + * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), the + * footerWidget of the TaggingPanel has a different height, which might cause the contentWidget + * to overlap the footerWidget. + */ + if (deltaHeight != 0) { panel.setContentWidget(contentPanel); } } else { @@ -643,11 +703,11 @@ public class TaggingPanel extends ComponentWithoutSettings saveChangesButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - if (inputPanel.getTagValue().length() > 0) { - selectedTagButton.setText(inputPanel.getTagValue()); - selectedTagButton.setTag(inputPanel.getTagValue()); - selectedTagButton.setComment(inputPanel.getCommentValue()); - selectedTagButton.setImageURL(inputPanel.getImageURLValue()); + if (inputPanel.getTag().length() > 0) { + selectedTagButton.setText(inputPanel.getTag()); + selectedTagButton.setTag(inputPanel.getTag()); + selectedTagButton.setComment(inputPanel.getComment()); + selectedTagButton.setImageURL(inputPanel.getImageURL()); inputPanel.clearAllValues(); tagPreviewPanel.renderPreview(); customTagButtonsTable.redraw(); @@ -699,7 +759,7 @@ public class TaggingPanel extends ComponentWithoutSettings mainPanel.add(closeButton); mainPanel.ensureDebugId("Test"); getElement().getStyle().setBackgroundColor("white"); - + setWidget(mainPanel); } @@ -1008,7 +1068,7 @@ public class TaggingPanel extends ComponentWithoutSettings TagPanelResources.INSTANCE.style().ensureInjected(); CellListResources.INSTANCE.cellListStyle().ensureInjected(); - //TODO Add this label to ui + // TODO Add this label to ui currentFilterLabel = new Label(); tagListProvider = new TagListProvider(currentFilterLabel); customTagButtons = new ArrayList(); @@ -1061,8 +1121,8 @@ public class TaggingPanel extends ComponentWithoutSettings timer.setTime(tagSelectionModel.getSelectedObject().getRaceTimepoint().asMillis()); } }); - - //contentPanel.add(currentFilterLabel); + + // contentPanel.add(currentFilterLabel); contentPanel.add(tagCellList); contentPanel.getElement().getStyle().setHeight(100, Unit.PCT); contentPanel.getElement().getStyle().setPaddingTop(10, Unit.PX); @@ -1083,11 +1143,11 @@ public class TaggingPanel extends ComponentWithoutSettings } } - private void addTagToRaceLog(String tag, String comment, String imageURL) { + private void addTagToRaceLog(String tag, String comment, String imageURL, boolean isPublic) { if (isLoggedInAndRaceLogAvailable()) { if (tag.length() > 0) { sailingService.addTagToRaceLog(leaderboardName, raceColumn.getName(), fleet.getName(), tag, comment, - imageURL, true, new MillisecondsTimePoint(timer.getTime()), new AsyncCallback() { + imageURL, isPublic, new MillisecondsTimePoint(timer.getTime()), new AsyncCallback() { @Override public void onFailure(Throwable caught) { Notification.notify(stringMessages.tagNotAddedReason(caught.toString()), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css index 1c5db6822b4..e6f750cbb45 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css @@ -113,11 +113,20 @@ b { border: 1px solid #cecece; margin-top: -1px; resize: none; - margin-bottom: 5px; - border-radius: 0px 0px 4px 4px; + border-radius: 0px 0px 0px 4px; width: 100%; } +.inputPanelIsVisibleForPublic { + float: right; + padding: 2px; + border: 1px solid #cecece; + resize: none; + border-radius: 0px 0px 4px 4px; + margin-bottom: 5px; + margin-top: -3px; +} + /**************************** Tag filtering ****************************/ .tagFilterContainer { max-width: 425px; 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 012e2f0cfd0..cfa9ad6ef19 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 @@ -2137,7 +2137,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S List foundTagEvents = tagFinder.analyze(); for (RaceLogTagEvent tagEvent : foundTagEvents) { tags.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(), - tagEvent.getUsername(), tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt(), tagEvent.isPublic())); + tagEvent.getUsername(), tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt(), tagEvent.isVisibleForPublic())); } } } @@ -7866,7 +7866,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public void visit(RaceLogTagEvent event) { // TODO check if if condition is correct D067890 if (hasStartTime && isLatestPass(event)) { - raceLog.add(new RaceLogTagEventImpl(event.getTag(), event.getComment(), event.getImageURL(), event.isPublic(), event.getCreatedAt(), event.getLogicalTimePoint(), + raceLog.add(new RaceLogTagEventImpl(event.getTag(), event.getComment(), event.getImageURL(), event.isVisibleForPublic(), event.getCreatedAt(), event.getLogicalTimePoint(), event.getAuthor(), raceLog.getCurrentPassId())); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java index 8fe0858fd70..14cd192b320 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java @@ -9,21 +9,21 @@ public class TagDTO implements IsSerializable { private String comment; private String imageURL; private String username; - private boolean isPublic; + private boolean visibleForPublic; private TimePoint raceTimepoint; private TimePoint createdAt; // for GWT public TagDTO() {} - public TagDTO(String tag, String comment, String imageURL, String username, TimePoint raceTimepoint, TimePoint createdAt, boolean isPublic) { + public TagDTO(String tag, String comment, String imageURL, String username, TimePoint raceTimepoint, TimePoint createdAt, boolean visibleForPublic) { this.tag = tag; this.comment = comment; this.imageURL = imageURL; this.username = username; this.raceTimepoint = raceTimepoint; this.createdAt = createdAt; - this.isPublic = isPublic; + this.visibleForPublic = visibleForPublic; } public String getTag() { @@ -42,8 +42,8 @@ public class TagDTO implements IsSerializable { return username; } - public boolean isPublic() { - return isPublic; + public boolean isVisibleForPublic() { + return visibleForPublic; } public TimePoint getRaceTimepoint() { @@ -89,7 +89,7 @@ public class TagDTO implements IsSerializable { } else if (!username.equals(other.username)) { return false; } - if (isPublic() != other.isPublic()) { + if (isVisibleForPublic() != other.isVisibleForPublic()) { return false; } return true; @@ -103,6 +103,6 @@ public class TagDTO implements IsSerializable { + ", username=" + username + ", raceTimepoint=" + raceTimepoint + ", createdAt=" + createdAt - + ", isPublic_]" + isPublic; + + ", isPublic_]" + visibleForPublic; } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java index b5c754b63b0..69879d7d5e3 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java @@ -31,7 +31,7 @@ public class RaceLogTagEventSerializer extends BaseRaceLogEventSerializer{ result.put(FIELD_TAG, tagEvent.getTag()); result.put(FIELD_COMMENT, tagEvent.getComment()); result.put(FIELD_URL, tagEvent.getImageURL()); - result.put(FIELD_IS_PUBLIC, tagEvent.isPublic()); + result.put(FIELD_IS_PUBLIC, tagEvent.isVisibleForPublic()); return result; } } \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogEventDeserializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogEventDeserializerTest.java index 468c175dd65..d8495863f84 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogEventDeserializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogEventDeserializerTest.java @@ -156,6 +156,6 @@ public class RaceLogEventDeserializerTest { assertEquals(originalEvent.getComment(), newEvent.getComment()); assertEquals(originalEvent.getImageURL(), newEvent.getImageURL()); assertEquals(originalEvent.getUsername(), newEvent.getUsername()); - assertEquals(originalEvent.isPublic(), newEvent.isPublic()); + assertEquals(originalEvent.isVisibleForPublic(), newEvent.isVisibleForPublic()); } } \ No newline at end of file From dba81066df4abe3c28aff3ff68d93b61285312b5 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Thu, 16 Aug 2018 13:51:55 +0200 Subject: [PATCH 143/292] Bug 4104: Fixed bug where tags with the same content where not cached correctly. --- .../abstractlog/race/analyzing/impl/TagFinder.java | 10 ++-------- .../abstractlog/race/impl/RaceLogTagEventImpl.java | 10 ++++++++++ .../sap/sailing/gwt/ui/server/SailingServiceImpl.java | 4 +++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/TagFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/TagFinder.java index 66e7b173c0d..2c0164d85fc 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/TagFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/TagFinder.java @@ -24,10 +24,7 @@ public class TagFinder extends RaceLogAnalyzer> { for (RaceLogEvent raceLogEvent : raceLogEvents) { if (raceLogEvent instanceof RaceLogTagEvent) { // tag event is not revoked (at least until this point of time at scanning race log) - RaceLogTagEvent tagEvent = (RaceLogTagEvent) raceLogEvent; - if (!result.contains(tagEvent)) { - result.add(tagEvent); - } + result.add((RaceLogTagEvent) raceLogEvent); } else if (raceLogEvent instanceof RaceLogRevokeEvent) { // tag event got revoked => update it in result list or add it to result as revoked tag event RaceLogRevokeEvent revokeEvent = (RaceLogRevokeEvent) raceLogEvent; @@ -35,11 +32,8 @@ public class TagFinder extends RaceLogAnalyzer> { if (revokedEvent != null && revokedEvent instanceof RaceLogTagEvent) { RaceLogTagEvent revokedTagEvent = (RaceLogTagEvent) revokedEvent; int index = result.indexOf(revokedTagEvent); - if (index > 0) { + if (index >= 0) { result.get(index).markAsRevoked(revokeEvent.getCreatedAt()); - } else { - revokedTagEvent.markAsRevoked(revokeEvent.getCreatedAt()); - result.add(revokedTagEvent); } } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index b68cb310607..1f1d2208baf 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -108,6 +108,16 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE return false; } else if (!username.equals(other.username)) return false; + if (getLogicalTimePoint() == null) { + if (other.getLogicalTimePoint() != null) + return false; + } else if (!getLogicalTimePoint().equals(other.getLogicalTimePoint())) + return false; + if (getCreatedAt() == null) { + if (other.getCreatedAt() != null) + return false; + } else if (!getCreatedAt().equals(other.getCreatedAt())) + return false; return true; } 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 4b3953ff63e..4dc6e246c53 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 @@ -6081,7 +6081,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Iterable foundTagEvents = raceState.getTagEvents(); for (RaceLogTagEvent tagEvent : foundTagEvents) { if (tagEvent.getTag().equals(tag.getTag()) && tagEvent.getComment().equals(tag.getComment()) - && tagEvent.getImageURL().equals(tag.getImageURL())) { + && tagEvent.getImageURL().equals(tag.getImageURL()) + && tagEvent.getUsername().equals(tag.getUsername()) + && tagEvent.getLogicalTimePoint().equals(tag.getRaceTimepoint())) { try { // check if logged in user is the same user as the creator or logged in user is Administrator Subject subject = SecurityUtils.getSubject(); From 369c8ff132330b23301e01da13e0f42231612501 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Thu, 16 Aug 2018 14:35:57 +0200 Subject: [PATCH 144/292] Bug 4104: Adapt UI to match previous designs. --- .../sap/sailing/gwt/ui/raceboard/TaggingPanel.java | 11 ++++++++++- .../sap/sailing/gwt/ui/raceboard/tagging-panel.css | 4 +--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 51cbb02438f..d99f3e70eec 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -334,6 +334,7 @@ public class TaggingPanel extends ComponentWithoutSettings createTagFromTextBoxes = new Button(stringMessages.tagAddTag()); createTagFromTextBoxes.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); + createTagFromTextBoxes.addStyleName("gwt-Button"); createTagFromTextBoxes.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -348,6 +349,7 @@ public class TaggingPanel extends ComponentWithoutSettings editCustomTagButtons = new Button(stringMessages.tagEditCustomTagButtons()); editCustomTagButtons.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); + editCustomTagButtons.addStyleName("gwt-Button"); editCustomTagButtons.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -597,6 +599,7 @@ public class TaggingPanel extends ComponentWithoutSettings addCustomTagButton = new Button(stringMessages.tagAddCustomTagButton()); addCustomTagButton.setStyleName(style.footerButton()); + addCustomTagButton.addStyleName("gwt-Button"); addCustomTagButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -630,6 +633,7 @@ public class TaggingPanel extends ComponentWithoutSettings saveChangesButton = new Button(stringMessages.save()); saveChangesButton.setVisible(false); saveChangesButton.setStyleName(style.footerButton()); + saveChangesButton.addStyleName("gwt-Button"); saveChangesButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -656,6 +660,7 @@ public class TaggingPanel extends ComponentWithoutSettings cancelChangesButton = new Button(stringMessages.cancel()); cancelChangesButton.setVisible(false); cancelChangesButton.setStyleName(style.footerButton()); + cancelChangesButton.addStyleName("gwt-Button"); cancelChangesButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -670,6 +675,7 @@ public class TaggingPanel extends ComponentWithoutSettings closeButton = new Button(stringMessages.close()); closeButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); + closeButton.addStyleName("gwt-Button"); closeButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -743,6 +749,7 @@ public class TaggingPanel extends ComponentWithoutSettings Button submitButton = new Button(); submitButton.setStyleName(css.tagFilterButton()); + submitButton.addStyleName("gwt-Button"); submitButton.addStyleName(css.tagFilterSearchButton()); submitButton.addStyleName(css.searchButtonBackgroundImage()); @@ -756,6 +763,7 @@ public class TaggingPanel extends ComponentWithoutSettings clearTextBoxButton.addStyleName(css.tagFilterClearButton()); clearTextBoxButton.addStyleName(css.clearButtonBackgroundImage()); clearTextBoxButton.addStyleName(css.tagFilterHiddenButton()); + clearTextBoxButton.addStyleName("gwt-Button"); clearTextBoxButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -766,8 +774,9 @@ public class TaggingPanel extends ComponentWithoutSettings filterSettingsButton = new Button(""); filterSettingsButton.setStyleName(css.tagFilterButton()); filterSettingsButton.addStyleName(css.tagFilterFilterButton()); - filterSettingsButton.setTitle(stringMessages.tagsFilter()); filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); + filterSettingsButton.addStyleName("gwt-Button"); + filterSettingsButton.setTitle(stringMessages.tagsFilter()); filterSettingsButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css index 1c5db6822b4..6e80e82745a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css @@ -60,7 +60,6 @@ b { .button { - background-color: #fff; border: 1px solid #cecece; margin-left: 5px; margin-bottom: 5px; @@ -70,7 +69,6 @@ b { } .footerButton { - background-color: #fff; border: 1px solid #cecece; margin-left: 5px; margin-bottom: 5px; @@ -178,7 +176,7 @@ b { } .tagFilterClearButton { - right: 7.3em; + right: 3.8em; top: 0.2em; } From 41a02102cecba674b12018de180503661ed336da Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Thu, 16 Aug 2018 15:30:00 +0200 Subject: [PATCH 145/292] Bug 4104: Code formatting --- .../gwt/ui/raceboard/TaggingPanel.java | 59 ++++++++----------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index d99f3e70eec..710dd2914a8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -10,7 +10,6 @@ import java.util.Map; import com.google.gwt.cell.client.AbstractCell; import com.google.gwt.cell.client.FieldUpdater; import com.google.gwt.cell.client.ValueUpdater; -import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.shared.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.EventTarget; @@ -354,16 +353,7 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onClick(ClickEvent event) { if (isLoggedInAndRaceLogAvailable()) { - EditCustomTagButtonsDialog editCustomTagButtonsDialog = new EditCustomTagButtonsDialog( - customButtonsPanel); - - // scheduler is used because otherwise DialogBox would not be centered properly - Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { - public void execute() { - editCustomTagButtonsDialog.show(); - editCustomTagButtonsDialog.center(); - } - }); + new EditCustomTagButtonsDialog(customButtonsPanel); updateButtons(); } } @@ -553,18 +543,18 @@ public class TaggingPanel extends ComponentWithoutSettings public void update(int index, TagButton button, String value) { if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { final int heightOfTagButtonPanel = customButtonsPanel.getOffsetHeight(); - + customTagButtons.remove(button); customButtonsPanel.remove(button); customTagButtonsTable.setRowData(customTagButtons); - + final int deltaHeight = customButtonsPanel.getOffsetHeight() - heightOfTagButtonPanel; - /* - * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), - * the footerWidget of the TaggingPanel has a different height, - * which in this case might cause the contentWidget to be to small. - */ - if(deltaHeight != 0) { + /* + * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), the + * footerWidget of the TaggingPanel has a different height, which in this case might cause the + * contentWidget to be to small. + */ + if (deltaHeight != 0) { panel.setContentWidget(contentPanel); } } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { @@ -605,7 +595,7 @@ public class TaggingPanel extends ComponentWithoutSettings public void onClick(ClickEvent event) { if (inputPanel.getTagValue().length() > 0) { final int heightOfTagButtonPanel = customButtonsPanel.getOffsetHeight(); - + TagButton tagButton = new TagButton(inputPanel.getTagValue(), inputPanel.getTagValue(), inputPanel.getImageURLValue(), inputPanel.getCommentValue()); inputPanel.clearAllValues(); @@ -614,14 +604,14 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtons.add(tagButton); customButtonsPanel.add(tagButton); setRowData(customTagButtons); - + final int deltaHeight = customButtonsPanel.getOffsetHeight() - heightOfTagButtonPanel; - /* - * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), - * the footerWidget of the TaggingPanel has a different height, - * which might cause the contentWidget to overlap the footerWidget. - */ - if(deltaHeight != 0) { + /* + * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), the + * footerWidget of the TaggingPanel has a different height, which might cause the contentWidget + * to overlap the footerWidget. + */ + if (deltaHeight != 0) { panel.setContentWidget(contentPanel); } } else { @@ -679,7 +669,7 @@ public class TaggingPanel extends ComponentWithoutSettings closeButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - hideDialog(); + hide(); } }); controlButttonPanel.add(addCustomTagButton); @@ -694,12 +684,9 @@ public class TaggingPanel extends ComponentWithoutSettings mainPanel.add(tagPreviewPanel); mainPanel.add(closeButton); getElement().getStyle().setBackgroundColor("white"); - - setWidget(mainPanel); - } - private void hideDialog() { - this.hide(); + setWidget(mainPanel); + center(); } private void setRowData(List buttons) { @@ -1006,7 +993,7 @@ public class TaggingPanel extends ComponentWithoutSettings TagPanelResources.INSTANCE.style().ensureInjected(); CellListResources.INSTANCE.cellListStyle().ensureInjected(); - //TODO Add this label to ui + // TODO Add this label to ui currentFilterLabel = new Label(); tagListProvider = new TagListProvider(currentFilterLabel); customTagButtons = new ArrayList(); @@ -1059,8 +1046,8 @@ public class TaggingPanel extends ComponentWithoutSettings timer.setTime(tagSelectionModel.getSelectedObject().getRaceTimepoint().asMillis()); } }); - - //contentPanel.add(currentFilterLabel); + + // contentPanel.add(currentFilterLabel); contentPanel.add(tagCellList); contentPanel.getElement().getStyle().setHeight(100, Unit.PCT); contentPanel.getElement().getStyle().setPaddingTop(10, Unit.PX); From bd52f60cd8d080d0291214b8971aac919d350a26 Mon Sep 17 00:00:00 2001 From: D067890 Date: Thu, 16 Aug 2018 15:55:49 +0200 Subject: [PATCH 146/292] bug4104: Public/Private works --- .../race/impl/RaceLogTagEventImpl.java | 13 +- .../gwt/ui/raceboard/TaggingPanel.java | 26 +- .../gwt/ui/server/SailingServiceImpl.java | 2957 ++++++++++------- .../impl/RaceLogTagEventDeserializer.java | 2 +- .../impl/RaceLogTagEventSerializer.java | 8 +- 5 files changed, 1738 insertions(+), 1268 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index 915a4e6072e..f131a7a99e3 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -15,8 +15,9 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE private TimePoint revokedAt; private final boolean visibleForPublic; - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, boolean pVisibleForPublic, TimePoint createdAt, - TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, int pPassId) { + public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, boolean pVisibleForPublic, + TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, + int pPassId) { super(createdAt, logicalTimePoint, author, pId, pPassId); tag = pTag; comment = pComment; @@ -26,13 +27,13 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE this.revokedAt = null; } - public RaceLogTagEventImpl(String tag, String comment, String imageURL, boolean visibleForPublic, TimePoint createdAt, - TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId) { + public RaceLogTagEventImpl(String tag, String comment, String imageURL, boolean visibleForPublic, + TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId) { this(tag, comment, imageURL, visibleForPublic, createdAt, logicalTimePoint, author, randId(), passId); } - public RaceLogTagEventImpl(String tag, String comment, String imageURL, boolean visibleForPublic, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, int passId) { + public RaceLogTagEventImpl(String tag, String comment, String imageURL, boolean visibleForPublic, + TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId) { this(tag, comment, imageURL, visibleForPublic, now(), logicalTimePoint, author, randId(), passId); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 2a2c5fdaee2..7c053833445 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -253,7 +253,8 @@ public class TaggingPanel extends ComponentWithoutSettings SafeHtml safeComment = SafeHtmlUtils.fromString(tag.getComment()); SafeUri trustedImageURL = UriUtils.fromTrustedString(tag.getImageURL()); - SafeUri safeIsVisibelForPublicImageUri = tag.isVisibleForPublic() ? TagPanelResources.INSTANCE.publicIcon().getSafeUri() + SafeUri safeIsVisibelForPublicImageUri = tag.isVisibleForPublic() + ? TagPanelResources.INSTANCE.publicIcon().getSafeUri() : TagPanelResources.INSTANCE.privateIcon().getSafeUri(); SafeHtml content = SafeHtmlUtils.EMPTY_SAFE_HTML; @@ -346,7 +347,7 @@ public class TaggingPanel extends ComponentWithoutSettings public String getComment() { return comment; } - + public boolean isVisibleForPublic() { return visibleForPublic; } @@ -388,8 +389,8 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onClick(ClickEvent event) { if (isLoggedInAndRaceLogAvailable()) { - addTagToRaceLog(inputPanel.getTag(), inputPanel.getComment(), - inputPanel.getImageURL(), inputPanel.isVisibleForPublic()); + addTagToRaceLog(inputPanel.getTag(), inputPanel.getComment(), inputPanel.getImageURL(), + inputPanel.isVisibleForPublic()); inputPanel.clearAllValues(); } } @@ -469,7 +470,7 @@ public class TaggingPanel extends ComponentWithoutSettings inputField.getVisibleForPublicCheckBox().addValueChangeHandler(new ValueChangeHandler() { @Override public void onValueChange(ValueChangeEvent event) { - renderPreview(); + renderPreview(); } }); renderPreview(); @@ -477,8 +478,8 @@ public class TaggingPanel extends ComponentWithoutSettings public void renderPreview() { listContainingPreviewTag.removeAll(listContainingPreviewTag); - previewTag = new TagDTO(inputField.getTag(), inputField.getComment(), - inputField.getImageURL(), "Author", inputField.isVisibleForPublic(), new MillisecondsTimePoint(timer.getTime()), + previewTag = new TagDTO(inputField.getTag(), inputField.getComment(), inputField.getImageURL(), "Author", + inputField.isVisibleForPublic(), new MillisecondsTimePoint(timer.getTime()), new MillisecondsTimePoint(timer.getTime())); listContainingPreviewTag.add(previewTag); tagPreviewCellList.setRowData(listContainingPreviewTag); @@ -515,7 +516,7 @@ public class TaggingPanel extends ComponentWithoutSettings commentTextArea.setTitle(stringMessages.tagLabelComment()); commentTextArea.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment()); add(commentTextArea); - + visibleForPublicCheckBox = new CheckBox(stringMessages.tagVisibleForPublicCheckBox()); visibleForPublicCheckBox.setStyleName(style.inputPanelIsVisibleForPublic()); add(visibleForPublicCheckBox); @@ -532,7 +533,7 @@ public class TaggingPanel extends ComponentWithoutSettings public TextArea getCommentTextArea() { return commentTextArea; } - + public CheckBox getVisibleForPublicCheckBox() { return visibleForPublicCheckBox; } @@ -548,9 +549,9 @@ public class TaggingPanel extends ComponentWithoutSettings public String getImageURL() { return imageURLTextBox.getValue(); } - + public boolean isVisibleForPublic() { - return visibleForPublicCheckBox.getValue(); + return visibleForPublicCheckBox.getValue(); } public void setTag(String tag) { @@ -1146,7 +1147,8 @@ public class TaggingPanel extends ComponentWithoutSettings if (isLoggedInAndRaceLogAvailable()) { if (tag.length() > 0) { sailingService.addTagToRaceLog(leaderboardName, raceColumn.getName(), fleet.getName(), tag, comment, - imageURL, isPublic, new MillisecondsTimePoint(timer.getTime()), new AsyncCallback() { + imageURL, isPublic, new MillisecondsTimePoint(timer.getTime()), + new AsyncCallback() { @Override public void onFailure(Throwable caught) { Notification.notify(stringMessages.tagNotAddedReason(caught.toString()), 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 c1101867b76..83e219c17ef 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 @@ -587,11 +587,11 @@ import com.sap.sse.util.ServiceTrackerFactory; import com.sap.sse.util.ThreadPoolUtil; import com.sapsailing.xrr.structureimport.eventimport.RegattaJSON; - /** * The server side implementation of the RPC service. */ -public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements SailingService, RaceFetcher, RegattaFetcher { +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"; @@ -607,7 +607,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private final ServiceTracker scoreCorrectionProviderServiceTracker; private final ServiceTracker competitorProviderServiceTracker; - + private final ServiceTracker windFinderTrackerFactoryServiceTracker; private final MongoObjectFactory mongoObjectFactory; @@ -615,7 +615,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private final ServiceTracker expeditionConnectorTracker; private final SwissTimingAdapterPersistence swissTimingAdapterPersistence; - + private final ServiceTracker swissTimingAdapterTracker; private final ServiceTracker tractracAdapterTracker; @@ -623,10 +623,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private final ServiceTracker igtimiAdapterTracker; private final ServiceTracker raceLogTrackingAdapterTracker; - - private final ServiceTracker - deviceIdentifierStringSerializationHandlerTracker; - + + private final ServiceTracker deviceIdentifierStringSerializationHandlerTracker; + private final com.sap.sailing.domain.tractracadapter.persistence.MongoObjectFactory tractracMongoObjectFactory; private final DomainObjectFactory domainObjectFactory; @@ -638,11 +637,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private final com.sap.sse.common.CountryCodeFactory countryCodeFactory; private final Executor executor; - + private final com.sap.sailing.domain.base.DomainFactory baseDomainFactory; - + private static final int LEADERBOARD_BY_NAME_RESULTS_CACHE_BY_ID_SIZE = 100; - + private static final int LEADERBOARD_DIFFERENCE_CACHE_SIZE = 50; private ResourceBundleStringMessages serverStringMessages; @@ -652,16 +651,16 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private int leaderboardDifferenceCacheByIdPairHits; private int leaderboardDifferenceCacheByIdPairMisses; /** - * Caches some results of the hard to compute difference between two {@link LeaderboardDTO}s. The objects contained as values - * have been obtained by {@link IncrementalLeaderboardDTO#strip(LeaderboardDTO)}. The cache size is limited to - * {@link #LEADERBOARD_DIFFERENCE_CACHE_SIZE}. + * Caches some results of the hard to compute difference between two {@link LeaderboardDTO}s. The objects contained + * as values have been obtained by {@link IncrementalLeaderboardDTO#strip(LeaderboardDTO)}. The cache size is + * limited to {@link #LEADERBOARD_DIFFERENCE_CACHE_SIZE}. */ private final LinkedHashMap, IncrementalLeaderboardDTO> leaderboardDifferenceCacheByIdPair; private final SwissTimingReplayService swissTimingReplayService; private final QuickRanksLiveCache quickRanksLiveCache; - + public SailingServiceImpl() { BundleContext context = Activator.getDefault(); Activator activator = Activator.getInstance(); @@ -670,7 +669,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } quickRanksLiveCache = new QuickRanksLiveCache(this); racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class); - windFinderTrackerFactoryServiceTracker = ServiceTrackerFactory.createAndOpen(context, WindFinderTrackerFactory.class); + windFinderTrackerFactoryServiceTracker = ServiceTrackerFactory.createAndOpen(context, + WindFinderTrackerFactory.class); replicationServiceTracker = ServiceTrackerFactory.createAndOpen(context, ReplicationService.class); resultUrlRegistryServiceTracker = ServiceTrackerFactory.createAndOpen(context, ResultUrlRegistry.class); swissTimingAdapterTracker = ServiceTrackerFactory.createAndOpen(context, SwissTimingAdapterFactory.class); @@ -683,30 +683,36 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S baseDomainFactory = getService().getBaseDomainFactory(); mongoObjectFactory = getService().getMongoObjectFactory(); domainObjectFactory = getService().getDomainObjectFactory(); - // TODO what about passing on the mongo/domain object factory to obtain an according SwissTimingAdapterPersistence instance similar to how the tractracDomainObjectFactory etc. are created below? + // TODO what about passing on the mongo/domain object factory to obtain an according + // SwissTimingAdapterPersistence instance similar to how the tractracDomainObjectFactory etc. are created below? swissTimingAdapterPersistence = SwissTimingAdapterPersistence.INSTANCE; swissTimingReplayService = ServiceTrackerFactory.createAndOpen(context, SwissTimingReplayServiceFactory.class) .getService().createSwissTimingReplayService(getSwissTimingAdapter().getSwissTimingDomainFactory(), - /* raceLogResolver */ getService()); + /* raceLogResolver */ getService()); expeditionConnectorTracker = ServiceTrackerFactory.createAndOpen(context, ExpeditionTrackerFactory.class); scoreCorrectionProviderServiceTracker = ServiceTrackerFactory.createAndOpen(context, ScoreCorrectionProvider.class); competitorProviderServiceTracker = ServiceTrackerFactory.createAndOpen(context, CompetitorProvider.class); tractracDomainObjectFactory = com.sap.sailing.domain.tractracadapter.persistence.PersistenceFactory.INSTANCE - .createDomainObjectFactory(mongoObjectFactory.getDatabase(), getTracTracAdapter() - .getTracTracDomainFactory()); + .createDomainObjectFactory(mongoObjectFactory.getDatabase(), + getTracTracAdapter().getTracTracDomainFactory()); tractracMongoObjectFactory = com.sap.sailing.domain.tractracadapter.persistence.MongoObjectFactory.INSTANCE; swissTimingFactory = SwissTimingFactory.INSTANCE; countryCodeFactory = com.sap.sse.common.CountryCodeFactory.INSTANCE; - leaderboardDifferenceCacheByIdPair = new LinkedHashMap, IncrementalLeaderboardDTO>(LEADERBOARD_DIFFERENCE_CACHE_SIZE, 0.75f, /* accessOrder */ true) { + leaderboardDifferenceCacheByIdPair = new LinkedHashMap, IncrementalLeaderboardDTO>( + LEADERBOARD_DIFFERENCE_CACHE_SIZE, 0.75f, /* accessOrder */ true) { private static final long serialVersionUID = 3775119859130148488L; + @Override - protected boolean removeEldestEntry(Entry, IncrementalLeaderboardDTO> eldest) { + protected boolean removeEldestEntry( + Entry, IncrementalLeaderboardDTO> eldest) { return this.size() > LEADERBOARD_DIFFERENCE_CACHE_SIZE; } }; - leaderboardByNameResultsCacheById = new LinkedHashMap(LEADERBOARD_BY_NAME_RESULTS_CACHE_BY_ID_SIZE, 0.75f, /* accessOrder */ true) { + leaderboardByNameResultsCacheById = new LinkedHashMap( + LEADERBOARD_BY_NAME_RESULTS_CACHE_BY_ID_SIZE, 0.75f, /* accessOrder */ true) { private static final long serialVersionUID = 3775119859130148488L; + @Override protected boolean removeEldestEntry(Entry eldest) { return this.size() > LEADERBOARD_BY_NAME_RESULTS_CACHE_BY_ID_SIZE; @@ -716,14 +722,14 @@ 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()); } - + /** - * Stops this service and frees its resources. In particular, caching services and threads owned by this service will be - * notified to stop their jobs. + * Stops this service and frees its resources. In particular, caching services and threads owned by this service + * will be notified to stop their jobs. */ public void stop() { quickRanksLiveCache.stop(); @@ -736,7 +742,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S protected SwissTimingAdapter getSwissTimingAdapter() { return getSwissTimingAdapterFactory().getOrCreateSwissTimingAdapter(baseDomainFactory); } - + protected TracTracAdapterFactory getTracTracAdapterFactory() { return tractracAdapterTracker.getService(); } @@ -771,7 +777,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } private Iterable getAllScoreCorrectionProviders() { - final ScoreCorrectionProvider[] services = scoreCorrectionProviderServiceTracker.getServices(new ScoreCorrectionProvider[0]); + final ScoreCorrectionProvider[] services = scoreCorrectionProviderServiceTracker + .getServices(new ScoreCorrectionProvider[0]); List result = new ArrayList(); if (services != null) { for (final ScoreCorrectionProvider service : services) { @@ -781,9 +788,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return result; } - private ScoreCorrectionProviderDTO convertScoreCorrectionProviderDTO(ScoreCorrectionProvider scoreCorrectionProvider) - throws Exception { - Map>> hasResultsForBoatClassFromDateByEventName = new HashMap>>(); + private ScoreCorrectionProviderDTO convertScoreCorrectionProviderDTO( + ScoreCorrectionProvider scoreCorrectionProvider) throws Exception { + Map>> hasResultsForBoatClassFromDateByEventName = new HashMap>>(); for (Map.Entry>> e : scoreCorrectionProvider .getHasResultsForBoatClassFromDateByEventName().entrySet()) { Set> set = new HashSet>(); @@ -792,7 +799,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } hasResultsForBoatClassFromDateByEventName.put(e.getKey(), set); } - return new ScoreCorrectionProviderDTO(scoreCorrectionProvider.getName(), hasResultsForBoatClassFromDateByEventName); + return new ScoreCorrectionProviderDTO(scoreCorrectionProvider.getName(), + hasResultsForBoatClassFromDateByEventName); } @Override @@ -838,9 +846,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return Collections.emptyList(); } - + @Override - public Pair serializationDummy(PersonDTO dummy, CountryCode ccDummy, PreciseCompactPosition preciseCompactPosition) { return null; } + public Pair serializationDummy(PersonDTO dummy, CountryCode ccDummy, + PreciseCompactPosition preciseCompactPosition) { + return null; + } /** * If date is null, the {@link LiveLeaderboardUpdater} for the @@ -852,6 +863,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S *

* * Otherwise, the leaderboard is computed synchronously on the fly. + * * @param previousLeaderboardId * if null or no leaderboard with that {@link LeaderboardDTO#getId() ID} is known, a * {@link FullLeaderboardDTO} will be computed; otherwise, an {@link IncrementalLeaderboardDTO} will be @@ -860,8 +872,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public IncrementalOrFullLeaderboardDTO getLeaderboardByName(final String leaderboardName, final Date date, final Collection namesOfRaceColumnsForWhichToLoadLegDetails, boolean addOverallDetails, - String previousLeaderboardId, boolean fillTotalPointsUncorrected) throws NoWindException, InterruptedException, ExecutionException, - IllegalArgumentException { + String previousLeaderboardId, boolean fillTotalPointsUncorrected) + throws NoWindException, InterruptedException, ExecutionException, IllegalArgumentException { try { long startOfRequestHandling = System.currentTimeMillis(); IncrementalOrFullLeaderboardDTO result = null; @@ -874,7 +886,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S timePoint = new MillisecondsTimePoint(date); } LeaderboardDTO leaderboardDTO = leaderboard.getLeaderboardDTO(timePoint, - namesOfRaceColumnsForWhichToLoadLegDetails, addOverallDetails, getService(), baseDomainFactory, fillTotalPointsUncorrected); + namesOfRaceColumnsForWhichToLoadLegDetails, addOverallDetails, getService(), baseDomainFactory, + fillTotalPointsUncorrected); LeaderboardDTO previousLeaderboardDTO = null; synchronized (leaderboardByNameResultsCacheById) { leaderboardByNameResultsCacheById.put(leaderboardDTO.getId(), leaderboardDTO); @@ -882,21 +895,26 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S previousLeaderboardDTO = leaderboardByNameResultsCacheById.get(previousLeaderboardId); } } - // Un-comment the following lines if you need to update the file used by LeaderboardDTODiffingTest, set a breakpoint + // Un-comment the following lines if you need to update the file used by LeaderboardDTODiffingTest, set + // a breakpoint // and toggle the storeLeaderboardForTesting flag if you found a good version. See also bug 1417. // The leaderboard that the test wants to use is that of the 505 Worlds 2013, obtained for - // an expanded Race R9 at time 2013-05-03T19:17:09Z after the last competitor tracked has finished the last leg. The + // an expanded Race R9 at time 2013-05-03T19:17:09Z after the last competitor tracked has finished the + // last leg. The // total distance traveled in meters has to be expanded for the test to work. boolean storeLeaderboardForTesting = false; if (storeLeaderboardForTesting) { - ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("C:/data/SAP/sailing/workspace/java/com.sap.sailing.domain.test/resources/IncrementalLeaderboardDTO.ser"))); + ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File( + "C:/data/SAP/sailing/workspace/java/com.sap.sailing.domain.test/resources/IncrementalLeaderboardDTO.ser"))); oos.writeObject(leaderboardDTO); oos.close(); } final IncrementalLeaderboardDTO cachedDiff; if (previousLeaderboardId != null) { synchronized (leaderboardDifferenceCacheByIdPair) { - cachedDiff = leaderboardDifferenceCacheByIdPair.get(new com.sap.sse.common.Util.Pair(previousLeaderboardId, leaderboardDTO.getId())); + cachedDiff = leaderboardDifferenceCacheByIdPair + .get(new com.sap.sse.common.Util.Pair(previousLeaderboardId, + leaderboardDTO.getId())); } if (cachedDiff == null) { leaderboardDifferenceCacheByIdPairMisses++; @@ -911,15 +929,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } else { final IncrementalLeaderboardDTO incrementalResult; if (cachedDiff == null) { - IncrementalLeaderboardDTO preResult = new IncrementalLeaderboardDTOCloner().clone(leaderboardDTO).strip(previousLeaderboardDTO); + IncrementalLeaderboardDTO preResult = new IncrementalLeaderboardDTOCloner() + .clone(leaderboardDTO).strip(previousLeaderboardDTO); synchronized (leaderboardDifferenceCacheByIdPair) { - leaderboardDifferenceCacheByIdPair.put(new com.sap.sse.common.Util.Pair(previousLeaderboardId, leaderboardDTO.getId()), preResult); + leaderboardDifferenceCacheByIdPair.put(new com.sap.sse.common.Util.Pair( + previousLeaderboardId, leaderboardDTO.getId()), preResult); } incrementalResult = preResult; } else { incrementalResult = cachedDiff; } - incrementalResult.setCurrentServerTime(new Date()); // may update a cached object, but we consider a reference update atomic + incrementalResult.setCurrentServerTime(new Date()); // may update a cached object, but we consider a + // reference update atomic result = incrementalResult; } logger.fine("getLeaderboardByName(" + leaderboardName + ", " + date + ", " @@ -938,7 +959,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } catch (IllegalArgumentException e) { throw e; } catch (Exception e) { - logger.log(Level.SEVERE,"Exception during SailingService.getLeaderboardByName", e); + logger.log(Level.SEVERE, "Exception during SailingService.getLeaderboardByName", e); throw new RuntimeException(e); } } @@ -977,7 +998,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S markDTO.type = mark.getType(); return markDTO; } - + private RegattaDTO convertToRegattaDTO(Regatta regatta) { RegattaDTO regattaDTO = new RegattaDTO(regatta.getName(), regatta.getScoringScheme().getType()); regattaDTO.races = convertToRaceDTOs(regatta); @@ -1002,7 +1023,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } private BoatClassDTO convertToBoatClassDTO(BoatClass boatClass) { - return boatClass==null?null:new BoatClassDTO(boatClass.getName(), boatClass.getDisplayName(), boatClass.getHullLength(), boatClass.getHullBeam()); + return boatClass == null ? null + : new BoatClassDTO(boatClass.getName(), boatClass.getDisplayName(), boatClass.getHullLength(), + boatClass.getHullBeam()); } private List convertToSeriesDTOs(Regatta regatta) { @@ -1020,10 +1043,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S fleets.add(baseDomainFactory.convertToFleetDTO(fleet)); } List raceColumns = convertToRaceColumnDTOs(series.getRaceColumns()); - SeriesDTO result = new SeriesDTO(series.getName(), fleets, raceColumns, series.isMedal(), series.isFleetsCanRunInParallel(), - series.getResultDiscardingRule() == null ? null : series.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces(), - series.isStartsWithZeroScore(), series.isFirstColumnIsNonDiscardableCarryForward(), series.hasSplitFleetContiguousScoring(), - series.getMaximumNumberOfDiscards()); + SeriesDTO result = new SeriesDTO(series.getName(), fleets, raceColumns, series.isMedal(), + series.isFleetsCanRunInParallel(), + series.getResultDiscardingRule() == null ? null + : series.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces(), + series.isStartsWithZeroScore(), series.isFirstColumnIsNonDiscardableCarryForward(), + series.hasSplitFleetContiguousScoring(), series.getMaximumNumberOfDiscards()); return result; } @@ -1032,21 +1057,23 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S raceColumnDTO.setMedalRace(raceColumn.isMedalRace()); raceColumnDTO.setExplicitFactor(raceColumn.getExplicitFactor()); } - + private List convertToRaceColumnDTOs(Iterable raceColumns) { List raceColumnDTOs = new ArrayList(); RaceColumnDTOFactory columnFactory = RaceColumnDTOFactory.INSTANCE; for (RaceColumn raceColumn : raceColumns) { final RaceColumnDTO raceColumnDTO = columnFactory.createRaceColumnDTO(raceColumn.getName(), raceColumn.isMedalRace(), raceColumn.getExplicitFactor(), - raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getRegatta().getName() : null, - raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() : null, + raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getRegatta().getName() + : null, + raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() + : null, raceColumn instanceof MetaLeaderboardColumn); raceColumnDTOs.add(raceColumnDTO); } return raceColumnDTOs; } - + private RaceInfoDTO createRaceInfoDTO(String seriesName, RaceColumn raceColumn, Fleet fleet) { RaceInfoDTO raceInfoDTO = new RaceInfoDTO(); RaceLog raceLog = raceColumn.getRaceLog(fleet); @@ -1077,7 +1104,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (startTime != null) { FlagPoleState activeFlagState = state.getRacingProcedure().getActiveFlags(startTime, now); List activeFlags = activeFlagState.getCurrentState(); - FlagPoleState previousFlagState = activeFlagState.getPreviousState(state.getRacingProcedure(), startTime); + FlagPoleState previousFlagState = activeFlagState.getPreviousState(state.getRacingProcedure(), + startTime); List previousFlags = previousFlagState.getCurrentState(); FlagPole mostInterestingFlagPole = FlagPoleState.getMostInterestingFlagPole(previousFlags, activeFlags); @@ -1086,31 +1114,34 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S raceInfoDTO.lastUpperFlag = mostInterestingFlagPole.getUpperFlag(); raceInfoDTO.lastLowerFlag = mostInterestingFlagPole.getLowerFlag(); raceInfoDTO.lastFlagsAreDisplayed = mostInterestingFlagPole.isDisplayed(); - raceInfoDTO.lastFlagsDisplayedStateChanged = previousFlagState.hasPoleChanged(mostInterestingFlagPole); + raceInfoDTO.lastFlagsDisplayedStateChanged = previousFlagState + .hasPoleChanged(mostInterestingFlagPole); } } - + AbortingFlagFinder abortingFlagFinder = new AbortingFlagFinder(raceLog); - + RaceLogFlagEvent abortingFlagEvent = abortingFlagFinder.analyze(); if (abortingFlagEvent != null) { raceInfoDTO.isRaceAbortedInPassBefore = true; raceInfoDTO.abortingTimeInPassBefore = abortingFlagEvent.getLogicalTimePoint().asDate(); - - if (raceInfoDTO.lastStatus == RaceLogRaceStatus.UNSCHEDULED || raceInfoDTO.lastStatus == RaceLogRaceStatus.PRESCHEDULED) { + + if (raceInfoDTO.lastStatus == RaceLogRaceStatus.UNSCHEDULED + || raceInfoDTO.lastStatus == RaceLogRaceStatus.PRESCHEDULED) { raceInfoDTO.lastUpperFlag = abortingFlagEvent.getUpperFlag(); raceInfoDTO.lastLowerFlag = abortingFlagEvent.getLowerFlag(); raceInfoDTO.lastFlagsAreDisplayed = abortingFlagEvent.isDisplayed(); raceInfoDTO.lastFlagsDisplayedStateChanged = true; } } - + CourseBase lastCourse = state.getCourseDesign(); if (lastCourse != null) { - raceInfoDTO.lastCourseDesign = convertToRaceCourseDTO(lastCourse, new TrackedRaceMarkPositionFinder(trackedRace), now); + raceInfoDTO.lastCourseDesign = convertToRaceCourseDTO(lastCourse, + new TrackedRaceMarkPositionFinder(trackedRace), now); raceInfoDTO.lastCourseName = lastCourse.getName(); } - + if (raceInfoDTO.lastStatus.equals(RaceLogRaceStatus.FINISHED)) { if (state.getProtestTime() != null) { final TimePoint protestEndTime = state.getProtestTime().to(); @@ -1125,7 +1156,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } } - + Wind wind = state.getWindFix(); if (wind != null) { raceInfoDTO.lastWind = createWindDTOFromAlreadyAveraged(wind, now); @@ -1140,7 +1171,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S raceInfoDTO.raceIdentifier = raceColumn.getRaceIdentifier(fleet); return raceInfoDTO; } - + private void fillStartProcedureSpecifics(RaceInfoDTO raceInfoDTO, ReadonlyRaceState state) { RaceInfoExtensionDTO info = null; raceInfoDTO.startProcedure = state.getRacingProcedure().getType(); @@ -1165,25 +1196,26 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (RaceDefinition r : regatta.getAllRaces()) { RegattaAndRaceIdentifier raceIdentifier = new RegattaNameAndRaceName(regatta.getName(), r.getName()); TrackedRace trackedRace = getService().getExistingTrackedRace(raceIdentifier); - TrackedRaceDTO trackedRaceDTO = null; + TrackedRaceDTO trackedRaceDTO = null; if (trackedRace != null) { trackedRaceDTO = getBaseDomainFactory().createTrackedRaceDTO(trackedRace); } - Map competitorAndBoatDTOs = baseDomainFactory.convertToCompetitorAndBoatDTOs(r.getCompetitorsAndTheirBoats()); - RaceWithCompetitorsAndBoatsDTO raceDTO = new RaceWithCompetitorsAndBoatsDTO(raceIdentifier, competitorAndBoatDTOs, - trackedRaceDTO, getService().isRaceBeingTracked(regatta, r)); + Map competitorAndBoatDTOs = baseDomainFactory + .convertToCompetitorAndBoatDTOs(r.getCompetitorsAndTheirBoats()); + RaceWithCompetitorsAndBoatsDTO raceDTO = new RaceWithCompetitorsAndBoatsDTO(raceIdentifier, + competitorAndBoatDTOs, trackedRaceDTO, getService().isRaceBeingTracked(regatta, r)); if (trackedRace != null) { getBaseDomainFactory().updateRaceDTOWithTrackedRaceData(trackedRace, raceDTO); } - raceDTO.boatClass = regatta.getBoatClass() == null ? null : regatta.getBoatClass().getName(); + raceDTO.boatClass = regatta.getBoatClass() == null ? null : regatta.getBoatClass().getName(); result.add(raceDTO); } return result; } /** - * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorDTO} objects. - * The iteration order in the result matches that of the {@code iterable} passed. + * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorDTO} objects. The + * iteration order in the result matches that of the {@code iterable} passed. */ private List convertToCompetitorDTOs(Iterable iterable) { List result = new ArrayList<>(); @@ -1195,23 +1227,26 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** - * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorWithBoatDTO} objects with an empty boat. - * The iteration order in the result matches that of the {@code iterable} passed. + * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorWithBoatDTO} objects with + * an empty boat. The iteration order in the result matches that of the {@code iterable} passed. */ - private List convertToCompetitorAndBoatDTOs(Map competitorsAndTheirBoats) { + private List convertToCompetitorAndBoatDTOs( + Map competitorsAndTheirBoats) { List result = new ArrayList<>(); for (final Entry c : competitorsAndTheirBoats.entrySet()) { - CompetitorAndBoatDTO competitorAndBoatDTO = baseDomainFactory.convertToCompetitorAndBoatDTO(c.getKey(), c.getValue()); + CompetitorAndBoatDTO competitorAndBoatDTO = baseDomainFactory.convertToCompetitorAndBoatDTO(c.getKey(), + c.getValue()); result.add(competitorAndBoatDTO); } return result; } /** - * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorWithBoatDTO} objects with an empty boat. - * The iteration order in the result matches that of the {@code iterable} passed. + * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorWithBoatDTO} objects with + * an empty boat. The iteration order in the result matches that of the {@code iterable} passed. */ - private List convertToCompetitorWithBoatDTOs(Iterable iterable) { + private List convertToCompetitorWithBoatDTOs( + Iterable iterable) { List result = new ArrayList<>(); for (CompetitorWithBoat c : iterable) { CompetitorWithBoatDTO competitorDTO = baseDomainFactory.convertToCompetitorWithBoatDTO(c); @@ -1221,8 +1256,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** - * Converts the {@link Boat} objects passed as {@code iterable} to {@link BoatDTO} objects. - * The iteration order in the result matches that of the {@code iterable} passed. + * Converts the {@link Boat} objects passed as {@code iterable} to {@link BoatDTO} objects. The iteration order in + * the result matches that of the {@code iterable} passed. */ private List convertToBoatDTOs(Iterable iterable) { List result = new ArrayList(); @@ -1234,20 +1269,23 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public com.sap.sse.common.Util.Pair> listTracTracRacesInEvent(String eventJsonURL, boolean listHiddenRaces) throws MalformedURLException, IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException { - com.sap.sse.common.Util.Pair> raceRecords; - raceRecords = getTracTracAdapter().getTracTracRaceRecords(new URL(eventJsonURL), /*loadClientParam*/ false); + public com.sap.sse.common.Util.Pair> listTracTracRacesInEvent( + String eventJsonURL, boolean listHiddenRaces) throws MalformedURLException, IOException, ParseException, + org.json.simple.parser.ParseException, URISyntaxException { + com.sap.sse.common.Util.Pair> raceRecords; + raceRecords = getTracTracAdapter().getTracTracRaceRecords(new URL(eventJsonURL), /* loadClientParam */ false); List result = new ArrayList(); for (RaceRecord raceRecord : raceRecords.getB()) { - if (listHiddenRaces == false && raceRecord.getRaceVisibility().equals(TracTracConnectionConstants.HIDDEN_VISIBILITY)) { + if (listHiddenRaces == false + && raceRecord.getRaceVisibility().equals(TracTracConnectionConstants.HIDDEN_VISIBILITY)) { continue; } - + result.add(new TracTracRaceRecordDTO(raceRecord.getID(), raceRecord.getEventName(), raceRecord.getName(), - raceRecord.getTrackingStartTime().asDate(), - raceRecord.getTrackingEndTime().asDate(), raceRecord.getRaceStartTime() == null ? null : raceRecord.getRaceStartTime().asDate(), - raceRecord.getBoatClassNames(), raceRecord.getRaceStatus(), raceRecord.getRaceVisibility(), raceRecord.getJsonURL().toString(), - hasRememberedRegatta(raceRecord.getID()))); + raceRecord.getTrackingStartTime().asDate(), raceRecord.getTrackingEndTime().asDate(), + raceRecord.getRaceStartTime() == null ? null : raceRecord.getRaceStartTime().asDate(), + raceRecord.getBoatClassNames(), raceRecord.getRaceStatus(), raceRecord.getRaceVisibility(), + raceRecord.getJsonURL().toString(), hasRememberedRegatta(raceRecord.getID()))); } return new com.sap.sse.common.Util.Pair>(raceRecords.getA(), result); } @@ -1257,18 +1295,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void trackWithTracTrac(RegattaIdentifier regattaToAddTo, Iterable rrs, String liveURI, String storedURI, - String courseDesignUpdateURI, boolean trackWind, final boolean correctWindByDeclination, - final Duration offsetToStartTimeOfSimulatedRace, final boolean useInternalMarkPassingAlgorithm, String tracTracUsername, String tracTracPassword) - throws Exception { - logger.info("tracWithTracTrac for regatta " + regattaToAddTo + " for race records " + rrs + " with liveURI " + liveURI - + " and storedURI " + storedURI); + public void trackWithTracTrac(RegattaIdentifier regattaToAddTo, Iterable rrs, String liveURI, + String storedURI, String courseDesignUpdateURI, boolean trackWind, final boolean correctWindByDeclination, + final Duration offsetToStartTimeOfSimulatedRace, final boolean useInternalMarkPassingAlgorithm, + String tracTracUsername, String tracTracPassword) throws Exception { + logger.info("tracWithTracTrac for regatta " + regattaToAddTo + " for race records " + rrs + " with liveURI " + + liveURI + " and storedURI " + storedURI); for (TracTracRaceRecordDTO rr : rrs) { try { // reload JSON and load clientparams.php - RaceRecord record = getTracTracAdapter().getSingleTracTracRaceRecord(new URL(rr.jsonURL), rr.id, /*loadClientParams*/true); - logger.info("Loaded race " + record.getName() + " in " + record.getEventName() + " start:" + record.getRaceStartTime() + - " trackingStart:" + record.getTrackingStartTime() + " trackingEnd:" + record.getTrackingEndTime()); + RaceRecord record = getTracTracAdapter().getSingleTracTracRaceRecord(new URL(rr.jsonURL), rr.id, + /* loadClientParams */true); + logger.info("Loaded race " + record.getName() + " in " + record.getEventName() + " start:" + + record.getRaceStartTime() + " trackingStart:" + record.getTrackingStartTime() + + " trackingEnd:" + record.getTrackingEndTime()); // note that the live URI may be null for races that were put into replay mode final String effectiveLiveURI; if (!record.getRaceStatus().equals(TracTracConnectionConstants.REPLAY_STATUS)) { @@ -1286,9 +1326,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } else { effectiveStoredURI = storedURI; } - getTracTracAdapter().addTracTracRace(getService(), regattaToAddTo, - record.getParamURL(), effectiveLiveURI == null ? null : new URI(effectiveLiveURI), - new URI(effectiveStoredURI), new URI(courseDesignUpdateURI), + getTracTracAdapter().addTracTracRace(getService(), regattaToAddTo, record.getParamURL(), + effectiveLiveURI == null ? null : new URI(effectiveLiveURI), new URI(effectiveStoredURI), + new URI(courseDesignUpdateURI), new MillisecondsTimePoint(record.getTrackingStartTime().asMillis()), new MillisecondsTimePoint(record.getTrackingEndTime().asMillis()), getRaceLogStore(), getRegattaLogStore(), RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, @@ -1296,7 +1336,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S tracTracPassword, record.getRaceStatus(), record.getRaceVisibility(), trackWind, correctWindByDeclination); } catch (Exception e) { - logger.log(Level.SEVERE, "Error trying to load race " + rrs+". Continuing with remaining races...", e); + logger.log(Level.SEVERE, "Error trying to load race " + rrs + ". Continuing with remaining races...", + e); } } } @@ -1307,16 +1348,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S List result = new ArrayList(); for (TracTracConfiguration ttConfig : configs) { result.add(new TracTracConfigurationDTO(ttConfig.getName(), ttConfig.getJSONURL().toString(), - ttConfig.getLiveDataURI().toString(), ttConfig.getStoredDataURI().toString(), ttConfig.getCourseDesignUpdateURI().toString(), - ttConfig.getTracTracUsername().toString(), ttConfig.getTracTracPassword().toString())); + ttConfig.getLiveDataURI().toString(), ttConfig.getStoredDataURI().toString(), + ttConfig.getCourseDesignUpdateURI().toString(), ttConfig.getTracTracUsername().toString(), + ttConfig.getTracTracPassword().toString())); } return result; } @Override - public void storeTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI, String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword) throws Exception { - tractracMongoObjectFactory.storeTracTracConfiguration(getTracTracAdapter().createTracTracConfiguration(name, jsonURL, liveDataURI, storedDataURI, - courseDesignUpdateURI, tracTracUsername, tracTracPassword)); + public void storeTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI, + String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword) throws Exception { + tractracMongoObjectFactory.storeTracTracConfiguration(getTracTracAdapter().createTracTracConfiguration(name, + jsonURL, liveDataURI, storedDataURI, courseDesignUpdateURI, tracTracUsername, tracTracPassword)); } private RaceDefinition getRaceByName(Regatta regatta, String raceName) { @@ -1326,10 +1369,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return null; } } - + @Override public void stopTrackingRaces(Iterable regattaAndRaceIdentifiers) throws Exception { - for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) { + for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) { getService().apply(new StopTrackingRace(regattaAndRaceIdentifier)); } } @@ -1342,7 +1385,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public WindInfoForRaceDTO getRawWindFixes(RegattaAndRaceIdentifier raceIdentifier, Collection windSources) { + public WindInfoForRaceDTO getRawWindFixes(RegattaAndRaceIdentifier raceIdentifier, + Collection windSources) { WindInfoForRaceDTO result = null; TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); if (trackedRace != null) { @@ -1359,7 +1403,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S windSourcesToDeliver.add(new WindSourceImpl(WindSourceType.WEB)); } for (WindSource windSource : windSourcesToDeliver) { - if(windSource.getType() == WindSourceType.WEB) { + if (windSource.getType() == WindSourceType.WEB) { WindTrackInfoDTO windTrackInfoDTO = new WindTrackInfoDTO(); windTrackInfoDTO.windFixes = new ArrayList(); WindTrack windTrack = trackedRace.getOrCreateWindTrack(windSource); @@ -1370,7 +1414,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Iterator windIter = windTrack.getRawFixes().iterator(); while (windIter.hasNext()) { Wind wind = windIter.next(); - if(wind != null) { + if (wind != null) { WindDTO windDTO = createWindDTO(wind, windTrack); windTrackInfoDTO.windFixes.add(windDTO); } @@ -1397,8 +1441,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } if (wind.getTimePoint() != null) { windDTO.measureTimepoint = wind.getTimePoint().asMillis(); - Wind estimatedWind = windTrack - .getAveragedWind(wind.getPosition(), wind.getTimePoint()); + Wind estimatedWind = windTrack.getAveragedWind(wind.getPosition(), wind.getTimePoint()); if (estimatedWind != null) { windDTO.dampenedTrueWindBearingDeg = estimatedWind.getBearing().getDegrees(); windDTO.dampenedTrueWindFromDeg = estimatedWind.getBearing().reverse().getDegrees(); @@ -1433,13 +1476,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** - * Fetches the {@link WindTrack#getAveragedWind(Position, TimePoint) average wind} from all wind tracks or those identified - * by windSourceTypeNames + * Fetches the {@link WindTrack#getAveragedWind(Position, TimePoint) average wind} from all wind tracks or those + * identified by windSourceTypeNames */ @Override - public WindInfoForRaceDTO getAveragedWindInfo(RegattaAndRaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth, - int numberOfFixes, double latDeg, double lngDeg, Collection windSourceTypeNames) - throws NoWindException { + public WindInfoForRaceDTO getAveragedWindInfo(RegattaAndRaceIdentifier raceIdentifier, Date from, + long millisecondsStepWidth, int numberOfFixes, double latDeg, double lngDeg, + Collection windSourceTypeNames) throws NoWindException { Position position = new DegreePosition(latDeg, lngDeg); WindInfoForRaceDTO result = null; TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); @@ -1471,9 +1514,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Double minWindConfidence = 2.0; Double maxWindConfidence = -1.0; for (int i = 0; i < numberOfFixes; i++) { - WindWithConfidence> averagedWindWithConfidence = windTrack.getAveragedWindWithConfidence(position, timePoint); + WindWithConfidence> averagedWindWithConfidence = windTrack + .getAveragedWindWithConfidence(position, timePoint); if (averagedWindWithConfidence != null) { - WindDTO windDTO = createWindDTOFromAlreadyAveraged(averagedWindWithConfidence.getObject(), timePoint); + WindDTO windDTO = createWindDTOFromAlreadyAveraged(averagedWindWithConfidence.getObject(), + timePoint); double confidence = averagedWindWithConfidence.getConfidence(); windDTO.confidence = confidence; windTrackInfoDTO.windFixes.add(windDTO); @@ -1486,8 +1531,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } timePoint = new MillisecondsTimePoint(timePoint.asMillis() + millisecondsStepWidth); } - windTrackInfoDTO.minWindConfidence = minWindConfidence; - windTrackInfoDTO.maxWindConfidence = maxWindConfidence; + windTrackInfoDTO.minWindConfidence = minWindConfidence; + windTrackInfoDTO.maxWindConfidence = maxWindConfidence; } } } @@ -1504,13 +1549,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S * trackedRace.getTimePointOfNewestEvent()}. */ @Override - public WindInfoForRaceDTO getAveragedWindInfo(RegattaAndRaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth, - int numberOfFixes, Collection windSourceTypeNames, boolean onlyUpToNewestEvent, boolean includeCombinedWindForAllLegMiddles) - throws NoWindException { + public WindInfoForRaceDTO getAveragedWindInfo(RegattaAndRaceIdentifier raceIdentifier, Date from, + long millisecondsStepWidth, int numberOfFixes, Collection windSourceTypeNames, + boolean onlyUpToNewestEvent, boolean includeCombinedWindForAllLegMiddles) throws NoWindException { assert from != null; TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); - WindInfoForRaceDTO result = getAveragedWindInfo(new MillisecondsTimePoint(from), millisecondsStepWidth, numberOfFixes, - windSourceTypeNames, trackedRace, /* onlyUpToNewestEvent FIXME why not pass through onlyUpToNewestEvent here??? */ true, includeCombinedWindForAllLegMiddles); + WindInfoForRaceDTO result = getAveragedWindInfo(new MillisecondsTimePoint(from), millisecondsStepWidth, + numberOfFixes, windSourceTypeNames, trackedRace, + /* onlyUpToNewestEvent FIXME why not pass through onlyUpToNewestEvent here??? */ true, + includeCombinedWindForAllLegMiddles); return result; } @@ -1524,8 +1571,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S * trackedRace.getTimePointOfNewestEvent()}. * @param windSourceTypeNames * if {@code null}, all wind sources delivered by {@link TrackedRace#getWindSources()} plus the - * {@link WindSourceType#COMBINED} wind source are delivered. Note that this does not include - * the {@link WindSourceType#LEG_MIDDLE} wind sources. + * {@link WindSourceType#COMBINED} wind source are delivered. Note that this does not include the + * {@link WindSourceType#LEG_MIDDLE} wind sources. * @param includeCombinedWindForAllLegMiddles * if true, the result will return non-null results for calls to * {@link WindInfoForRaceDTO#getCombinedWindOnLegMiddle(int)}. @@ -1552,15 +1599,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S windSourcesToDeliver.add(combinedWindSource); } else { for (final String windSourceTypeToAdd : windSourceTypeNames) { - for (final WindSource windSource : trackedRace.getWindSources(WindSourceType.valueOf(windSourceTypeToAdd))) { + for (final WindSource windSource : trackedRace + .getWindSources(WindSourceType.valueOf(windSourceTypeToAdd))) { windSourcesToDeliver.add(windSource); } } } for (final WindSource windSource : windSourcesToDeliver) { // TODO consider parallelizing - WindTrackInfoDTO windTrackInfoDTO = createWindTrackInfoDTO(from, millisecondsStepWidth, - numberOfFixes, trackedRace, onlyUpToNewestEvent, newestEvent, windSource, /* use default positions */ at->null); + WindTrackInfoDTO windTrackInfoDTO = createWindTrackInfoDTO(from, millisecondsStepWidth, numberOfFixes, + trackedRace, onlyUpToNewestEvent, newestEvent, windSource, + /* use default positions */ at -> null); windTrackInfoDTOs.put(windSource, windTrackInfoDTO); } if (includeCombinedWindForAllLegMiddles) { @@ -1568,7 +1617,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (final TrackedLeg trackedLeg : trackedRace.getTrackedLegs()) { WindTrackInfoDTO windTrackInfoForLegMiddle = createWindTrackInfoDTO(from, millisecondsStepWidth, numberOfFixes, trackedRace, onlyUpToNewestEvent, newestEvent, combinedWindSource, - new PositionAtTimeProvider() { @Override public Position getPosition(TimePoint at) { return trackedLeg.getMiddleOfLeg(at); }}); + new PositionAtTimeProvider() { + @Override + public Position getPosition(TimePoint at) { + return trackedLeg.getMiddleOfLeg(at); + } + }); result.addWindOnLegMiddle(zeroBasedLegNumber, windTrackInfoForLegMiddle); zeroBasedLegNumber++; } @@ -1580,22 +1634,23 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private interface PositionAtTimeProvider { Position getPosition(TimePoint at); } - + private WindTrackInfoDTO createWindTrackInfoDTO(TimePoint from, long millisecondsStepWidth, int numberOfFixes, TrackedRace trackedRace, boolean onlyUpToNewestEvent, TimePoint newestEvent, WindSource windSource, PositionAtTimeProvider positionProvider) { WindTrack windTrack = trackedRace.getOrCreateWindTrack(windSource); WindTrackInfoDTO windTrackInfoDTO = new WindTrackInfoDTO(); - windTrackInfoDTO.resolutionOutsideOfWhichNoFixWillBeReturned = windTrack.getResolutionOutsideOfWhichNoFixWillBeReturned(); + windTrackInfoDTO.resolutionOutsideOfWhichNoFixWillBeReturned = windTrack + .getResolutionOutsideOfWhichNoFixWillBeReturned(); windTrackInfoDTO.windFixes = new ArrayList(); windTrackInfoDTO.dampeningIntervalInMilliseconds = windTrack.getMillisecondsOverWhichToAverageWind(); TimePoint timePoint = from; Double minWindConfidence = 2.0; Double maxWindConfidence = -1.0; - for (int i = 0; i < numberOfFixes && (!onlyUpToNewestEvent || - (newestEvent != null && timePoint.before(newestEvent))); i++) { - WindWithConfidence> averagedWindWithConfidence = - windTrack.getAveragedWindWithConfidence(positionProvider.getPosition(timePoint), timePoint); + for (int i = 0; i < numberOfFixes + && (!onlyUpToNewestEvent || (newestEvent != null && timePoint.before(newestEvent))); i++) { + WindWithConfidence> averagedWindWithConfidence = windTrack + .getAveragedWindWithConfidence(positionProvider.getPosition(timePoint), timePoint); if (averagedWindWithConfidence != null) { if (logger.getLevel() != null && logger.getLevel().equals(Level.FINEST)) { logger.finest("Found averaged wind: " + averagedWindWithConfidence); @@ -1612,12 +1667,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } else { if (logger.getLevel() != null && logger.getLevel().equals(Level.FINEST)) { - logger.finest("Did NOT find any averaged wind for timepoint " + timePoint + " and tracked race " + trackedRace.getRaceIdentifier().getRaceName()); + logger.finest("Did NOT find any averaged wind for timepoint " + timePoint + " and tracked race " + + trackedRace.getRaceIdentifier().getRaceName()); } } timePoint = new MillisecondsTimePoint(timePoint.asMillis() + millisecondsStepWidth); } - windTrackInfoDTO.minWindConfidence = minWindConfidence; + windTrackInfoDTO.minWindConfidence = minWindConfidence; windTrackInfoDTO.maxWindConfidence = maxWindConfidence; return windTrackInfoDTO; } @@ -1640,15 +1696,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); WindInfoForRaceDTO result = null; if (trackedRace != null) { - TimePoint fromTimePoint = from == null ? trackedRace.getStartOfTracking() == null ? trackedRace - .getStartOfRace() : trackedRace.getStartOfTracking() : new MillisecondsTimePoint(from); - TimePoint toTimePoint = to == null ? trackedRace.getEndOfRace() == null ? - MillisecondsTimePoint.now().minus(trackedRace.getDelayToLiveInMillis()) : trackedRace.getEndOfRace() : new MillisecondsTimePoint(to); + TimePoint fromTimePoint = from == null + ? trackedRace.getStartOfTracking() == null ? trackedRace.getStartOfRace() + : trackedRace.getStartOfTracking() + : new MillisecondsTimePoint(from); + TimePoint toTimePoint = to == null ? trackedRace.getEndOfRace() == null + ? MillisecondsTimePoint.now().minus(trackedRace.getDelayToLiveInMillis()) + : trackedRace.getEndOfRace() : new MillisecondsTimePoint(to); if (fromTimePoint != null && toTimePoint != null) { int numberOfFixes = Math.min(SailingServiceConstants.MAX_NUMBER_OF_WIND_FIXES_TO_DELIVER_IN_ONE_CALL, - (int) ((toTimePoint.asMillis() - fromTimePoint.asMillis())/resolutionInMilliseconds)); + (int) ((toTimePoint.asMillis() - fromTimePoint.asMillis()) / resolutionInMilliseconds)); result = getAveragedWindInfo(fromTimePoint, resolutionInMilliseconds, numberOfFixes, - windSourceTypeNames, trackedRace, onlyUpToNewestEvent, /* includeCombinedWindForAllLegMiddles */ false); + windSourceTypeNames, trackedRace, onlyUpToNewestEvent, + /* includeCombinedWindForAllLegMiddles */ false); } } return result; @@ -1679,41 +1739,42 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S // get simulation-results from smart-future-cached simulation-service SimulatorResultsDTO result = null; SimulationService simulationService = getService().getSimulationService(); - if (simulationService == null) + if (simulationService == null) return result; SimulationResults simulationResults = simulationService.getSimulationResults(legIdentifier); - if (simulationResults == null) + if (simulationResults == null) return result; - // prepare simulator-results-dto + // prepare simulator-results-dto Map paths = simulationResults.getPaths(); if (paths != null) { int noOfPaths = paths.size(); - PathDTO[] pathDTOs = new PathDTO[noOfPaths]; - int index = noOfPaths - 1; + PathDTO[] pathDTOs = new PathDTO[noOfPaths]; + int index = noOfPaths - 1; for (Entry entry : paths.entrySet()) { pathDTOs[index] = new PathDTO(entry.getKey()); - // fill pathDTO with path points where speed is true wind speed - List wList = new ArrayList(); - for (TimedPositionWithSpeed p : entry.getValue().getPathPoints()) { - wList.add(createSimulatorWindDTO(p)); - } - pathDTOs[index].setPoints(wList); + // fill pathDTO with path points where speed is true wind speed + List wList = new ArrayList(); + for (TimedPositionWithSpeed p : entry.getValue().getPathPoints()) { + wList.add(createSimulatorWindDTO(p)); + } + pathDTOs[index].setPoints(wList); pathDTOs[index].setAlgorithmTimedOut(entry.getValue().getAlgorithmTimedOut()); pathDTOs[index].setMixedLeg(entry.getValue().getMixedLeg()); - index--; - } - RaceMapDataDTO rcDTO; - rcDTO = new RaceMapDataDTO(); - rcDTO.coursePositions = new CoursePositionsDTO(); + index--; + } + RaceMapDataDTO rcDTO; + rcDTO = new RaceMapDataDTO(); + rcDTO.coursePositions = new CoursePositionsDTO(); rcDTO.coursePositions.waypointPositions = new ArrayList(); rcDTO.coursePositions.waypointPositions.add(simulationResults.getStartPosition()); rcDTO.coursePositions.waypointPositions.add(simulationResults.getEndPosition()); - result = new SimulatorResultsDTO(simulationResults.getVersion().asMillis(), legIdentifier.getLegNumber()+1, simulationResults.getStartTime(), simulationResults.getTimeStep(), + result = new SimulatorResultsDTO(simulationResults.getVersion().asMillis(), + legIdentifier.getLegNumber() + 1, simulationResults.getStartTime(), simulationResults.getTimeStep(), simulationResults.getLegDuration(), rcDTO, pathDTOs, null, null); - } + } return result; } - + private SimulatorWindDTO createSimulatorWindDTO(TimedPositionWithSpeed timedPositionWithSpeed) { Position position = timedPositionWithSpeed.getPosition(); @@ -1722,11 +1783,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S SimulatorWindDTO result = new SimulatorWindDTO(); if (speedWithBearing == null) { - result.trueWindBearingDeg = 0.0; - result.trueWindSpeedInKnots = 0.0; + result.trueWindBearingDeg = 0.0; + result.trueWindSpeedInKnots = 0.0; } else { - result.trueWindBearingDeg = speedWithBearing.getBearing().getDegrees(); - result.trueWindSpeedInKnots = speedWithBearing.getKnots(); + result.trueWindBearingDeg = speedWithBearing.getBearing().getDegrees(); + result.trueWindSpeedInKnots = speedWithBearing.getKnots(); } if (position != null) { @@ -1765,11 +1826,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } if (speed != null) { if (windDTO.trueWindBearingDeg != null) { - speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), new DegreeBearingImpl( - windDTO.trueWindBearingDeg)); + speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), + new DegreeBearingImpl(windDTO.trueWindBearingDeg)); } else if (windDTO.trueWindFromDeg != null) { - speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), new DegreeBearingImpl( - windDTO.trueWindFromDeg).reverse()); + speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), + new DegreeBearingImpl(windDTO.trueWindFromDeg).reverse()); } } Wind wind = new WindImpl(p, at, speedWithBearing); @@ -1788,14 +1849,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Map result = null; TrackedRace trackedRace = getService().getExistingTrackedRace(raceIdentifier); if (trackedRace != null) { - result = baseDomainFactory.convertToCompetitorAndBoatDTOs(trackedRace.getRace().getCompetitorsAndTheirBoats()); + result = baseDomainFactory + .convertToCompetitorAndBoatDTOs(trackedRace.getRace().getCompetitorsAndTheirBoats()); } return result; } @Override - public RaceboardDataDTO getRaceboardData(String regattaName, String raceName, - String leaderboardName, String leaderboardGroupName, UUID eventId) { + public RaceboardDataDTO getRaceboardData(String regattaName, String raceName, String leaderboardName, + String leaderboardGroupName, UUID eventId) { RaceWithCompetitorsAndBoatsDTO raceDTO = null; Regatta regatta = getService().getRegattaByName(regattaName); if (regatta != null) { @@ -1803,27 +1865,31 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (race != null) { RegattaAndRaceIdentifier raceIdentifier = new RegattaNameAndRaceName(regatta.getName(), race.getName()); TrackedRace trackedRace = getService().getExistingTrackedRace(raceIdentifier); - Map competitorsAndBoats = baseDomainFactory.convertToCompetitorAndBoatDTOs(race.getCompetitorsAndTheirBoats()); + Map competitorsAndBoats = baseDomainFactory + .convertToCompetitorAndBoatDTOs(race.getCompetitorsAndTheirBoats()); TrackedRaceDTO trackedRaceDTO = null; if (trackedRace != null) { trackedRaceDTO = getBaseDomainFactory().createTrackedRaceDTO(trackedRace); } - raceDTO = new RaceWithCompetitorsAndBoatsDTO(raceIdentifier, competitorsAndBoats, trackedRaceDTO, getService().isRaceBeingTracked(regatta, race)); + raceDTO = new RaceWithCompetitorsAndBoatsDTO(raceIdentifier, competitorsAndBoats, trackedRaceDTO, + getService().isRaceBeingTracked(regatta, race)); if (trackedRace != null) { getBaseDomainFactory().updateRaceDTOWithTrackedRaceData(trackedRace, raceDTO); } raceDTO.boatClass = regatta.getBoatClass() == null ? null : regatta.getBoatClass().getName(); - } + } } Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - LeaderboardGroup leaderboardGroup = leaderboardGroupName != null ? getService().getLeaderboardGroupByName(leaderboardGroupName) : null; - Event event = eventId != null ? getService().getEvent(eventId) : null; - - boolean isValidLeaderboard = leaderboard != null; + LeaderboardGroup leaderboardGroup = leaderboardGroupName != null + ? getService().getLeaderboardGroupByName(leaderboardGroupName) + : null; + Event event = eventId != null ? getService().getEvent(eventId) : null; + + boolean isValidLeaderboard = leaderboard != null; boolean isValidLeaderboardGroup = false; if (leaderboardGroup != null) { - for(Leaderboard leaderboardInGroup: leaderboardGroup.getLeaderboards()) { - if(leaderboardInGroup.getName().equals(leaderboard.getName())) { + for (Leaderboard leaderboardInGroup : leaderboardGroup.getLeaderboards()) { + if (leaderboardInGroup.getName().equals(leaderboard.getName())) { isValidLeaderboardGroup = true; break; } @@ -1832,14 +1898,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S boolean isValidEvent = event != null; if (event != null && leaderboardGroup != null) { isValidEvent = false; - for (LeaderboardGroup leaderboardGroupInEvent: event.getLeaderboardGroups()) { + for (LeaderboardGroup leaderboardGroupInEvent : event.getLeaderboardGroups()) { if (leaderboardGroupInEvent.getId().equals(leaderboardGroup.getId())) { isValidEvent = true; break; } } } - RaceboardDataDTO result = new RaceboardDataDTO(raceDTO, isValidLeaderboard, isValidLeaderboardGroup, isValidEvent); + RaceboardDataDTO result = new RaceboardDataDTO(raceDTO, isValidLeaderboard, isValidLeaderboardGroup, + isValidEvent); return result; } @@ -1851,10 +1918,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Date timeToGetTheEstimatedDurationFor, boolean estimatedDurationRequired) throws NoWindException { final HashSet raceCompetitorIdsAsStrings; final TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); - // if md5OfIdsAsStringOfCompetitorParticipatingInRaceInAlphanumericOrderOfTheirID is null, Arrays.equals will return false, and the + // if md5OfIdsAsStringOfCompetitorParticipatingInRaceInAlphanumericOrderOfTheirID is null, Arrays.equals will + // return false, and the // competitor set will be calculated and returned to the client - if (trackedRace == null || Arrays.equals(md5OfIdsAsStringOfCompetitorParticipatingInRaceInAlphanumericOrderOfTheirID, trackedRace.getRace().getCompetitorMD5())) { - raceCompetitorIdsAsStrings = null; // tracked race not found or still same MD5 hash, suggesting unchanged competitor set + if (trackedRace == null + || Arrays.equals(md5OfIdsAsStringOfCompetitorParticipatingInRaceInAlphanumericOrderOfTheirID, + trackedRace.getRace().getCompetitorMD5())) { + raceCompetitorIdsAsStrings = null; // tracked race not found or still same MD5 hash, suggesting unchanged + // competitor set } else { raceCompetitorIdsAsStrings = new HashSet<>(); for (final Competitor c : trackedRace.getRace().getCompetitors()) { @@ -1867,8 +1938,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } else { estimatedDuration = null; } - final Map> boatPositions = getBoatPositionsInternal(raceIdentifier, - fromPerCompetitorIdAsString, toPerCompetitorIdAsString, extrapolate); + final Map> boatPositions = getBoatPositionsInternal( + raceIdentifier, fromPerCompetitorIdAsString, toPerCompetitorIdAsString, extrapolate); final CoursePositionsDTO coursePositions = getCoursePositions(raceIdentifier, date); final List courseSidelines = getCourseSidelines(raceIdentifier, date); final QuickRanksDTO quickRanks = getQuickRanks(raceIdentifier, date); @@ -1885,7 +1956,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Duration estimatedDuration = null; if (trackedRace != null) { try { - estimatedDuration = trackedRace.getEstimatedTimeToComplete(new MillisecondsTimePoint(time)).getExpectedDuration(); + estimatedDuration = trackedRace.getEstimatedTimeToComplete(new MillisecondsTimePoint(time)) + .getExpectedDuration(); } catch (NotEnoughDataHasBeenAddedException | NoWindException e) { logger.log(Level.WARNING, "Problem computing the estimated race duration", e); } @@ -1897,7 +1969,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public CompactBoatPositionsDTO getBoatPositions(RegattaAndRaceIdentifier raceIdentifier, Map fromPerCompetitorIdAsString, Map toPerCompetitorIdAsString, boolean extrapolate) throws NoWindException { - return new CompactBoatPositionsDTO(getBoatPositionsInternal(raceIdentifier, fromPerCompetitorIdAsString, toPerCompetitorIdAsString, extrapolate)); + return new CompactBoatPositionsDTO(getBoatPositionsInternal(raceIdentifier, fromPerCompetitorIdAsString, + toPerCompetitorIdAsString, extrapolate)); } /** @@ -1919,10 +1992,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S * @return a map where for each competitor participating in the race the list of GPS fixes in increasing * chronological order is provided. The last one is the last position at or before date. */ - private Map> getBoatPositionsInternal(RegattaAndRaceIdentifier raceIdentifier, - Map fromPerCompetitorIdAsString, Map toPerCompetitorIdAsString, - boolean extrapolate) - throws NoWindException { + private Map> getBoatPositionsInternal( + RegattaAndRaceIdentifier raceIdentifier, Map fromPerCompetitorIdAsString, + Map toPerCompetitorIdAsString, boolean extrapolate) throws NoWindException { Map, LegType> legTypeCache = new HashMap<>(); Map> result = new HashMap<>(); TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); @@ -1933,8 +2005,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S List fixesForCompetitor = new ArrayList(); result.put(competitorDTO, fixesForCompetitor); GPSFixTrack track = trackedRace.getTrack(competitor); - TimePoint fromTimePoint = new MillisecondsTimePoint(fromPerCompetitorIdAsString.get(competitorDTO.getIdAsString())); - TimePoint toTimePointExcluding = new MillisecondsTimePoint(toPerCompetitorIdAsString.get(competitorDTO.getIdAsString())); + TimePoint fromTimePoint = new MillisecondsTimePoint( + fromPerCompetitorIdAsString.get(competitorDTO.getIdAsString())); + TimePoint toTimePointExcluding = new MillisecondsTimePoint( + toPerCompetitorIdAsString.get(competitorDTO.getIdAsString())); // copy the fixes into a list while holding the monitor; then release the monitor to avoid deadlocks // during wind estimations required for tack determination List fixes = new ArrayList(); @@ -1943,9 +2017,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Iterator fixIter = track.getFixesIterator(fromTimePoint, /* inclusive */true); while (fixIter.hasNext()) { GPSFixMoving fix = fixIter.next(); - if (fix.getTimePoint().before(toTimePointExcluding) || - (extrapolate && fix.getTimePoint().equals(toTimePointExcluding))) { - logger.finest(()->""+competitor.getName()+": " + fix); + if (fix.getTimePoint().before(toTimePointExcluding) + || (extrapolate && fix.getTimePoint().equals(toTimePointExcluding))) { + logger.finest(() -> "" + competitor.getName() + ": " + fix); fixes.add(fix); } else { break; @@ -1956,14 +2030,16 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } final Set extrapolatedFixes; if (fixes.isEmpty()) { - // then there was no (smoothened) fix between fromTimePoint and toTimePointExcluding; estimate... - TimePoint middle = new MillisecondsTimePoint((toTimePointExcluding.asMillis()+fromTimePoint.asMillis())/2); + // then there was no (smoothened) fix between fromTimePoint and toTimePointExcluding; + // estimate... + TimePoint middle = new MillisecondsTimePoint( + (toTimePointExcluding.asMillis() + fromTimePoint.asMillis()) / 2); Position estimatedPosition = track.getEstimatedPosition(middle, extrapolate); SpeedWithBearing estimatedSpeed = track.getEstimatedSpeed(middle); if (estimatedPosition != null && estimatedSpeed != null) { GPSFixMoving estimatedFix = new GPSFixMovingImpl(estimatedPosition, middle, estimatedSpeed); if (logger.getLevel() != null && logger.getLevel().equals(Level.FINEST)) { - logger.finest(""+competitor.getName()+": " + estimatedFix+" (estimated)"); + logger.finest("" + competitor.getName() + ": " + estimatedFix + " (estimated)"); } fixes.add(estimatedFix); extrapolatedFixes = Collections.singleton(estimatedFix); @@ -1976,21 +2052,26 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Iterator fixIter = fixes.iterator(); if (fixIter.hasNext()) { GPSFixMoving fix = fixIter.next(); - while (fix != null && (fix.getTimePoint().before(toTimePointExcluding) || - (fix.getTimePoint().equals(toTimePointExcluding) && toTimePointExcluding.equals(fromTimePoint)))) { + while (fix != null && (fix.getTimePoint().before(toTimePointExcluding) + || (fix.getTimePoint().equals(toTimePointExcluding) + && toTimePointExcluding.equals(fromTimePoint)))) { Wind wind = trackedRace.getWind(fix.getPosition(), fix.getTimePoint()); final SpeedWithBearing estimatedSpeed = track.getEstimatedSpeed(fix.getTimePoint()); - Tack tack = wind == null? null : trackedRace.getTack(estimatedSpeed, wind, fix.getTimePoint()); + Tack tack = wind == null ? null + : trackedRace.getTack(estimatedSpeed, wind, fix.getTimePoint()); TrackedLegOfCompetitor trackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor, fix.getTimePoint()); LegType legType; if (trackedLegOfCompetitor != null && trackedLegOfCompetitor.getLeg() != null) { - TimePoint quantifiedTimePoint = quantifyTimePointWithResolution(fix.getTimePoint(), /* resolutionInMilliseconds */60000); - Pair cacheKey = new Pair(trackedLegOfCompetitor.getLeg(), quantifiedTimePoint); + TimePoint quantifiedTimePoint = quantifyTimePointWithResolution(fix.getTimePoint(), + /* resolutionInMilliseconds */60000); + Pair cacheKey = new Pair( + trackedLegOfCompetitor.getLeg(), quantifiedTimePoint); legType = legTypeCache.get(cacheKey); if (legType == null) { try { - legType = trackedRace.getTrackedLeg(trackedLegOfCompetitor.getLeg()).getLegType(fix.getTimePoint()); + legType = trackedRace.getTrackedLeg(trackedLegOfCompetitor.getLeg()) + .getLegType(fix.getTimePoint()); legTypeCache.put(cacheKey, legType); } catch (NoWindException nwe) { // without wind, leave the leg type null, meaning "unknown" @@ -2000,18 +2081,21 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } else { legType = null; } - WindDTO windDTO = wind == null ? null : createWindDTOFromAlreadyAveraged(wind, toTimePointExcluding); - GPSFixDTOWithSpeedWindTackAndLegType fixDTO = createGPSFixDTO(fix, estimatedSpeed, windDTO, tack, legType, /* extrapolate */ extrapolatedFixes.contains(fix)); + WindDTO windDTO = wind == null ? null + : createWindDTOFromAlreadyAveraged(wind, toTimePointExcluding); + GPSFixDTOWithSpeedWindTackAndLegType fixDTO = createGPSFixDTO(fix, estimatedSpeed, windDTO, + tack, legType, /* extrapolate */ extrapolatedFixes.contains(fix)); fixesForCompetitor.add(fixDTO); if (fixIter.hasNext()) { fix = fixIter.next(); } else { - // check if fix was at date and if extrapolation is requested; + // check if fix was at date and if extrapolation is requested; if (!fix.getTimePoint().equals(toTimePointExcluding) && extrapolate) { Position position = track.getEstimatedPosition(toTimePointExcluding, extrapolate); Wind wind2 = trackedRace.getWind(position, toTimePointExcluding); SpeedWithBearing estimatedSpeed2 = track.getEstimatedSpeed(toTimePointExcluding); - Tack tack2 = wind2 == null ? null : trackedRace.getTack(estimatedSpeed2, wind2, toTimePointExcluding); + Tack tack2 = wind2 == null ? null + : trackedRace.getTack(estimatedSpeed2, wind2, toTimePointExcluding); LegType legType2; if (trackedLegOfCompetitor != null && trackedLegOfCompetitor.getLeg() != null) { TimePoint quantifiedTimePoint = quantifyTimePointWithResolution( @@ -2022,7 +2106,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S legType2 = legTypeCache.get(cacheKey); if (legType2 == null) { try { - legType2 = trackedRace.getTrackedLeg(trackedLegOfCompetitor.getLeg()).getLegType(fix.getTimePoint()); + legType2 = trackedRace.getTrackedLeg(trackedLegOfCompetitor.getLeg()) + .getLegType(fix.getTimePoint()); legTypeCache.put(cacheKey, legType2); } catch (NoWindException nwe) { // no wind information; leave leg type null, meaning "unknown" @@ -2032,12 +2117,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } else { legType2 = null; } - WindDTO windDTO2 = wind2 == null ? null : createWindDTOFromAlreadyAveraged(wind2, toTimePointExcluding); + WindDTO windDTO2 = wind2 == null ? null + : createWindDTOFromAlreadyAveraged(wind2, toTimePointExcluding); GPSFixDTOWithSpeedWindTackAndLegType extrapolated = new GPSFixDTOWithSpeedWindTackAndLegType( toPerCompetitorIdAsString.get(competitorDTO.getIdAsString()), - position==null?null:position, - estimatedSpeed2==null?null:createSpeedWithBearingDTO(estimatedSpeed2), windDTO2, - tack2, legType2, /* extrapolated */ true); + position == null ? null : position, + estimatedSpeed2 == null ? null : createSpeedWithBearingDTO(estimatedSpeed2), + windDTO2, tack2, legType2, /* extrapolated */ true); fixesForCompetitor.add(extrapolated); } fix = null; @@ -2055,13 +2141,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } private SpeedWithBearingDTO createSpeedWithBearingDTO(SpeedWithBearing speedWithBearing) { - return new SpeedWithBearingDTO(speedWithBearing.getKnots(), speedWithBearing - .getBearing().getDegrees()); + return new SpeedWithBearingDTO(speedWithBearing.getKnots(), speedWithBearing.getBearing().getDegrees()); } - private GPSFixDTOWithSpeedWindTackAndLegType createGPSFixDTO(GPSFix fix, SpeedWithBearing speedWithBearing, WindDTO windDTO, Tack tack, LegType legType, boolean extrapolated) { - return new GPSFixDTOWithSpeedWindTackAndLegType(fix.getTimePoint().asDate(), fix.getPosition()==null?null:fix.getPosition(), - speedWithBearing==null?null:createSpeedWithBearingDTO(speedWithBearing), windDTO, tack, legType, extrapolated); + private GPSFixDTOWithSpeedWindTackAndLegType createGPSFixDTO(GPSFix fix, SpeedWithBearing speedWithBearing, + WindDTO windDTO, Tack tack, LegType legType, boolean extrapolated) { + return new GPSFixDTOWithSpeedWindTackAndLegType(fix.getTimePoint().asDate(), + fix.getPosition() == null ? null : fix.getPosition(), + speedWithBearing == null ? null : createSpeedWithBearingDTO(speedWithBearing), windDTO, tack, legType, + extrapolated); } @Override @@ -2078,15 +2166,21 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S List tags = new ArrayList(); raceTimesInfo.setTags(tags); - raceTimesInfo.startOfRace = trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asDate(); - raceTimesInfo.startOfTracking = trackedRace.getStartOfTracking() == null ? null : trackedRace.getStartOfTracking().asDate(); - raceTimesInfo.newestTrackingEvent = trackedRace.getTimePointOfNewestEvent() == null ? null : trackedRace.getTimePointOfNewestEvent().asDate(); - raceTimesInfo.endOfTracking = trackedRace.getEndOfTracking() == null ? null : trackedRace.getEndOfTracking().asDate(); + raceTimesInfo.startOfRace = trackedRace.getStartOfRace() == null ? null + : trackedRace.getStartOfRace().asDate(); + raceTimesInfo.startOfTracking = trackedRace.getStartOfTracking() == null ? null + : trackedRace.getStartOfTracking().asDate(); + raceTimesInfo.newestTrackingEvent = trackedRace.getTimePointOfNewestEvent() == null ? null + : trackedRace.getTimePointOfNewestEvent().asDate(); + raceTimesInfo.endOfTracking = trackedRace.getEndOfTracking() == null ? null + : trackedRace.getEndOfTracking().asDate(); raceTimesInfo.endOfRace = trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace().asDate(); - raceTimesInfo.raceFinishedTime = trackedRace.getFinishedTime() == null ? null : trackedRace.getFinishedTime().asDate(); + raceTimesInfo.raceFinishedTime = trackedRace.getFinishedTime() == null ? null + : trackedRace.getFinishedTime().asDate(); raceTimesInfo.delayToLiveInMs = trackedRace.getDelayToLiveInMillis(); - Iterable>> markPassingsTimes = trackedRace.getMarkPassingsTimes(); + Iterable>> markPassingsTimes = trackedRace + .getMarkPassingsTimes(); synchronized (markPassingsTimes) { int numberOfWaypoints = Util.size(markPassingsTimes); int wayPointNumber = 1; @@ -2130,23 +2224,30 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S trackedRace.getRace().getCourse().unlockAfterRead(); } + // check if logged in user is the same user as the creator or logged in user is Administrator + Subject subject = SecurityUtils.getSubject(); + Iterable raceLogs = trackedRace.getAttachedRaceLogs(); for (RaceLog raceLog : raceLogs) { ReadonlyRaceState raceState = ReadonlyRaceStateImpl.getOrCreate(getService(), raceLog); Iterable foundTagEvents = raceState.getTagEvents(); for (RaceLogTagEvent tagEvent : foundTagEvents) { - if ((latestReceivedTagTime == null && tagEvent.getRevokedAt() == null) - || (latestReceivedTagTime != null && tagEvent.getRevokedAt() == null - && tagEvent.getCreatedAt().after(latestReceivedTagTime)) - || (latestReceivedTagTime != null && tagEvent.getRevokedAt() != null - && tagEvent.getRevokedAt().after(latestReceivedTagTime))) { - tags.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(), - tagEvent.getUsername(), tagEvent.isVisibleForPublic(), tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt(), - tagEvent.getRevokedAt())); + if (tagEvent.isVisibleForPublic() || (subject.getPrincipals() != null + && (subject.getPrincipals().getPrimaryPrincipal().equals(tagEvent.getUsername()) + || subject.hasRole("admin")))) { + if ((latestReceivedTagTime == null && tagEvent.getRevokedAt() == null) + || (latestReceivedTagTime != null && tagEvent.getRevokedAt() == null + && tagEvent.getCreatedAt().after(latestReceivedTagTime)) + || (latestReceivedTagTime != null && tagEvent.getRevokedAt() != null + && tagEvent.getRevokedAt().after(latestReceivedTagTime))) { + tags.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(), + tagEvent.getUsername(), tagEvent.isVisibleForPublic(), + tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt(), tagEvent.getRevokedAt())); + } } } } - } + } if (raceTimesInfo != null) { raceTimesInfo.currentServerTime = new Date(); } @@ -2154,10 +2255,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public List getRaceTimesInfos(Collection raceIdentifiers, Map latestReceivedTagTimes) { + public List getRaceTimesInfos(Collection raceIdentifiers, + Map latestReceivedTagTimes) { List raceTimesInfos = new ArrayList(); for (RegattaAndRaceIdentifier raceIdentifier : raceIdentifiers) { - RaceTimesInfoDTO raceTimesInfo = getRaceTimesInfo(raceIdentifier, latestReceivedTagTimes.get(raceIdentifier)); + RaceTimesInfoDTO raceTimesInfo = getRaceTimesInfo(raceIdentifier, + latestReceivedTagTimes.get(raceIdentifier)); if (raceTimesInfo != null) { raceTimesInfos.add(raceTimesInfo); } @@ -2189,7 +2292,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return result; } - + @Override public CoursePositionsDTO getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date) { CoursePositionsDTO result = new CoursePositionsDTO(); @@ -2204,7 +2307,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S result.totalLegsCount = trackedRace.getRace().getCourse().getLegs().size(); result.currentLegNumber = trackedRace.getLastLegStarted(dateAsTimePoint); result.marks = new HashSet(); - result.course = convertToRaceCourseDTO(trackedRace.getRace().getCourse(), new TrackedRaceMarkPositionFinder(trackedRace), dateAsTimePoint); + result.course = convertToRaceCourseDTO(trackedRace.getRace().getCourse(), + new TrackedRaceMarkPositionFinder(trackedRace), dateAsTimePoint); // now make sure we don't duplicate the MarkDTO objects but instead use the ones from the RaceCourseDTO // object and amend them with the Position result.waypointPositions = new ArrayList<>(); @@ -2235,7 +2339,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S result.startLineLengthInMeters = markPositionDTOsAndLineAdvantage.getLength().getMeters(); Bearing angleDifferenceFromPortToStarboardWhenApproachingLineToTrueWind = markPositionDTOsAndLineAdvantage .getAngleDifferenceFromPortToStarboardWhenApproachingLineToTrueWind(); - result.startLineAngleFromPortToStarboardWhenApproachingLineToCombinedWind = angleDifferenceFromPortToStarboardWhenApproachingLineToTrueWind == null ? null + result.startLineAngleFromPortToStarboardWhenApproachingLineToCombinedWind = angleDifferenceFromPortToStarboardWhenApproachingLineToTrueWind == null + ? null : angleDifferenceFromPortToStarboardWhenApproachingLineToTrueWind.getDegrees(); result.startLineAdvantageousSide = markPositionDTOsAndLineAdvantage .getAdvantageousSideWhileApproachingLine(); @@ -2250,7 +2355,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S result.finishLineLengthInMeters = markPositionDTOsAndLineAdvantage.getLength().getMeters(); Bearing angleDifferenceFromPortToStarboardWhenApproachingLineToTrueWind = markPositionDTOsAndLineAdvantage .getAngleDifferenceFromPortToStarboardWhenApproachingLineToTrueWind(); - result.finishLineAngleFromPortToStarboardWhenApproachingLineToCombinedWind = angleDifferenceFromPortToStarboardWhenApproachingLineToTrueWind == null ? null + result.finishLineAngleFromPortToStarboardWhenApproachingLineToCombinedWind = angleDifferenceFromPortToStarboardWhenApproachingLineToTrueWind == null + ? null : angleDifferenceFromPortToStarboardWhenApproachingLineToTrueWind.getDegrees(); result.finishLineAdvantageousSide = markPositionDTOsAndLineAdvantage .getAdvantageousSideWhileApproachingLine(); @@ -2261,7 +2367,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return result; } - + @Override public RaceCourseDTO getRaceCourse(RegattaAndRaceIdentifier raceIdentifier, Date date) { List waypointDTOs = new ArrayList(); @@ -2278,7 +2384,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (Waypoint waypoint : course.getWaypoints()) { ControlPointDTO controlPointDTO = controlPointCache.get(waypoint.getControlPoint().getId()); if (controlPointDTO == null) { - controlPointDTO = convertToControlPointDTO(waypoint.getControlPoint(), new TrackedRaceMarkPositionFinder(trackedRace), dateAsTimePoint); + controlPointDTO = convertToControlPointDTO(waypoint.getControlPoint(), + new TrackedRaceMarkPositionFinder(trackedRace), dateAsTimePoint); controlPointCache.put(waypoint.getControlPoint().getId(), controlPointDTO); } WaypointDTO waypointDTO = new WaypointDTO(waypoint.getName(), controlPointDTO, @@ -2288,41 +2395,44 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return new RaceCourseDTO(waypointDTOs, allMarks); } - - class TrackedRaceMarkPositionFinder implements MarkPositionFinder{ + + class TrackedRaceMarkPositionFinder implements MarkPositionFinder { private TrackedRace trackedRace; public TrackedRaceMarkPositionFinder(TrackedRace trackedRace) { this.trackedRace = trackedRace; } - + @Override public Position find(Mark mark, TimePoint at) { - final TimePoint timePointToUse = trackedRace == null ? null : - at == null ? MillisecondsTimePoint.now().minus(trackedRace.getDelayToLiveInMillis()) : at; + final TimePoint timePointToUse = trackedRace == null ? null + : at == null ? MillisecondsTimePoint.now().minus(trackedRace.getDelayToLiveInMillis()) : at; final Position result; if (timePointToUse == null) { result = null; } else { - result = trackedRace.getOrCreateTrack(mark).getEstimatedPosition(timePointToUse, /* extrapolate */ false); + result = trackedRace.getOrCreateTrack(mark).getEstimatedPosition(timePointToUse, + /* extrapolate */ false); } return result; } } - + private interface MarkPositionFinder { Position find(Mark mark, TimePoint at); } - - private ControlPointDTO convertToControlPointDTO(ControlPoint controlPoint, MarkPositionFinder positionFinder, TimePoint timePoint) { + + private ControlPointDTO convertToControlPointDTO(ControlPoint controlPoint, MarkPositionFinder positionFinder, + TimePoint timePoint) { ControlPointDTO result; - + if (controlPoint instanceof ControlPointWithTwoMarks) { final Mark left = ((ControlPointWithTwoMarks) controlPoint).getLeft(); - final Position leftPos = positionFinder.find(left, timePoint); + final Position leftPos = positionFinder.find(left, timePoint); final Mark right = ((ControlPointWithTwoMarks) controlPoint).getRight(); final Position rightPos = positionFinder.find(right, timePoint); - result = new GateDTO(controlPoint.getId().toString(), controlPoint.getName(), convertToMarkDTO(left, leftPos), convertToMarkDTO(right, rightPos)); + result = new GateDTO(controlPoint.getId().toString(), controlPoint.getName(), + convertToMarkDTO(left, leftPos), convertToMarkDTO(right, rightPos)); } else { Mark mark = controlPoint.getMarks().iterator().next(); final Position position = positionFinder.find(mark, timePoint); @@ -2330,7 +2440,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return result; } - + private ControlPoint getOrCreateControlPoint(ControlPointDTO dto) { String idAsString = dto.getIdAsString(); if (idAsString == null) { @@ -2343,14 +2453,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return baseDomainFactory.getOrCreateControlPointWithTwoMarks(idAsString, gateDTO.getName(), left, right); } else { MarkDTO markDTO = (MarkDTO) dto; - return baseDomainFactory.getOrCreateMark(idAsString, dto.getName(), markDTO.type, markDTO.color, markDTO.shape, markDTO.pattern); + return baseDomainFactory.getOrCreateMark(idAsString, dto.getName(), markDTO.type, markDTO.color, + markDTO.shape, markDTO.pattern); } } /** - * Creates new ControlPoints, if nThe resulting - * list of control points is then passed to {@link Course#update(List, com.sap.sailing.domain.base.DomainFactory)} for - * the course of the race identified by raceIdentifier. + * Creates new ControlPoints, if nThe resulting list of control points is then passed to + * {@link Course#update(List, com.sap.sailing.domain.base.DomainFactory)} for the course of the race identified by + * raceIdentifier. */ @Override public void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, @@ -2388,15 +2499,16 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } final RaceDefinition race = trackedRace.getRace(); int oneBasedRank = 1; - final List competitorsFromBestToWorst = trackedRace.getCompetitorsFromBestToWorst(actualTimePoint); + final List competitorsFromBestToWorst = trackedRace + .getCompetitorsFromBestToWorst(actualTimePoint); for (Competitor competitor : competitorsFromBestToWorst) { TrackedLegOfCompetitor trackedLeg = trackedRace.getTrackedLeg(competitor, actualTimePoint); if (trackedLeg != null) { int legNumberOneBased = race.getCourse().getLegs().indexOf(trackedLeg.getLeg()) + 1; Boat boatOfCompetitor = trackedRace.getBoatOfCompetitor(competitor); - QuickRankDTO quickRankDTO = new QuickRankDTO( - baseDomainFactory.convertToCompetitorAndBoatDTO(competitor, boatOfCompetitor).getCompetitor(), - oneBasedRank, legNumberOneBased); + QuickRankDTO quickRankDTO = new QuickRankDTO(baseDomainFactory + .convertToCompetitorAndBoatDTO(competitor, boatOfCompetitor).getCompetitor(), oneBasedRank, + legNumberOneBased); result.add(quickRankDTO); } oneBasedRank++; @@ -2421,7 +2533,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void setWindSourcesToExclude(RegattaAndRaceIdentifier raceIdentifier, Iterable windSourcesToExclude) { + public void setWindSourcesToExclude(RegattaAndRaceIdentifier raceIdentifier, + Iterable windSourcesToExclude) { getService().apply(new SetWindSourcesToExclude(raceIdentifier, windSourcesToExclude)); } @@ -2440,7 +2553,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Map windTrackInfoDTOs = new HashMap(); result.windTrackInfoByWindSource = windTrackInfoDTOs; - for (WindSource windSource: trackedRace.getWindSources()) { + for (WindSource windSource : trackedRace.getWindSources()) { windTrackInfoDTOs.put(windSource, new WindTrackInfoDTO()); } windTrackInfoDTOs.put(new WindSourceImpl(WindSourceType.COMBINED), new WindTrackInfoDTO()); @@ -2473,11 +2586,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } if (speed != null) { if (windDTO.trueWindBearingDeg != null) { - speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), new DegreeBearingImpl( - windDTO.trueWindBearingDeg)); + speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), + new DegreeBearingImpl(windDTO.trueWindBearingDeg)); } else if (windDTO.trueWindFromDeg != null) { - speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), new DegreeBearingImpl( - windDTO.trueWindFromDeg).reverse()); + speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), + new DegreeBearingImpl(windDTO.trueWindFromDeg).reverse()); } } Wind wind = new WindImpl(p, at, speedWithBearing); @@ -2492,7 +2605,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S protected ReplicationService getReplicationService() { return replicationServiceTracker.getService(); } - + @Override public List getLeaderboardNames() { return new ArrayList(getService().getLeaderboards().keySet()); @@ -2511,27 +2624,36 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public StrippedLeaderboardDTO createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, int[] discardThresholds, ScoringSchemeType scoringSchemeType, - UUID courseAreaId) { - return createStrippedLeaderboardDTO(getService().apply(new CreateFlexibleLeaderboard(leaderboardName, leaderboardDisplayName, discardThresholds, - baseDomainFactory.createScoringScheme(scoringSchemeType), courseAreaId)), false, false); + public StrippedLeaderboardDTO createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, + int[] discardThresholds, ScoringSchemeType scoringSchemeType, UUID courseAreaId) { + return createStrippedLeaderboardDTO( + getService().apply(new CreateFlexibleLeaderboard(leaderboardName, leaderboardDisplayName, + discardThresholds, baseDomainFactory.createScoringScheme(scoringSchemeType), courseAreaId)), + false, false); } - public StrippedLeaderboardDTO createRegattaLeaderboard(RegattaIdentifier regattaIdentifier, String leaderboardDisplayName, int[] discardThresholds) { - return createStrippedLeaderboardDTO(getService().apply(new CreateRegattaLeaderboard(regattaIdentifier, leaderboardDisplayName, discardThresholds)), false, false); + public StrippedLeaderboardDTO createRegattaLeaderboard(RegattaIdentifier regattaIdentifier, + String leaderboardDisplayName, int[] discardThresholds) { + return createStrippedLeaderboardDTO( + getService().apply( + new CreateRegattaLeaderboard(regattaIdentifier, leaderboardDisplayName, discardThresholds)), + false, false); } @Override public StrippedLeaderboardDTO createRegattaLeaderboardWithEliminations(String name, String displayName, String fullRegattaLeaderboardName) { - return createStrippedLeaderboardDTO(getService().apply(new CreateRegattaLeaderboardWithEliminations(name, displayName, fullRegattaLeaderboardName)), false, false); + return createStrippedLeaderboardDTO( + getService().apply( + new CreateRegattaLeaderboardWithEliminations(name, displayName, fullRegattaLeaderboardName)), + false, false); } @Override public List getLeaderboards() { Map leaderboards = getService().getLeaderboards(); List results = new ArrayList(); - for(Leaderboard leaderboard: leaderboards.values()) { + for (Leaderboard leaderboard : leaderboards.values()) { StrippedLeaderboardDTO dao = createStrippedLeaderboardDTO(leaderboard, false, false); results.add(dao); } @@ -2550,11 +2672,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public List getLeaderboardsByRaceAndRegatta(String raceName, RegattaIdentifier regattaIdentifier) { + public List getLeaderboardsByRaceAndRegatta(String raceName, + RegattaIdentifier regattaIdentifier) { List results = new ArrayList(); Map leaderboards = getService().getLeaderboards(); for (Leaderboard leaderboard : leaderboards.values()) { - if (leaderboard instanceof RegattaLeaderboard && ((RegattaLeaderboard) leaderboard).getRegatta().getRegattaIdentifier().equals(regattaIdentifier)) { + if (leaderboard instanceof RegattaLeaderboard && ((RegattaLeaderboard) leaderboard).getRegatta() + .getRegattaIdentifier().equals(regattaIdentifier)) { Iterable races = leaderboard.getRaceColumns(); for (RaceColumn raceInLeaderboard : races) { for (Fleet fleet : raceInLeaderboard.getFleets()) { @@ -2574,27 +2698,30 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** - * Creates a {@link LeaderboardDTO} for leaderboard and fills in the name, race master data - * in the form of {@link RaceColumnDTO}s, whether or not there are {@link LeaderboardDTO#hasCarriedPoints carried points} - * and the {@link LeaderboardDTO#discardThresholds discarding thresholds} for the leaderboard. No data about the points + * Creates a {@link LeaderboardDTO} for leaderboard and fills in the name, race master data in the form + * of {@link RaceColumnDTO}s, whether or not there are {@link LeaderboardDTO#hasCarriedPoints carried points} and + * the {@link LeaderboardDTO#discardThresholds discarding thresholds} for the leaderboard. No data about the points * is filled into the result object. No data about the competitor display names is filled in; instead, an empty map * is used for {@link LeaderboardDTO#competitorDisplayNames}.
- * If withGeoLocationData is true the geographical location of all races will be determined. + * If withGeoLocationData is true the geographical location of all races will be + * determined. */ - private StrippedLeaderboardDTO createStrippedLeaderboardDTO(Leaderboard leaderboard, boolean withGeoLocationData, boolean withStatisticalData) { - StrippedLeaderboardDTO leaderboardDTO = new StrippedLeaderboardDTO(convertToBoatClassDTO(leaderboard.getBoatClass())); + private StrippedLeaderboardDTO createStrippedLeaderboardDTO(Leaderboard leaderboard, boolean withGeoLocationData, + boolean withStatisticalData) { + StrippedLeaderboardDTO leaderboardDTO = new StrippedLeaderboardDTO( + convertToBoatClassDTO(leaderboard.getBoatClass())); TimePoint startOfLatestRace = null; Long delayToLiveInMillisForLatestRace = null; leaderboardDTO.name = leaderboard.getName(); leaderboardDTO.displayName = leaderboard.getDisplayName(); leaderboardDTO.competitorDisplayNames = new HashMap<>(); leaderboardDTO.competitorsCount = Util.size(leaderboard.getCompetitors()); - leaderboardDTO.boatClassName = leaderboard.getBoatClass()==null?null:leaderboard.getBoatClass().getName(); + leaderboardDTO.boatClassName = leaderboard.getBoatClass() == null ? null : leaderboard.getBoatClass().getName(); leaderboardDTO.type = leaderboard.getLeaderboardType(); if (leaderboard instanceof RegattaLeaderboard) { RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; Regatta regatta = regattaLeaderboard.getRegatta(); - leaderboardDTO.regattaName = regatta.getName(); + leaderboardDTO.regattaName = regatta.getName(); leaderboardDTO.scoringScheme = regatta.getScoringScheme().getType(); leaderboardDTO.canBoatsOfCompetitorsChangePerRace = regatta.canBoatsOfCompetitorsChangePerRace(); } else { @@ -2608,7 +2735,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S leaderboardDTO.setDelayToLiveInMillisForLatestRace(delayToLiveInMillisForLatestRace); leaderboardDTO.hasCarriedPoints = leaderboard.hasCarriedPoints(); if (leaderboard.getResultDiscardingRule() instanceof ThresholdBasedResultDiscardingRule) { - leaderboardDTO.discardThresholds = ((ThresholdBasedResultDiscardingRule) leaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces(); + leaderboardDTO.discardThresholds = ((ThresholdBasedResultDiscardingRule) leaderboard + .getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces(); } else { leaderboardDTO.discardThresholds = null; } @@ -2618,27 +2746,39 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S RegattaAndRaceIdentifier raceIdentifier = null; TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); if (trackedRace != null) { - if (startOfLatestRace == null || (trackedRace.getStartOfRace() != null && trackedRace.getStartOfRace().compareTo(startOfLatestRace) > 0)) { + if (startOfLatestRace == null || (trackedRace.getStartOfRace() != null + && trackedRace.getStartOfRace().compareTo(startOfLatestRace) > 0)) { delayToLiveInMillisForLatestRace = trackedRace.getDelayToLiveInMillis(); } - raceIdentifier = new RegattaNameAndRaceName(trackedRace.getTrackedRegatta().getRegatta().getName(), trackedRace.getRace().getName()); - raceDTO = baseDomainFactory.createRaceDTO(getService(), withGeoLocationData, raceIdentifier, trackedRace); - if(withStatisticalData) { + raceIdentifier = new RegattaNameAndRaceName(trackedRace.getTrackedRegatta().getRegatta().getName(), + trackedRace.getRace().getName()); + raceDTO = baseDomainFactory.createRaceDTO(getService(), withGeoLocationData, raceIdentifier, + trackedRace); + if (withStatisticalData) { Iterable mediaTracksForRace = getService().getMediaTracksForRace(raceIdentifier); - raceDTO.trackedRaceStatistics = baseDomainFactory.createTrackedRaceStatisticsDTO(trackedRace, leaderboard, raceColumn, fleet, mediaTracksForRace); + raceDTO.trackedRaceStatistics = baseDomainFactory.createTrackedRaceStatisticsDTO(trackedRace, + leaderboard, raceColumn, fleet, mediaTracksForRace); } - } + } final FleetDTO fleetDTO = baseDomainFactory.convertToFleetDTO(fleet); RaceColumnDTO raceColumnDTO = leaderboardDTO.addRace(raceColumn.getName(), raceColumn.getExplicitFactor(), leaderboard.getScoringScheme().getScoreFactor(raceColumn), - raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getRegatta().getName() : null, - raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() : null, - fleetDTO, raceColumn.isMedalRace(), raceIdentifier, raceDTO, raceColumn instanceof MetaLeaderboardColumn); + raceColumn instanceof RaceColumnInSeries + ? ((RaceColumnInSeries) raceColumn).getRegatta().getName() + : null, + raceColumn instanceof RaceColumnInSeries + ? ((RaceColumnInSeries) raceColumn).getSeries().getName() + : null, + fleetDTO, raceColumn.isMedalRace(), raceIdentifier, raceDTO, + raceColumn instanceof MetaLeaderboardColumn); final RaceLog raceLog = raceColumn.getRaceLog(fleet); - final RaceLogTrackingState raceLogTrackingState = raceLog == null ? RaceLogTrackingState.NOT_A_RACELOG_TRACKED_RACE : - new RaceLogTrackingStateAnalyzer(raceLog).analyze(); - final boolean raceLogTrackerExists = raceLog == null ? false : getService().getRaceTrackerById(raceLog.getId()) != null; - final boolean competitorRegistrationsExist = raceLog == null ? false : !Util.isEmpty(raceColumn.getAllCompetitorsAndTheirBoats(fleet).keySet()); + final RaceLogTrackingState raceLogTrackingState = raceLog == null + ? RaceLogTrackingState.NOT_A_RACELOG_TRACKED_RACE + : new RaceLogTrackingStateAnalyzer(raceLog).analyze(); + final boolean raceLogTrackerExists = raceLog == null ? false + : getService().getRaceTrackerById(raceLog.getId()) != null; + final boolean competitorRegistrationsExist = raceLog == null ? false + : !Util.isEmpty(raceColumn.getAllCompetitorsAndTheirBoats(fleet).keySet()); final boolean courseExist = raceLog == null ? false : !Util.isEmpty(raceColumn.getCourseMarks(fleet)); final RaceLogTrackingInfoDTO raceLogTrackingInfo = new RaceLogTrackingInfoDTO(raceLogTrackerExists, competitorRegistrationsExist, courseExist, raceLogTrackingState); @@ -2649,15 +2789,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public StrippedLeaderboardDTO updateLeaderboard(String leaderboardName, String newLeaderboardName, String newLeaderboardDisplayName, int[] newDiscardingThresholds, UUID newCourseAreaId) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); - Leaderboard updatedLeaderboard = getService().apply(new UpdateLeaderboard(leaderboardName, newLeaderboardName, newLeaderboardDisplayName, newDiscardingThresholds, newCourseAreaId)); + public StrippedLeaderboardDTO updateLeaderboard(String leaderboardName, String newLeaderboardName, + String newLeaderboardDisplayName, int[] newDiscardingThresholds, UUID newCourseAreaId) { + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + Leaderboard updatedLeaderboard = getService().apply(new UpdateLeaderboard(leaderboardName, newLeaderboardName, + newLeaderboardDisplayName, newDiscardingThresholds, newCourseAreaId)); return createStrippedLeaderboardDTO(updatedLeaderboard, false, false); } - + @Override public void removeLeaderboards(Collection leaderboardNames) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.DELETE, leaderboardNames.toArray(new String[0]))); + SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.DELETE, + leaderboardNames.toArray(new String[0]))); for (String leaderoardName : leaderboardNames) { removeLeaderboard(leaderoardName); } @@ -2665,33 +2809,39 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public void removeLeaderboard(String leaderboardName) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.DELETE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.DELETE, leaderboardName)); getService().apply(new RemoveLeaderboard(leaderboardName)); } @Override public void renameLeaderboard(String leaderboardName, String newLeaderboardName) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); getService().apply(new RenameLeaderboard(leaderboardName, newLeaderboardName)); } @Override public void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); getService().apply(new AddColumnToLeaderboard(columnName, leaderboardName, medalRace)); } @Override - public void addColumnsToLeaderboard(String leaderboardName, List> columnsToAdd) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); - for(com.sap.sse.common.Util.Pair columnToAdd: columnsToAdd) { + public void addColumnsToLeaderboard(String leaderboardName, + List> columnsToAdd) { + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + for (com.sap.sse.common.Util.Pair columnToAdd : columnsToAdd) { getService().apply(new AddColumnToLeaderboard(columnToAdd.getA(), leaderboardName, columnToAdd.getB())); } } @Override public void removeLeaderboardColumns(String leaderboardName, List columnsToRemove) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); for (String columnToRemove : columnsToRemove) { getService().apply(new RemoveLeaderboardColumn(columnToRemove, leaderboardName)); } @@ -2699,46 +2849,56 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public void removeLeaderboardColumn(String leaderboardName, String columnName) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); getService().apply(new RemoveLeaderboardColumn(columnName, leaderboardName)); } @Override public void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); getService().apply(new RenameLeaderboardColumn(leaderboardName, oldColumnName, newColumnName)); } @Override public void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double newFactor) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); getService().apply(new UpdateLeaderboardColumnFactor(leaderboardName, columnName, newFactor)); } @Override - public void suppressCompetitorInLeaderboard(String leaderboardName, String competitorIdAsString, boolean suppressed) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); - getService().apply(new SetSuppressedFlagForCompetitorInLeaderboard(leaderboardName, competitorIdAsString, suppressed)); + public void suppressCompetitorInLeaderboard(String leaderboardName, String competitorIdAsString, + boolean suppressed) { + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + getService().apply( + new SetSuppressedFlagForCompetitorInLeaderboard(leaderboardName, competitorIdAsString, suppressed)); } @Override public boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName, String fleetName, RegattaAndRaceIdentifier raceIdentifier) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); Object principal = SessionUtils.getPrincipal(); if (principal != null) { logger.info(String.format("%s linked race column %s %s (%s) with tracked race %s.", principal.toString(), leaderboardName, raceColumnName, fleetName, raceIdentifier.getRaceName())); } else { - logger.info(String.format("Linked race column %s %s (%s) with tracked race %s.", leaderboardName, raceColumnName, fleetName, - raceIdentifier.getRaceName())); + logger.info(String.format("Linked race column %s %s (%s) with tracked race %s.", leaderboardName, + raceColumnName, fleetName, raceIdentifier.getRaceName())); } - return getService().apply(new ConnectTrackedRaceToLeaderboardColumn(leaderboardName, raceColumnName, fleetName, raceIdentifier)); + return getService().apply( + new ConnectTrackedRaceToLeaderboardColumn(leaderboardName, raceColumnName, fleetName, raceIdentifier)); } @Override - public Map getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName, String raceColumnName) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.READ, leaderboardName)); + public Map getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn( + String leaderboardName, String raceColumnName) { + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.READ, leaderboardName)); Map result = new HashMap(); Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard != null) { @@ -2758,83 +2918,102 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + public void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, + String fleetName) { + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); getService().apply(new DisconnectLeaderboardColumnFromTrackedRace(leaderboardName, raceColumnName, fleetName)); } @Override public void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); getService().apply(new UpdateLeaderboardCarryValue(leaderboardName, competitorIdAsString, carriedPoints)); } @Override - public com.sap.sse.common.Util.Triple updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString, String raceColumnName, - MaxPointsReason maxPointsReason, Date date) throws NoWindException { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); - return getService().apply( - new UpdateLeaderboardMaxPointsReason(leaderboardName, raceColumnName, competitorIdAsString, - maxPointsReason, new MillisecondsTimePoint(date))); + public com.sap.sse.common.Util.Triple updateLeaderboardMaxPointsReason( + String leaderboardName, String competitorIdAsString, String raceColumnName, MaxPointsReason maxPointsReason, + Date date) throws NoWindException { + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + return getService().apply(new UpdateLeaderboardMaxPointsReason(leaderboardName, raceColumnName, + competitorIdAsString, maxPointsReason, new MillisecondsTimePoint(date))); } @Override - public com.sap.sse.common.Util.Triple updateLeaderboardScoreCorrection(String leaderboardName, - String competitorIdAsString, String columnName, Double correctedScore, Date date) throws NoWindException { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); - return getService().apply( - new UpdateLeaderboardScoreCorrection(leaderboardName, columnName, competitorIdAsString, correctedScore, - new MillisecondsTimePoint(date))); + public com.sap.sse.common.Util.Triple updateLeaderboardScoreCorrection( + String leaderboardName, String competitorIdAsString, String columnName, Double correctedScore, Date date) + throws NoWindException { + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + return getService().apply(new UpdateLeaderboardScoreCorrection(leaderboardName, columnName, + competitorIdAsString, correctedScore, new MillisecondsTimePoint(date))); } @Override - public void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, String comment) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); - getService().apply( - new UpdateLeaderboardScoreCorrectionMetadata(leaderboardName, - timePointOfLastCorrectionValidity == null ? null : new MillisecondsTimePoint(timePointOfLastCorrectionValidity), - comment)); + public void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, + String comment) { + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + getService().apply(new UpdateLeaderboardScoreCorrectionMetadata(leaderboardName, + timePointOfLastCorrectionValidity == null ? null + : new MillisecondsTimePoint(timePointOfLastCorrectionValidity), + comment)); } @Override - public void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates) throws NoWindException { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, updates.getLeaderboardName())); + public void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates) + throws NoWindException { + SecurityUtils.getSubject().checkPermission( + Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, updates.getLeaderboardName())); Date dateForResults = new Date(); // we don't care about the result date/time here; use current date as default - for (Map.Entry> e : updates.getScoreUpdatesForRaceColumnByCompetitorIdAsString().entrySet()) { + for (Map.Entry> e : updates.getScoreUpdatesForRaceColumnByCompetitorIdAsString() + .entrySet()) { for (Map.Entry raceColumnNameAndCorrectedScore : e.getValue().entrySet()) { updateLeaderboardScoreCorrection(updates.getLeaderboardName(), e.getKey(), - raceColumnNameAndCorrectedScore.getKey(), raceColumnNameAndCorrectedScore.getValue(), dateForResults); + raceColumnNameAndCorrectedScore.getKey(), raceColumnNameAndCorrectedScore.getValue(), + dateForResults); } } - for (Map.Entry> e : updates.getMaxPointsUpdatesForRaceColumnByCompetitorIdAsString().entrySet()) { + for (Map.Entry> e : updates + .getMaxPointsUpdatesForRaceColumnByCompetitorIdAsString().entrySet()) { for (Map.Entry raceColumnNameAndNewMaxPointsReason : e.getValue().entrySet()) { updateLeaderboardMaxPointsReason(updates.getLeaderboardName(), e.getKey(), - raceColumnNameAndNewMaxPointsReason.getKey(), raceColumnNameAndNewMaxPointsReason.getValue(), dateForResults); + raceColumnNameAndNewMaxPointsReason.getKey(), raceColumnNameAndNewMaxPointsReason.getValue(), + dateForResults); } } } @Override - public void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorIdAsString, String displayName) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); - getService().apply(new UpdateCompetitorDisplayNameInLeaderboard(leaderboardName, competitorIdAsString, displayName)); + public void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorIdAsString, + String displayName) { + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + getService().apply( + new UpdateCompetitorDisplayNameInLeaderboard(leaderboardName, competitorIdAsString, displayName)); } @Override public void moveLeaderboardColumnUp(String leaderboardName, String columnName) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); getService().apply(new MoveLeaderboardColumnUp(leaderboardName, columnName)); } @Override public void moveLeaderboardColumnDown(String leaderboardName, String columnName) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); getService().apply(new MoveLeaderboardColumnDown(leaderboardName, columnName)); } @Override public void updateIsMedalRace(String leaderboardName, String columnName, boolean isMedalRace) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); getService().apply(new UpdateIsMedalRace(leaderboardName, columnName, isMedalRace)); } @@ -2863,11 +3042,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public SwissTimingEventRecordDTO getRacesOfSwissTimingEvent(String eventJsonURL) + public SwissTimingEventRecordDTO getRacesOfSwissTimingEvent(String eventJsonURL) throws UnknownHostException, IOException, InterruptedException, ParseException { - SwissTimingEventRecordDTO result = null; + SwissTimingEventRecordDTO result = null; List swissTimingRaces = new ArrayList(); - + // TODO: delete getSwissTimingAdapter().getSwissTimingRaceRecords() method // TODO: delete SwissTimingDomainFactory.getRaceTypeFromRaceID(String raceID) URL url = new URL(eventJsonURL); @@ -2877,73 +3056,80 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (eventResult != null) { for (RegattaResultDescriptor regattaResult : eventResult.getRegattaResults()) { for (RaceResultDescriptor race : regattaResult.getRaceResults()) { - // add only the tracked races + // add only the tracked races if (race.isTracked() != null && race.isTracked() == true) { - SwissTimingRaceRecordDTO swissTimingRaceRecordDTO = new SwissTimingRaceRecordDTO(race.getId(), race.getName(), - regattaResult.getName(), race.getSeriesName(), race.getFleetName(), race.getStatus(), race.getStartTime(), - regattaResult.getXrrEntriesUrl() != null ? regattaResult.getXrrEntriesUrl().toExternalForm() : null, hasRememberedRegatta(race.getId())); - swissTimingRaceRecordDTO.boatClass = regattaResult.getIsafId() != null && !regattaResult.getIsafId().isEmpty() ? regattaResult.getIsafId() : regattaResult.getClassName(); + SwissTimingRaceRecordDTO swissTimingRaceRecordDTO = new SwissTimingRaceRecordDTO(race.getId(), + race.getName(), regattaResult.getName(), race.getSeriesName(), race.getFleetName(), + race.getStatus(), race.getStartTime(), + regattaResult.getXrrEntriesUrl() != null + ? regattaResult.getXrrEntriesUrl().toExternalForm() + : null, + hasRememberedRegatta(race.getId())); + swissTimingRaceRecordDTO.boatClass = regattaResult.getIsafId() != null + && !regattaResult.getIsafId().isEmpty() ? regattaResult.getIsafId() + : regattaResult.getClassName(); swissTimingRaceRecordDTO.gender = regattaResult.getCompetitorGenderType().name(); swissTimingRaces.add(swissTimingRaceRecordDTO); } } } - result = new SwissTimingEventRecordDTO(eventResult.getId(), eventResult.getName(), eventResult.getTrackingDataHost(), - eventResult.getTrackingDataPort(), swissTimingRaces); + result = new SwissTimingEventRecordDTO(eventResult.getId(), eventResult.getName(), + eventResult.getTrackingDataHost(), eventResult.getTrackingDataPort(), swissTimingRaces); } return result; } @Override - public void storeSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port, String updateURL, String updateUsername, String updatePassword) { + public void storeSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port, + String updateURL, String updateUsername, String updatePassword) { if (!jsonURL.equalsIgnoreCase("test")) { - swissTimingAdapterPersistence.storeSwissTimingConfiguration(swissTimingFactory.createSwissTimingConfiguration(configName, jsonURL, hostname, port, updateURL, updateUsername, updatePassword)); + swissTimingAdapterPersistence + .storeSwissTimingConfiguration(swissTimingFactory.createSwissTimingConfiguration(configName, + jsonURL, hostname, port, updateURL, updateUsername, updatePassword)); } } - + private RaceLogStore getRaceLogStore() { - return MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(mongoObjectFactory, - domainObjectFactory); + return MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(mongoObjectFactory, domainObjectFactory); } - + private RegattaLogStore getRegattaLogStore() { - return MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStore( - mongoObjectFactory, domainObjectFactory); + return MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStore(mongoObjectFactory, domainObjectFactory); } @Override - public void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, Iterable rrs, String hostname, int port, - boolean trackWind, final boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm, - String updateURL, String updateUsername, String updatePassword) throws InterruptedException, ParseException, Exception { - logger.info("tracWithSwissTiming for regatta " + regattaToAddTo + " for race records " + rrs - + " with hostname " + hostname + " and port " + port); + public void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, Iterable rrs, + String hostname, int port, boolean trackWind, final boolean correctWindByDeclination, + boolean useInternalMarkPassingAlgorithm, String updateURL, String updateUsername, String updatePassword) + throws InterruptedException, ParseException, Exception { + logger.info("tracWithSwissTiming for regatta " + regattaToAddTo + " for race records " + rrs + " with hostname " + + hostname + " and port " + port); Map cachedRegattaEntriesLists = new HashMap(); for (SwissTimingRaceRecordDTO rr : rrs) { BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(rr.boatClass); - String raceDescription = rr.regattaName != null ? rr.regattaName : ""; + String raceDescription = rr.regattaName != null ? rr.regattaName : ""; raceDescription += rr.seriesName != null ? "/" + rr.seriesName : ""; - raceDescription += raceDescription.length() > 0 ? "/" + rr.getName() : rr.getName(); + raceDescription += raceDescription.length() > 0 ? "/" + rr.getName() : rr.getName(); // try to find a cached entry list for the regatta RegattaResults regattaResults = cachedRegattaEntriesLists.get(rr.xrrEntriesUrl); if (regattaResults == null && rr.xrrEntriesUrl != null) { - regattaResults = getSwissTimingAdapter().readRegattaEntryListFromXrrUrl(rr.xrrEntriesUrl); + regattaResults = getSwissTimingAdapter().readRegattaEntryListFromXrrUrl(rr.xrrEntriesUrl); if (regattaResults != null) { cachedRegattaEntriesLists.put(rr.xrrEntriesUrl, regattaResults); } } StartList startList = null; if (regattaResults != null) { - startList = getSwissTimingAdapter().readStartListForRace(rr.raceId, regattaResults); + startList = getSwissTimingAdapter().readStartListForRace(rr.raceId, regattaResults); } // now read the entry list for the race from the result - getSwissTimingAdapter().addSwissTimingRace(getService(), regattaToAddTo, - rr.raceId, rr.getName(), raceDescription, boatClass, hostname, port, startList, - getRaceLogStore(), getRegattaLogStore(), - RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, useInternalMarkPassingAlgorithm, trackWind, - correctWindByDeclination, updateURL, updateUsername, updatePassword); + getSwissTimingAdapter().addSwissTimingRace(getService(), regattaToAddTo, rr.raceId, rr.getName(), + raceDescription, boatClass, hostname, port, startList, getRaceLogStore(), getRegattaLogStore(), + RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, useInternalMarkPassingAlgorithm, + trackWind, correctWindByDeclination, updateURL, updateUsername, updatePassword); } } - + protected SwissTimingReplayService getSwissTimingReplayService() { return swissTimingReplayService; } @@ -2951,7 +3137,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public List listSwissTiminigReplayRaces(String swissTimingUrl) { List replayRaces = getSwissTimingReplayService().listReplayRaces(swissTimingUrl); - List result = new ArrayList(replayRaces.size()); + List result = new ArrayList(replayRaces.size()); for (SwissTimingReplayRace replayRace : replayRaces) { result.add(new SwissTimingReplayRaceDTO(replayRace.getFlightNumber(), replayRace.getRaceId(), replayRace.getRsc(), replayRace.getName(), replayRace.getBoatClass(), replayRace.getStartTime(), @@ -2961,9 +3147,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void replaySwissTimingRace(RegattaIdentifier regattaIdentifier, Iterable replayRaceDTOs, - boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm) { - logger.info("replaySwissTimingRace for regatta "+regattaIdentifier+" for races "+replayRaceDTOs); + public void replaySwissTimingRace(RegattaIdentifier regattaIdentifier, + Iterable replayRaceDTOs, boolean trackWind, boolean correctWindByDeclination, + boolean useInternalMarkPassingAlgorithm) { + logger.info("replaySwissTimingRace for regatta " + regattaIdentifier + " for races " + replayRaceDTOs); for (SwissTimingReplayRaceDTO replayRaceDTO : replayRaceDTOs) { try { String boatClassName; @@ -2980,8 +3167,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } else { boatClassName = null; } - getSwissTimingReplayService().loadRaceData(regattaIdentifier, replayRaceDTO.link, replayRaceDTO.getName(), - replayRaceDTO.race_id, boatClassName, getService(), getService(), useInternalMarkPassingAlgorithm, getRaceLogStore(), getRegattaLogStore()); + getSwissTimingReplayService().loadRaceData(regattaIdentifier, replayRaceDTO.link, + replayRaceDTO.getName(), replayRaceDTO.race_id, boatClassName, getService(), getService(), + useInternalMarkPassingAlgorithm, getRaceLogStore(), getRegattaLogStore()); } catch (Exception e) { logger.log(Level.SEVERE, "Error trying to load SwissTimingReplay race " + replayRaceDTO, e); } @@ -3001,7 +3189,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** - * Finds a competitor in a sequence of competitors that has an {@link Competitor#getId()} equal to id. + * Finds a competitor in a sequence of competitors that has an {@link Competitor#getId()} equal to id. */ private Competitor getCompetitorByIdAsString(Iterable competitors, String idAsString) { for (Competitor c : competitors) { @@ -3013,7 +3201,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } private Double getCompetitorRaceDataEntry(DetailType dataType, TrackedRace trackedRace, Competitor competitor, - TimePoint timePoint, String leaderboardGroupName, String leaderboardName, WindLegTypeAndLegBearingCache cache) throws NoWindException { + TimePoint timePoint, String leaderboardGroupName, String leaderboardName, + WindLegTypeAndLegBearingCache cache) throws NoWindException { Double result = null; Course course = trackedRace.getRace().getCourse(); course.lockForRead(); // make sure the tracked leg survives this call even if a course update is pending @@ -3052,21 +3241,25 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S break; case LEG_DISTANCE_TRAVELED_INCLUDING_GATE_START: if (trackedLeg != null) { - Distance distanceTraveledConsideringGateStart = trackedRace.getDistanceTraveledIncludingGateStart(competitor, timePoint); - result = distanceTraveledConsideringGateStart == null ? null : distanceTraveledConsideringGateStart.getMeters(); + Distance distanceTraveledConsideringGateStart = trackedRace + .getDistanceTraveledIncludingGateStart(competitor, timePoint); + result = distanceTraveledConsideringGateStart == null ? null + : distanceTraveledConsideringGateStart.getMeters(); } break; case LEG_GAP_TO_LEADER_IN_SECONDS: if (trackedLeg != null) { final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint); - final Duration gapToLeaderInOwnTime = trackedLeg.getTrackedLeg().getTrackedRace().getRankingMetric().getGapToLeaderInOwnTime(rankingInfo, competitor, cache); + final Duration gapToLeaderInOwnTime = trackedLeg.getTrackedLeg().getTrackedRace().getRankingMetric() + .getGapToLeaderInOwnTime(rankingInfo, competitor, cache); result = gapToLeaderInOwnTime == null ? null : gapToLeaderInOwnTime.asSeconds(); } break; case CHART_WINDWARD_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD: if (trackedLeg != null) { final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint); - Distance distanceToLeader = trackedLeg.getWindwardDistanceToCompetitorFarthestAhead(timePoint, WindPositionMode.LEG_MIDDLE, rankingInfo); + Distance distanceToLeader = trackedLeg.getWindwardDistanceToCompetitorFarthestAhead(timePoint, + WindPositionMode.LEG_MIDDLE, rankingInfo); result = (distanceToLeader == null) ? null : distanceToLeader.getMeters(); } break; @@ -3080,8 +3273,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S break; } Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - result = leaderboard == null ? null : (double) leaderboard.getTotalRankOfCompetitor(competitor, - timePoint); + result = leaderboard == null ? null + : (double) leaderboard.getTotalRankOfCompetitor(competitor, timePoint); break; case OVERALL_RANK: if (leaderboardGroupName == null || leaderboardGroupName.isEmpty()) { @@ -3100,7 +3293,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S break; case CHART_BEAT_ANGLE: Bearing twa = trackedRace.getTWA(competitor, timePoint, cache); - result = twa == null? null:twa.getDegrees(); + result = twa == null ? null : twa.getDegrees(); break; case BRAVO_RACE_HEEL_IN_DEGREES: case BRAVO_LEG_CURRENT_HEEL_IN_DEGREES: { @@ -3117,27 +3310,33 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S break; } case BRAVOEXTENDED_RACE_CURRENT_PORT_DAGGERBOARD_RAKE: { - result = getBravoDoubleValue(BravoFixTrack::getPortDaggerboardRakeIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getPortDaggerboardRakeIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_STBD_DAGGERBOARD_RAKE: { - result = getBravoDoubleValue(BravoFixTrack::getStbdDaggerboardRakeStbdIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getStbdDaggerboardRakeStbdIfAvailable, trackedRace, + competitor, timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_PORT_RUDDER_RAKE: { - result = getBravoDoubleValue(BravoFixTrack::getPortRudderRakeIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getPortRudderRakeIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_STBD_RUDDER_RAKE: { - result = getBravoDoubleValue(BravoFixTrack::getStbdRudderRakeIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getStbdRudderRakeIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_MAST_ROTATION_IN_DEGREES: { - result = getBravoBearingInDegrees(BravoFixTrack::getMastRotationIfAvailable, trackedRace, competitor, timePoint); + result = getBravoBearingInDegrees(BravoFixTrack::getMastRotationIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_LEEWAY_IN_DEGREES: { - result = getBravoBearingInDegrees(BravoFixTrack::getLeewayIfAvailable, trackedRace, competitor, timePoint); + result = getBravoBearingInDegrees(BravoFixTrack::getLeewayIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_SET: { @@ -3145,210 +3344,260 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S break; } case BRAVOEXTENDED_RACE_CURRENT_DRIFT_IN_DEGREES: { - result = getBravoBearingInDegrees(BravoFixTrack::getDriftIfAvailable, trackedRace, competitor, timePoint); + result = getBravoBearingInDegrees(BravoFixTrack::getDriftIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_DEPTH_IN_METERS: { - result = getBravoDistanceInMeters(BravoFixTrack::getDepthIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDistanceInMeters(BravoFixTrack::getDepthIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_RUDDER_IN_DEGREES: { - result = getBravoBearingInDegrees(BravoFixTrack::getRudderIfAvailable, trackedRace, competitor, timePoint); + result = getBravoBearingInDegrees(BravoFixTrack::getRudderIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_TACK_ANGLE_IN_DEGREES: { - result = getBravoBearingInDegrees(BravoFixTrack::getTackAngleIfAvailable, trackedRace, competitor, timePoint); + result = getBravoBearingInDegrees(BravoFixTrack::getTackAngleIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_DEFLECTOR_PERCENTAGE: { - result = getBravoDoubleValue(BravoFixTrack::getDeflectorPercentageIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getDeflectorPercentageIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_DEFLECTOR_IN_MILLIMETERS: { - Double deflectorInMeters = getBravoDistanceInMeters(BravoFixTrack::getDeflectorIfAvailable, trackedRace, competitor, timePoint); + Double deflectorInMeters = getBravoDistanceInMeters(BravoFixTrack::getDeflectorIfAvailable, trackedRace, + competitor, timePoint); result = deflectorInMeters == null ? null : (deflectorInMeters * 1000.); break; } case BRAVOEXTENDED_RACE_CURRENT_RAKE_IN_DEGREES: { - result = getBravoBearingInDegrees(BravoFixTrack::getRakeIfAvailable, trackedRace, competitor, timePoint); + result = getBravoBearingInDegrees(BravoFixTrack::getRakeIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_TARGET_HEEL_ANGLE_IN_DEGREES: { - result = getBravoBearingInDegrees(BravoFixTrack::getTargetHeelIfAvailable, trackedRace, competitor, timePoint); + result = getBravoBearingInDegrees(BravoFixTrack::getTargetHeelIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_FORESTAY_LOAD: { - result = getBravoDoubleValue(BravoFixTrack::getForestayLoadIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getForestayLoadIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_FORESTAY_PRESSURE: { - result = getBravoDoubleValue(BravoFixTrack::getForestayPressureIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getForestayPressureIfAvailable, trackedRace, competitor, + timePoint); break; } case BRAVOEXTENDED_RACE_CURRENT_TARGET_BOATSPEED_PERCENTAGE: { - result = getBravoDoubleValue(BravoFixTrack::getTargetBoatspeedPIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getTargetBoatspeedPIfAvailable, trackedRace, competitor, + timePoint); break; } - + case EXPEDITION_RACE_AWA: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionAWAIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionAWAIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_AWS: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionAWSIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionAWSIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_BARO: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionBaroIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionBaroIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_BOAT_SPEED: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionBoatSpeedIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionBoatSpeedIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_COG: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionCOGIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionCOGIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_COURSE: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionCourseDetailIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionCourseDetailIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_DIST_TO_PORT_LAYLINE: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistToPortLaylineIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistToPortLaylineIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_DIST_TO_STB_LAYLINE: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistToStbLaylineIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistToStbLaylineIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_DISTANCE_BELOW_LINE: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceBelowLineInMetersIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceBelowLineInMetersIfAvailable, + trackedRace, competitor, timePoint); break; } case EXPEDITION_RACE_DISTANCE_TO_COMMITTEE_BOAT: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceToCommitteeBoatIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceToCommitteeBoatIfAvailable, + trackedRace, competitor, timePoint); break; } case EXPEDITION_RACE_DISTANCE_TO_PIN: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceToPinDetailIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceToPinDetailIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_FORESTAY_LOAD: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionForestayLoadIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionForestayLoadIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_HEADING: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionHeadingIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionHeadingIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_JIB_CAR_PORT: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionJibCarPortIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionJibCarPortIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_JIB_CAR_STBD: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionJibCarStbdIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionJibCarStbdIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_LINE_SQUARE_FOR_WIND_DIRECTION: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionLineSquareForWindIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionLineSquareForWindIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_LOAD_P: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionLoadPIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionLoadPIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_LOAD_S: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionLoadSIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionLoadSIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_MAST_BUTT: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionMastButtIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionMastButtIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_RAKE: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionRakeIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionRakeIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_RATE_OF_TURN: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionRateOfTurnIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionRateOfTurnIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_RUDDER_ANGLE: { - result = getBravoBearingInDegrees(BravoFixTrack::getRudderIfAvailable, trackedRace, competitor, timePoint); + result = getBravoBearingInDegrees(BravoFixTrack::getRudderIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_SOG: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionSOGIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionSOGIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_TARG_BOAT_SPEED: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargBoatSpeedIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargBoatSpeedIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_TARG_TWA: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargTWAIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargTWAIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_TARGET_HEEL: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargetHeelIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargetHeelIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_TIME_TO_BURN_TO_COMMITTEE_BOAT: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToCommitteeBoatIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToCommitteeBoatIfAvailable, + trackedRace, competitor, timePoint); break; } case EXPEDITION_RACE_TIME_TO_BURN_TO_LINE: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToLineInSecondsIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToLineInSecondsIfAvailable, + trackedRace, competitor, timePoint); break; } case EXPEDITION_RACE_TIME_TO_BURN_TO_PIN: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToPinIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToPinIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_TIME_TO_COMMITTEE_BOAT: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToCommitteeBoatIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToCommitteeBoatIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_TIME_TO_GUN: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToGunInSecondsIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToGunInSecondsIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_TIME_TO_PIN: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToPinIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToPinIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_TIME_TO_PORT_LAYLINE: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToPortLaylineIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToPortLaylineIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_TIME_TO_STB_LAYLINE: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToStbLaylineIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToStbLaylineIfAvailable, trackedRace, + competitor, timePoint); break; } case EXPEDITION_RACE_TWA: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWAIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWAIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_TWD: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWDIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWDIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_TWS: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWSIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWSIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_VMG: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionVMGIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionVMGIfAvailable, trackedRace, competitor, + timePoint); break; } case EXPEDITION_RACE_VMG_TARG_VMG_DELTA: { - result = getBravoDoubleValue(BravoFixTrack::getExpeditionVMGTargVMGDeltaIfAvailable, trackedRace, competitor, timePoint); + result = getBravoDoubleValue(BravoFixTrack::getExpeditionVMGTargVMGDeltaIfAvailable, trackedRace, + competitor, timePoint); break; } default: - throw new UnsupportedOperationException("There is currently no support for the enum value '" + dataType - + "' in this method."); + throw new UnsupportedOperationException( + "There is currently no support for the enum value '" + dataType + "' in this method."); } return result; } finally { @@ -3360,20 +3609,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) { return getBravoValue(valueGetter, Function.identity(), trackedRace, competitor, timePoint); } - + private Double getBravoBearingInDegrees(BiFunction, TimePoint, Bearing> valueGetter, TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) { return getBravoValue(valueGetter, Bearing::getDegrees, trackedRace, competitor, timePoint); } - + private Double getBravoDistanceInMeters(BiFunction, TimePoint, Distance> valueGetter, TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) { return getBravoValue(valueGetter, Distance::getMeters, trackedRace, competitor, timePoint); } - + private Double getBravoValue(BiFunction, TimePoint, T> valueGetter, - Function mapperToDouble, - TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) { + Function mapperToDouble, TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) { final Double result; final BravoFixTrack bravoFixTrack = trackedRace .> getSensorTrack(competitor, BravoFixTrack.TRACK_NAME); @@ -3387,25 +3635,31 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public CompetitorsRaceDataDTO getCompetitorsRaceData(RegattaAndRaceIdentifier race, List competitors, Date from, Date to, - final long stepSizeInMillis, final DetailType detailType, final String leaderboardGroupName, final String leaderboardName) throws NoWindException { + public CompetitorsRaceDataDTO getCompetitorsRaceData(RegattaAndRaceIdentifier race, List competitors, + Date from, Date to, final long stepSizeInMillis, final DetailType detailType, + final String leaderboardGroupName, final String leaderboardName) throws NoWindException { CompetitorsRaceDataDTO result = null; final TrackedRace trackedRace = getExistingTrackedRace(race); if (trackedRace != null) { TimePoint newestEvent = trackedRace.getTimePointOfNewestEvent(); - final TimePoint startTime = from == null ? trackedRace.getStartOfTracking() : new MillisecondsTimePoint(from); - final TimePoint endTime = (to == null || to.after(newestEvent.asDate())) ? newestEvent : new MillisecondsTimePoint(to); - final long adjustedStepSizeInMillis = (long) Math.max((double) stepSizeInMillis, startTime.until(endTime).divide(SailingServiceConstants.MAX_NUMBER_OF_FIXES_TO_QUERY).asMillis()); - result = new CompetitorsRaceDataDTO(detailType, startTime==null?null:startTime.asDate(), endTime==null?null:endTime.asDate()); + final TimePoint startTime = from == null ? trackedRace.getStartOfTracking() + : new MillisecondsTimePoint(from); + final TimePoint endTime = (to == null || to.after(newestEvent.asDate())) ? newestEvent + : new MillisecondsTimePoint(to); + final long adjustedStepSizeInMillis = (long) Math.max((double) stepSizeInMillis, + startTime.until(endTime).divide(SailingServiceConstants.MAX_NUMBER_OF_FIXES_TO_QUERY).asMillis()); + result = new CompetitorsRaceDataDTO(detailType, startTime == null ? null : startTime.asDate(), + endTime == null ? null : endTime.asDate()); final int MAX_CACHE_SIZE = SailingServiceConstants.MAX_NUMBER_OF_FIXES_TO_QUERY; final ConcurrentHashMap cachesByTimePoint = new ConcurrentHashMap<>(); Map> resultFutures = new HashMap<>(); for (final CompetitorDTO competitorDTO : competitors) { - FutureTask future = new FutureTask(new Callable() { + FutureTask future = new FutureTask( + new Callable() { @Override public CompetitorRaceDataDTO call() throws NoWindException { - Competitor competitor = getCompetitorByIdAsString(trackedRace.getRace().getCompetitors(), - competitorDTO.getIdAsString()); + Competitor competitor = getCompetitorByIdAsString( + trackedRace.getRace().getCompetitors(), competitorDTO.getIdAsString()); ArrayList> markPassingsData = new ArrayList>(); ArrayList> raceData = new ArrayList>(); // Filling the mark passings @@ -3414,17 +3668,21 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S trackedRace.lockForRead(competitorMarkPassings); try { for (MarkPassing markPassing : competitorMarkPassings) { - MillisecondsTimePoint time = new MillisecondsTimePoint(markPassing.getTimePoint().asMillis()); + MillisecondsTimePoint time = new MillisecondsTimePoint( + markPassing.getTimePoint().asMillis()); WindLegTypeAndLegBearingCache cache = cachesByTimePoint.get(time); if (cache == null) { cache = new LeaderboardDTOCalculationReuseCache(time); cachesByTimePoint.put(time, cache); } Double competitorMarkPassingsData = getCompetitorRaceDataEntry(detailType, - trackedRace, competitor, time, leaderboardGroupName, leaderboardName, cache); + trackedRace, competitor, time, leaderboardGroupName, + leaderboardName, cache); if (competitorMarkPassingsData != null) { - markPassingsData.add(new com.sap.sse.common.Util.Triple(markPassing - .getWaypoint().getName(), time.asDate(), competitorMarkPassingsData)); + markPassingsData + .add(new com.sap.sse.common.Util.Triple( + markPassing.getWaypoint().getName(), time.asDate(), + competitorMarkPassingsData)); } } } finally { @@ -3432,14 +3690,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } if (startTime != null && endTime != null) { - for (long i = startTime.asMillis(); i <= endTime.asMillis(); i += adjustedStepSizeInMillis) { + for (long i = startTime.asMillis(); i <= endTime + .asMillis(); i += adjustedStepSizeInMillis) { MillisecondsTimePoint time = new MillisecondsTimePoint(i); WindLegTypeAndLegBearingCache cache = cachesByTimePoint.get(time); if (cache == null) { cache = new LeaderboardDTOCalculationReuseCache(time); if (cachesByTimePoint.size() >= MAX_CACHE_SIZE) { - final Iterator> iterator = cachesByTimePoint.entrySet().iterator(); - while (cachesByTimePoint.size() >= MAX_CACHE_SIZE && iterator.hasNext()) { + final Iterator> iterator = cachesByTimePoint + .entrySet().iterator(); + while (cachesByTimePoint.size() >= MAX_CACHE_SIZE + && iterator.hasNext()) { iterator.next(); iterator.remove(); } @@ -3449,7 +3710,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Double competitorRaceData = getCompetitorRaceDataEntry(detailType, trackedRace, competitor, time, leaderboardGroupName, leaderboardName, cache); if (competitorRaceData != null) { - raceData.add(new com.sap.sse.common.Util.Pair(time.asDate(), competitorRaceData)); + raceData.add(new com.sap.sse.common.Util.Pair(time.asDate(), + competitorRaceData)); } } } @@ -3465,10 +3727,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S competitorData = e.getValue().get(); } catch (InterruptedException e1) { competitorData = null; - logger.log(Level.SEVERE, "Exception while trying to compute competitor data "+detailType+" for competitor "+e.getKey().getName(), e1); + logger.log(Level.SEVERE, "Exception while trying to compute competitor data " + detailType + + " for competitor " + e.getKey().getName(), e1); } catch (ExecutionException e1) { competitorData = null; - logger.log(Level.SEVERE, "Exception while trying to compute competitor data "+detailType+" for competitor "+e.getKey().getName(), e1); + logger.log(Level.SEVERE, "Exception while trying to compute competitor data " + detailType + + " for competitor " + e.getKey().getName(), e1); } result.setCompetitorData(e.getKey(), competitorData); } @@ -3477,10 +3741,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public List, List>> getLeaderboardDataEntriesForAllRaceColumns(String leaderboardName, - Date date, DetailType detailType) throws Exception { + public List, List>> getLeaderboardDataEntriesForAllRaceColumns( + String leaderboardName, Date date, DetailType detailType) throws Exception { List, List>> result = new ArrayList<>(); - // Attention: The reason why we read the data from the LeaderboardDTO and not from the leaderboard directly is to ensure + // Attention: The reason why we read the data from the LeaderboardDTO and not from the leaderboard directly is + // to ensure // the use of the leaderboard cache. final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard != null) { @@ -3494,14 +3759,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (detailType != null) { switch (detailType) { case REGATTA_NET_POINTS_SUM: - for (Entry> e : leaderboard.getNetPointsSumAfterRaceColumn(effectiveTimePoint).entrySet()) { + for (Entry> e : leaderboard + .getNetPointsSumAfterRaceColumn(effectiveTimePoint).entrySet()) { List competitorDTOs = new ArrayList<>(); List pointSums = new ArrayList<>(); for (Entry e2 : e.getValue().entrySet()) { competitorDTOs.add(baseDomainFactory.convertToCompetitorDTO(e2.getKey())); pointSums.add(e2.getValue()); } - result.add(new Triple<>(e.getKey().getName(), competitorDTOs, pointSums)); + result.add(new Triple<>(e.getKey().getName(), competitorDTOs, pointSums)); } break; case REGATTA_RANK: @@ -3549,7 +3815,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } // If we could identify the associated LeaderboardGroup the Leaderboards can be sorted based on that group Iterable leaderBoards = groupOrNull != null - ? HomeServiceUtil.getLeaderboardsForSeriesInOrder(groupOrNull) : metaLeaderboard.getLeaderboards(); + ? HomeServiceUtil.getLeaderboardsForSeriesInOrder(groupOrNull) + : metaLeaderboard.getLeaderboards(); List> result = new ArrayList>(); for (Leaderboard containedLeaderboard : leaderBoards) { result.add(new com.sap.sse.common.Util.Pair(containedLeaderboard.getName(), @@ -3583,15 +3850,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final Bearing bearing = fix.getPosition().getBearingGreatCircle(next.getPosition()); final Speed speed = fix.getPosition().getDistance(next.getPosition()) .inTime(next.getTimePoint().asMillis() - fix.getTimePoint().asMillis()); - final SpeedWithBearing speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), bearing); - gpsFixDouglasList.add(createDouglasPeuckerGPSFixDTO(trackedRace, competitor, fix, speedWithBearing)); + final SpeedWithBearing speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), + bearing); + gpsFixDouglasList + .add(createDouglasPeuckerGPSFixDTO(trackedRace, competitor, fix, speedWithBearing)); } fix = next; } if (fix != null) { // add one last GPSFixDTO with no successor to calculate speed/bearing to: final SpeedWithBearing speedWithBearing = gpsFixTrack.getEstimatedSpeed(fix.getTimePoint()); - gpsFixDouglasList.add(createDouglasPeuckerGPSFixDTO(trackedRace, competitor, fix, speedWithBearing)); + gpsFixDouglasList + .add(createDouglasPeuckerGPSFixDTO(trackedRace, competitor, fix, speedWithBearing)); } result.put(competitorDTO, gpsFixDouglasList); } @@ -3600,16 +3870,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return result; } - private GPSFixDTOWithSpeedWindTackAndLegType createDouglasPeuckerGPSFixDTO(TrackedRace trackedRace, Competitor competitor, GPSFix fix, - SpeedWithBearing speedWithBearing) throws NoWindException { + private GPSFixDTOWithSpeedWindTackAndLegType createDouglasPeuckerGPSFixDTO(TrackedRace trackedRace, + Competitor competitor, GPSFix fix, SpeedWithBearing speedWithBearing) throws NoWindException { Tack tack = trackedRace.getTack(competitor, fix.getTimePoint()); - TrackedLegOfCompetitor trackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor, - fix.getTimePoint()); - LegType legType = trackedLegOfCompetitor == null ? null : trackedRace.getTrackedLeg( - trackedLegOfCompetitor.getLeg()).getLegType(fix.getTimePoint()); + TrackedLegOfCompetitor trackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor, fix.getTimePoint()); + LegType legType = trackedLegOfCompetitor == null ? null + : trackedRace.getTrackedLeg(trackedLegOfCompetitor.getLeg()).getLegType(fix.getTimePoint()); Wind wind = trackedRace.getWind(fix.getPosition(), fix.getTimePoint()); WindDTO windDTO = createWindDTOFromAlreadyAveraged(wind, fix.getTimePoint()); - GPSFixDTOWithSpeedWindTackAndLegType fixDTO = createGPSFixDTO(fix, speedWithBearing, windDTO, tack, legType, /* extrapolated */ + GPSFixDTOWithSpeedWindTackAndLegType fixDTO = createGPSFixDTO(fix, speedWithBearing, windDTO, tack, legType, /* + * extrapolated + */ false); return fixDTO; } @@ -3646,7 +3917,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return result; } - private List createManeuverDTOsForCompetitor(Iterable maneuvers, TrackedRace trackedRace, Competitor competitor) { + private List createManeuverDTOsForCompetitor(Iterable maneuvers, TrackedRace trackedRace, + Competitor competitor) { final List result = new ArrayList(); for (Maneuver maneuver : maneuvers) { final ManeuverType type = maneuver.getType(); @@ -3661,18 +3933,21 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final double averageTurningRateInDegreesPerSecond = maneuver.getAvgTurningRateInDegreesPerSecond(); final double lowestSpeedInKnots = maneuver.getLowestSpeed().getKnots(); final Date markPassingTimePoint = maneuver.isMarkPassing() - ? maneuver.getMarkPassing().getTimePoint().asDate() : null; + ? maneuver.getMarkPassing().getTimePoint().asDate() + : null; final NauticalSide markPassingSide = maneuver.isMarkPassing() ? maneuver.getToSide() : null; final SpeedWithBearing speedWithBearingBeforeManeuverLoss = maneuver.getManeuverLoss() == null ? null : maneuver.getManeuverLoss().getSpeedWithBearingBefore(); - final Double middleManeuverAngle = maneuver.getManeuverLoss() == null ? null : maneuver.getManeuverLoss().getMiddleManeuverAngle().getDegrees(); + final Double middleManeuverAngle = maneuver.getManeuverLoss() == null ? null + : maneuver.getManeuverLoss().getMiddleManeuverAngle().getDegrees(); final ManeuverLossDTO maneuverLoss = maneuver.getManeuverLoss() == null ? null : new ManeuverLossDTO(maneuver.getManeuverLoss().getManeuverStartPosition(), - maneuver.getManeuverLoss().getManeuverEndPosition(), speedWithBearingBeforeManeuverLoss, middleManeuverAngle, - maneuver.getManeuverLoss().getManeuverDuration(), maneuver.getManeuverLoss().getProjectedDistanceLost()); - result.add(new ManeuverDTO(type, newTack, position, timepoint, timePointBefore, speedBefore, - speedAfter, directionChangeInDegrees, maxTurningRateInDegreesPerSecond, - averageTurningRateInDegreesPerSecond, lowestSpeedInKnots, markPassingTimePoint, markPassingSide, maneuverLoss)); + maneuver.getManeuverLoss().getManeuverEndPosition(), speedWithBearingBeforeManeuverLoss, + middleManeuverAngle, maneuver.getManeuverLoss().getManeuverDuration(), + maneuver.getManeuverLoss().getProjectedDistanceLost()); + result.add(new ManeuverDTO(type, newTack, position, timepoint, timePointBefore, speedBefore, speedAfter, + directionChangeInDegrees, maxTurningRateInDegreesPerSecond, averageTurningRateInDegreesPerSecond, + lowestSpeedInKnots, markPassingTimePoint, markPassingSide, maneuverLoss)); } return result; } @@ -3703,9 +3978,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** - * Returns a servlet context that, when asked for a resource, first tries the original servlet context's implementation. If that - * fails, it prepends "war/" to the request because the war/ folder contains all the resources exposed externally - * through the HTTP server. + * Returns a servlet context that, when asked for a resource, first tries the original servlet context's + * implementation. If that fails, it prepends "war/" to the request because the war/ folder contains all the + * resources exposed externally through the HTTP server. */ @Override public ServletContext getServletContext() { @@ -3714,10 +3989,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override /** - * Override of function to prevent exception "Blocked request without GWT permutation header (XSRF attack?)" when testing the GWT sites + * Override of function to prevent exception "Blocked request without GWT permutation header (XSRF attack?)" when + * testing the GWT sites */ protected void checkPermutationStrongName() throws SecurityException { - //Override to prevent exception "Blocked request without GWT permutation header (XSRF attack?)" when testing the GWT sites + // Override to prevent exception "Blocked request without GWT permutation header (XSRF attack?)" when testing + // the GWT sites return; } @@ -3735,33 +4012,37 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public LeaderboardGroupDTO getLeaderboardGroupByName(String groupName, boolean withGeoLocationData) { - return convertToLeaderboardGroupDTO(getService().getLeaderboardGroupByName(groupName), withGeoLocationData, false); + return convertToLeaderboardGroupDTO(getService().getLeaderboardGroupByName(groupName), withGeoLocationData, + false); } - public LeaderboardGroupDTO convertToLeaderboardGroupDTO(LeaderboardGroup leaderboardGroup, boolean withGeoLocationData, boolean withStatisticalData) { + public LeaderboardGroupDTO convertToLeaderboardGroupDTO(LeaderboardGroup leaderboardGroup, + boolean withGeoLocationData, boolean withStatisticalData) { LeaderboardGroupDTO groupDTO = new LeaderboardGroupDTO(leaderboardGroup.getId(), leaderboardGroup.getName(), leaderboardGroup.getDisplayName(), leaderboardGroup.getDescription()); groupDTO.displayLeaderboardsInReverseOrder = leaderboardGroup.isDisplayGroupsInReverseOrder(); for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { try { - StrippedLeaderboardDTO leaderboardDTO = createStrippedLeaderboardDTO(leaderboard, withGeoLocationData, withStatisticalData); + StrippedLeaderboardDTO leaderboardDTO = createStrippedLeaderboardDTO(leaderboard, withGeoLocationData, + withStatisticalData); groupDTO.leaderboards.add(leaderboardDTO); } catch (Exception e) { - logger.log(Level.SEVERE, "Caught exception while reading data for leaderboard " + leaderboard.getName(), e); + logger.log(Level.SEVERE, "Caught exception while reading data for leaderboard " + leaderboard.getName(), + e); } } Leaderboard overallLeaderboard = leaderboardGroup.getOverallLeaderboard(); if (overallLeaderboard != null) { if (overallLeaderboard.getResultDiscardingRule() instanceof ThresholdBasedResultDiscardingRule) { - groupDTO.setOverallLeaderboardDiscardThresholds(((ThresholdBasedResultDiscardingRule) overallLeaderboard - .getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces()); + groupDTO.setOverallLeaderboardDiscardThresholds( + ((ThresholdBasedResultDiscardingRule) overallLeaderboard.getResultDiscardingRule()) + .getDiscardIndexResultsStartingWithHowManyRaces()); } groupDTO.setOverallLeaderboardScoringSchemeType(overallLeaderboard.getScoringScheme().getType()); } return groupDTO; } - @Override public void renameLeaderboardGroup(String oldName, String newName) { getService().apply(new RenameLeaderboardGroup(oldName, newName)); @@ -3780,20 +4061,22 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public LeaderboardGroupDTO createLeaderboardGroup(String groupName, String description, String displayName, - boolean displayGroupsInReverseOrder, - int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType) { - CreateLeaderboardGroup createLeaderboardGroupOp = new CreateLeaderboardGroup(groupName, description, displayName, - displayGroupsInReverseOrder, new ArrayList(), overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType); + boolean displayGroupsInReverseOrder, int[] overallLeaderboardDiscardThresholds, + ScoringSchemeType overallLeaderboardScoringSchemeType) { + CreateLeaderboardGroup createLeaderboardGroupOp = new CreateLeaderboardGroup(groupName, description, + displayName, displayGroupsInReverseOrder, new ArrayList(), overallLeaderboardDiscardThresholds, + overallLeaderboardScoringSchemeType); return convertToLeaderboardGroupDTO(getService().apply(createLeaderboardGroupOp), false, false); } @Override public void updateLeaderboardGroup(String oldName, String newName, String newDescription, String newDisplayName, - List leaderboardNames, int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD_GROUP.getStringPermissionForObjects(Mode.UPDATE, oldName)); - getService().apply( - new UpdateLeaderboardGroup(oldName, newName, newDescription, newDisplayName, - leaderboardNames, overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType)); + List leaderboardNames, int[] overallLeaderboardDiscardThresholds, + ScoringSchemeType overallLeaderboardScoringSchemeType) { + SecurityUtils.getSubject() + .checkPermission(Permission.LEADERBOARD_GROUP.getStringPermissionForObjects(Mode.UPDATE, oldName)); + getService().apply(new UpdateLeaderboardGroup(oldName, newName, newDescription, newDisplayName, + leaderboardNames, overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType)); } @Override @@ -3801,7 +4084,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S ReplicationService service = getReplicationService(); Set replicaDTOs = new HashSet(); for (ReplicaDescriptor replicaDescriptor : service.getReplicaInfo()) { - final Map>, Integer> statistics = service.getStatistics(replicaDescriptor); + final Map>, Integer> statistics = service + .getStatistics(replicaDescriptor); Map replicationCountByOperationClassName = new HashMap(); for (Entry>, Integer> e : statistics.entrySet()) { replicationCountByOperationClassName.put(e.getKey().getName(), e.getValue()); @@ -3818,9 +4102,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (replicatingFromMaster == null) { master = null; } else { - master = new ReplicationMasterDTO(replicatingFromMaster.getHostname(), replicatingFromMaster.getServletPort(), - replicatingFromMaster.getMessagingHostname(), replicatingFromMaster.getMessagingPort(), replicatingFromMaster.getExchangeName(), - StreamSupport.stream(replicatingFromMaster.getReplicables().spliterator(), /* parallel */ false).map(r->r.getId()).toArray(s->new String[s])); + master = new ReplicationMasterDTO(replicatingFromMaster.getHostname(), + replicatingFromMaster.getServletPort(), replicatingFromMaster.getMessagingHostname(), + replicatingFromMaster.getMessagingPort(), replicatingFromMaster.getExchangeName(), + StreamSupport.stream(replicatingFromMaster.getReplicables().spliterator(), /* parallel */ false) + .map(r -> r.getId()).toArray(s -> new String[s])); } return new ReplicationStateDTO(master, replicaDTOs, service.getServerIdentifier().toString()); } @@ -3833,14 +4119,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public String[] getReplicableIdsAsStringThatShallLeadToWarningAboutInstanceBeingReplica() { return new String[] { getService().getId().toString() }; } - + @Override - public void startReplicatingFromMaster(String messagingHost, String masterHost, String exchangeName, int servletPort, int messagingPort) throws IOException, ClassNotFoundException, InterruptedException { + public void startReplicatingFromMaster(String messagingHost, String masterHost, String exchangeName, + int servletPort, int messagingPort) throws IOException, ClassNotFoundException, InterruptedException { // The queue name must always be the same for this server. In order to achieve // this we're using the unique server identifier - getReplicationService().startToReplicateFrom( - ReplicationFactory.INSTANCE.createReplicationMasterDescriptor(messagingHost, masterHost, exchangeName, servletPort, messagingPort, - /* use local server identifier as queue name */ getReplicationService().getServerIdentifier().toString(), getReplicationService().getAllReplicables())); + getReplicationService() + .startToReplicateFrom( + ReplicationFactory.INSTANCE.createReplicationMasterDescriptor(messagingHost, masterHost, + exchangeName, servletPort, messagingPort, + /* use local server identifier as queue name */ getReplicationService() + .getServerIdentifier().toString(), + getReplicationService().getAllReplicables())); } @Override @@ -3863,16 +4154,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S result.add(localEvent); } } - for (Entry, Exception>> serverRefAndEventsOrException : - getService().getPublicEventsOfAllSailingServers().entrySet()) { - final com.sap.sse.common.Util.Pair, Exception> eventsOrException = serverRefAndEventsOrException.getValue(); + for (Entry, Exception>> serverRefAndEventsOrException : getService() + .getPublicEventsOfAllSailingServers().entrySet()) { + final com.sap.sse.common.Util.Pair, Exception> eventsOrException = serverRefAndEventsOrException + .getValue(); final RemoteSailingServerReference serverRef = serverRefAndEventsOrException.getKey(); final Iterable remoteEvents = eventsOrException.getA(); String baseURLFromServerReference = getBaseURL(serverRef.getURL()).toString(); if (remoteEvents != null) { for (EventBase remoteEvent : remoteEvents) { EventBaseDTO remoteEventDTO = convertToEventDTO(remoteEvent); - remoteEventDTO.setBaseURL(remoteEvent.getBaseURL() == null ? baseURLFromServerReference : remoteEvent.getBaseURL().toString()); + remoteEventDTO.setBaseURL(remoteEvent.getBaseURL() == null ? baseURLFromServerReference + : remoteEvent.getBaseURL().toString()); remoteEventDTO.setIsOnRemoteServer(true); result.add(remoteEventDTO); } @@ -3882,9 +4175,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** - * Determines the base URL (protocol, host and port parts) used for the currently executing servlet request. Defaults - * to http://sapsailing.com. - * @throws MalformedURLException + * Determines the base URL (protocol, host and port parts) used for the currently executing servlet request. + * Defaults to http://sapsailing.com. + * + * @throws MalformedURLException */ private URL getRequestBaseURL() throws MalformedURLException { final URL url = new URL(getThreadLocalRequest().getRequestURL().toString()); @@ -3906,16 +4200,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S eventDTOs = null; final Exception exception = eventsOrException.getB(); sailingServerDTO = new RemoteSailingServerReferenceDTO(serverRef.getName(), - serverRef.getURL().toExternalForm(), exception==null?null:exception.getMessage()); + serverRef.getURL().toExternalForm(), exception == null ? null : exception.getMessage()); } else { eventDTOs = convertToEventDTOs(events); - sailingServerDTO = new RemoteSailingServerReferenceDTO( - serverRef.getName(), serverRef - .getURL().toExternalForm(), eventDTOs); + sailingServerDTO = new RemoteSailingServerReferenceDTO(serverRef.getName(), + serverRef.getURL().toExternalForm(), eventDTOs); } return sailingServerDTO; } - + private Iterable convertToEventDTOs(Iterable events) { List result = new ArrayList<>(); for (EventBase event : events) { @@ -3927,40 +4220,40 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public EventDTO updateEvent(UUID eventId, String eventName, String eventDescription, Date startDate, Date endDate, - VenueDTO venue, boolean isPublic, Iterable leaderboardGroupIds, String officialWebsiteURLString, String baseURLAsString, - Map sailorsInfoWebsiteURLsByLocaleName, Iterable images, Iterable videos, - Iterable windFinderReviewedSpotCollectionIds) throws MalformedURLException { + VenueDTO venue, boolean isPublic, Iterable leaderboardGroupIds, String officialWebsiteURLString, + String baseURLAsString, Map sailorsInfoWebsiteURLsByLocaleName, Iterable images, + Iterable videos, Iterable windFinderReviewedSpotCollectionIds) + throws MalformedURLException { TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; - TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; + TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; URL officialWebsiteURL = officialWebsiteURLString != null ? new URL(officialWebsiteURLString) : null; URL baseURL = baseURLAsString != null ? new URL(baseURLAsString) : null; Map sailorsInfoWebsiteURLs = convertToLocalesAndUrls(sailorsInfoWebsiteURLsByLocaleName); List eventImages = convertToImages(images); List eventVideos = convertToVideos(videos); - getService().apply( - new UpdateEvent(eventId, eventName, eventDescription, startTimePoint, endTimePoint, venue.getName(), - isPublic, leaderboardGroupIds, officialWebsiteURL, baseURL, sailorsInfoWebsiteURLs, eventImages, - eventVideos, windFinderReviewedSpotCollectionIds)); + getService().apply(new UpdateEvent(eventId, eventName, eventDescription, startTimePoint, endTimePoint, + venue.getName(), isPublic, leaderboardGroupIds, officialWebsiteURL, baseURL, sailorsInfoWebsiteURLs, + eventImages, eventVideos, windFinderReviewedSpotCollectionIds)); return getEventById(eventId, false); } @Override public EventDTO createEvent(String eventName, String eventDescription, Date startDate, Date endDate, String venue, boolean isPublic, List courseAreaNames, String officialWebsiteURLAsString, String baseURLAsString, - Map sailorsInfoWebsiteURLsByLocaleName, Iterable images, Iterable videos, Iterable leaderboardGroupIds) - throws MalformedURLException { + Map sailorsInfoWebsiteURLsByLocaleName, Iterable images, + Iterable videos, Iterable leaderboardGroupIds) throws MalformedURLException { UUID eventUuid = UUID.randomUUID(); - TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; - TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; + TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; + TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; URL officialWebsiteURL = officialWebsiteURLAsString != null ? new URL(officialWebsiteURLAsString) : null; URL baseURL = baseURLAsString != null ? new URL(baseURLAsString) : null; Map sailorsInfoWebsiteURLs = convertToLocalesAndUrls(sailorsInfoWebsiteURLsByLocaleName); - + List eventImages = convertToImages(images); List eventVideos = convertToVideos(videos); - getService().apply( - new CreateEvent(eventName, eventDescription, startTimePoint, endTimePoint, venue, isPublic, eventUuid, - officialWebsiteURL, baseURL, sailorsInfoWebsiteURLs, eventImages, eventVideos, leaderboardGroupIds)); + getService().apply(new CreateEvent(eventName, eventDescription, startTimePoint, endTimePoint, venue, isPublic, + eventUuid, officialWebsiteURL, baseURL, sailorsInfoWebsiteURLs, eventImages, eventVideos, + leaderboardGroupIds)); createCourseAreas(eventUuid, courseAreaNames.toArray(new String[courseAreaNames.size()])); return getEventById(eventUuid, false); } @@ -3976,11 +4269,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return imageDimensions; } - + @Override public void createCourseAreas(UUID eventId, String[] courseAreaNames) { final UUID[] courseAreaIDs = new UUID[courseAreaNames.length]; - for (int i=0; i sailorsInfoWebsiteEntry : event.getSailorsInfoWebsiteURLs().entrySet()) { - eventDTO.setSailorsInfoWebsiteURL(sailorsInfoWebsiteEntry.getKey() == null ? null : sailorsInfoWebsiteEntry - .getKey().toLanguageTag(), sailorsInfoWebsiteEntry.getValue().toExternalForm()); + eventDTO.setSailorsInfoWebsiteURL( + sailorsInfoWebsiteEntry.getKey() == null ? null : sailorsInfoWebsiteEntry.getKey().toLanguageTag(), + sailorsInfoWebsiteEntry.getValue().toExternalForm()); } for (ImageDescriptor image : event.getImages()) { eventDTO.addImage(convertToImageDTO(image)); @@ -4074,7 +4369,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (ImageDTO image : images) { try { eventImages.add(convertToImage(image)); - } catch(Exception e) { + } catch (Exception e) { // broken URLs are not being stored } } @@ -4086,7 +4381,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (VideoDTO video : videos) { try { eventVideos.add(convertToVideo(video)); - } catch(Exception e) { + } catch (Exception e) { // broken URLs are not being stored } } @@ -4099,7 +4394,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (entry.getValue() != null) { try { eventURLs.put(toLocale(entry.getKey()), new URL(entry.getValue())); - } catch(Exception e) { + } catch (Exception e) { // broken URLs or Locales are not being stored } } @@ -4108,7 +4403,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } private ImageDescriptor convertToImage(ImageDTO image) throws MalformedURLException { - ImageDescriptor result = new ImageDescriptorImpl(new URL(image.getSourceRef()), new MillisecondsTimePoint(image.getCreatedAtDate())); + ImageDescriptor result = new ImageDescriptorImpl(new URL(image.getSourceRef()), + new MillisecondsTimePoint(image.getCreatedAtDate())); result.setCopyright(image.getCopyright()); result.setTitle(image.getTitle()); result.setSubtitle(image.getSubtitle()); @@ -4123,17 +4419,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private VideoDescriptor convertToVideo(VideoDTO video) throws MalformedURLException { MimeType mimeType = video.getMimeType(); - if(mimeType == null || mimeType == MimeType.unknown) { + if (mimeType == null || mimeType == MimeType.unknown) { mimeType = MediaUtils.detectMimeTypeFromUrl(video.getSourceRef()); } - VideoDescriptor result = new VideoDescriptorImpl(new URL(video.getSourceRef()), mimeType, new MillisecondsTimePoint(video.getCreatedAtDate())); + VideoDescriptor result = new VideoDescriptorImpl(new URL(video.getSourceRef()), mimeType, + new MillisecondsTimePoint(video.getCreatedAtDate())); result.setCopyright(video.getCopyright()); result.setTitle(video.getTitle()); result.setSubtitle(video.getSubtitle()); result.setCopyright(video.getCopyright()); result.setLengthInSeconds(video.getLengthInSeconds()); - if(video.getThumbnailRef() != null && !video.getThumbnailRef().isEmpty()) - result.setThumbnailURL(new URL(video.getThumbnailRef())); + if (video.getThumbnailRef() != null && !video.getThumbnailRef().isEmpty()) + result.setThumbnailURL(new URL(video.getThumbnailRef())); result.setLocale(toLocale(video.getLocale())); for (String tag : video.getTags()) { result.addTag(tag); @@ -4142,7 +4439,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } private ImageDTO convertToImageDTO(ImageDescriptor image) { - ImageDTO result = new ImageDTO(image.getURL().toString(), image.getCreatedAtDate() != null ? image.getCreatedAtDate().asDate() : null); + ImageDTO result = new ImageDTO(image.getURL().toString(), + image.getCreatedAtDate() != null ? image.getCreatedAtDate().asDate() : null); result.setCopyright(image.getCopyright()); result.setTitle(image.getTitle()); result.setSubtitle(image.getSubtitle()); @@ -4150,7 +4448,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S result.setSizeInPx(image.getWidthInPx(), image.getHeightInPx()); result.setLocale(toLocaleName(image.getLocale())); List tags = new ArrayList(); - for(String tag: image.getTags()) { + for (String tag : image.getTags()) { tags.add(tag); } result.setTags(tags); @@ -4158,7 +4456,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } private VideoDTO convertToVideoDTO(VideoDescriptor video) { - VideoDTO result = new VideoDTO(video.getURL().toString(), video.getMimeType(), + VideoDTO result = new VideoDTO(video.getURL().toString(), video.getMimeType(), video.getCreatedAtDate() != null ? video.getCreatedAtDate().asDate() : null); result.setCopyright(video.getCopyright()); result.setTitle(video.getTitle()); @@ -4167,22 +4465,22 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S result.setLengthInSeconds(video.getLengthInSeconds()); result.setLocale(toLocaleName(video.getLocale())); List tags = new ArrayList(); - for(String tag: video.getTags()) { + for (String tag : video.getTags()) { tags.add(tag); } result.setTags(tags); return result; } - + private Locale toLocale(String localeName) { - if(localeName == null || localeName.isEmpty()) { + if (localeName == null || localeName.isEmpty()) { return null; } return Locale.forLanguageTag(localeName); } - + private String toLocaleName(Locale locale) { - if(locale == null) { + if (locale == null) { return null; } return locale.toString(); @@ -4197,7 +4495,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S eventDTO.venue.getCourseAreas().add(courseAreaDTO); } for (LeaderboardGroup lg : event.getLeaderboardGroups()) { - eventDTO.addLeaderboardGroup(convertToLeaderboardGroupDTO(lg, /* withGeoLocationData */ false, withStatisticalData)); + eventDTO.addLeaderboardGroup( + convertToLeaderboardGroupDTO(lg, /* withGeoLocationData */ false, withStatisticalData)); } eventDTO.setWindFinderReviewedSpotsCollection(event.getWindFinderReviewedSpotsCollectionIds()); final WindFinderTrackerFactory windFinderTrackerFactory = windFinderTrackerFactoryServiceTracker.getService(); @@ -4213,27 +4512,29 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S courseAreaDTO.id = courseArea.getId(); return courseAreaDTO; } - + /** for backward compatibility with the regatta overview */ @Override public List getRegattaStructureForEvent(UUID eventId) { List raceGroups = new ArrayList(); Event event = getService().getEvent(eventId); Map leaderboardWithLeaderboardGroups = new HashMap(); - for(LeaderboardGroup leaderboardGroup: event.getLeaderboardGroups()) { - for(Leaderboard leaderboard: leaderboardGroup.getLeaderboards()) { + for (LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { + for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { leaderboardWithLeaderboardGroups.put(leaderboard, leaderboardGroup); } } if (event != null) { for (CourseArea courseArea : event.getVenue().getCourseAreas()) { for (Leaderboard leaderboard : getService().getLeaderboards().values()) { - if (leaderboard.getDefaultCourseArea() != null && leaderboard.getDefaultCourseArea() == courseArea) { + if (leaderboard.getDefaultCourseArea() != null + && leaderboard.getDefaultCourseArea() == courseArea) { RaceGroupDTO raceGroup = new RaceGroupDTO(leaderboard.getName()); raceGroup.courseAreaIdAsString = courseArea.getId().toString(); raceGroup.displayName = getRegattaNameFromLeaderboard(leaderboard); - if(leaderboardWithLeaderboardGroups.containsKey(leaderboard)) { - raceGroup.leaderboardGroupName = leaderboardWithLeaderboardGroups.get(leaderboard).getName(); + if (leaderboardWithLeaderboardGroups.containsKey(leaderboard)) { + raceGroup.leaderboardGroupName = leaderboardWithLeaderboardGroups.get(leaderboard) + .getName(); } if (leaderboard instanceof RegattaLeaderboard) { RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; @@ -4241,13 +4542,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S RaceGroupSeriesDTO seriesDTO = new RaceGroupSeriesDTO(series.getName()); raceGroup.getSeries().add(seriesDTO); for (Fleet fleet : series.getFleets()) { - FleetDTO fleetDTO = new FleetDTO(fleet.getName(), fleet.getOrdering(), fleet.getColor()); + FleetDTO fleetDTO = new FleetDTO(fleet.getName(), fleet.getOrdering(), + fleet.getColor()); seriesDTO.getFleets().add(fleetDTO); } seriesDTO.getRaceColumns().addAll(convertToRaceColumnDTOs(series.getRaceColumns())); } } else { - RaceGroupSeriesDTO seriesDTO = new RaceGroupSeriesDTO(LeaderboardNameConstants.DEFAULT_SERIES_NAME); + RaceGroupSeriesDTO seriesDTO = new RaceGroupSeriesDTO( + LeaderboardNameConstants.DEFAULT_SERIES_NAME); raceGroup.getSeries().add(seriesDTO); FleetDTO fleetDTO = new FleetDTO(LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null); seriesDTO.getFleets().add(fleetDTO); @@ -4267,24 +4570,25 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S List raceGroups = new ArrayList(); Event event = getService().getEvent(eventId); Map leaderboardWithLeaderboardGroups = new HashMap(); - for(LeaderboardGroup leaderboardGroup: event.getLeaderboardGroups()) { - for(Leaderboard leaderboard: leaderboardGroup.getLeaderboards()) { + for (LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { + for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { leaderboardWithLeaderboardGroups.put(leaderboard, leaderboardGroup); } } if (event != null) { - for(LeaderboardGroup leaderboardGroup: event.getLeaderboardGroups()) { - for(Leaderboard leaderboard: leaderboardGroup.getLeaderboards()) { + for (LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { + for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { RaceGroupDTO raceGroup = new RaceGroupDTO(leaderboard.getName()); for (CourseArea courseArea : event.getVenue().getCourseAreas()) { - if (leaderboard.getDefaultCourseArea() != null && leaderboard.getDefaultCourseArea() == courseArea) { + if (leaderboard.getDefaultCourseArea() != null + && leaderboard.getDefaultCourseArea() == courseArea) { raceGroup.courseAreaIdAsString = courseArea.getId().toString(); break; } } raceGroup.displayName = getRegattaNameFromLeaderboard(leaderboard); - if(leaderboardWithLeaderboardGroups.containsKey(leaderboard)) { - raceGroup.leaderboardGroupName = leaderboardWithLeaderboardGroups.get(leaderboard).getName(); + if (leaderboardWithLeaderboardGroups.containsKey(leaderboard)) { + raceGroup.leaderboardGroupName = leaderboardWithLeaderboardGroups.get(leaderboard).getName(); } if (leaderboard instanceof RegattaLeaderboard) { RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; @@ -4293,20 +4597,22 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S RaceGroupSeriesDTO seriesDTO = new RaceGroupSeriesDTO(series.getName()); raceGroup.getSeries().add(seriesDTO); for (Fleet fleet : series.getFleets()) { - FleetDTO fleetDTO = new FleetDTO(fleet.getName(), fleet.getOrdering(), fleet.getColor()); + FleetDTO fleetDTO = new FleetDTO(fleet.getName(), fleet.getOrdering(), + fleet.getColor()); seriesDTO.getFleets().add(fleetDTO); } seriesDTO.getRaceColumns().addAll(convertToRaceColumnDTOs(series.getRaceColumns())); } } else { - RaceGroupSeriesDTO seriesDTO = new RaceGroupSeriesDTO(LeaderboardNameConstants.DEFAULT_SERIES_NAME); + RaceGroupSeriesDTO seriesDTO = new RaceGroupSeriesDTO( + LeaderboardNameConstants.DEFAULT_SERIES_NAME); raceGroup.getSeries().add(seriesDTO); FleetDTO fleetDTO = new FleetDTO(LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null); seriesDTO.getFleets().add(fleetDTO); seriesDTO.getRaceColumns().addAll(convertToRaceColumnDTOs(leaderboard.getRaceColumns())); BoatClass boatClass = leaderboard.getBoatClass(); - raceGroup.boatClass = boatClass != null ? boatClass.getDisplayName(): null; + raceGroup.boatClass = boatClass != null ? boatClass.getDisplayName() : null; } raceGroups.add(raceGroup); } @@ -4314,16 +4620,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return raceGroups; } - + /** - * The name of the regatta to be shown on the regatta overview webpage is retrieved from the name of the {@link Leaderboard}. Since regattas are - * not always represented by a {@link Regatta} object in the Sailing Suite but need to be shown on the regatta overview page, the leaderboard is - * used as the representative of the sailing regatta. When a display name is set for a leaderboard, this name is favored against the (mostly technical) - * regatta name as the display name represents the publicly visible name of the regatta. - *
- * When the leaderboard is a {@link RegattaLeaderboard} the name of the {@link Regatta} is used, otherwise the leaderboard - * is a {@link FlexibleLeaderboard} and it's name is used as the last option. - * @param leaderboard The {@link Leaderboard} from which the name is be retrieved + * The name of the regatta to be shown on the regatta overview webpage is retrieved from the name of the + * {@link Leaderboard}. Since regattas are not always represented by a {@link Regatta} object in the Sailing Suite + * but need to be shown on the regatta overview page, the leaderboard is used as the representative of the sailing + * regatta. When a display name is set for a leaderboard, this name is favored against the (mostly technical) + * regatta name as the display name represents the publicly visible name of the regatta.
+ * When the leaderboard is a {@link RegattaLeaderboard} the name of the {@link Regatta} is used, otherwise the + * leaderboard is a {@link FlexibleLeaderboard} and it's name is used as the last option. + * + * @param leaderboard + * The {@link Leaderboard} from which the name is be retrieved * @return the name of the regatta to be shown on the regatta overview page */ private String getRegattaNameFromLeaderboard(Leaderboard leaderboard) { @@ -4347,35 +4655,38 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S removeRegatta(regatta); } } - + @Override public void removeRegatta(RegattaIdentifier regattaIdentifier) { getService().apply(new RemoveRegatta(regattaIdentifier)); } - + @Override public void removeSeries(RegattaIdentifier identifier, String seriesName) { getService().apply(new RemoveSeries(identifier, seriesName)); } private RaceColumnInSeriesDTO convertToRaceColumnInSeriesDTO(RaceColumnInSeries raceColumnInSeries) { - RaceColumnInSeriesDTO raceColumnInSeriesDTO = new RaceColumnInSeriesDTO(raceColumnInSeries.getSeries().getName(), - raceColumnInSeries.getRegatta().getName()); + RaceColumnInSeriesDTO raceColumnInSeriesDTO = new RaceColumnInSeriesDTO( + raceColumnInSeries.getSeries().getName(), raceColumnInSeries.getRegatta().getName()); fillRaceColumnDTO(raceColumnInSeries, raceColumnInSeriesDTO); return raceColumnInSeriesDTO; } @Override - public void updateRegatta(RegattaIdentifier regattaName, Date startDate, Date endDate, UUID defaultCourseAreaUuid, - RegattaConfigurationDTO configurationDTO, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes) { + public void updateRegatta(RegattaIdentifier regattaName, Date startDate, Date endDate, UUID defaultCourseAreaUuid, + RegattaConfigurationDTO configurationDTO, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, + boolean controlTrackingFromStartAndFinishTimes) { Regatta regatta = getService().getRegatta(regattaName); if (regatta != null) { - SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); + SecurityUtils.getSubject() + .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); } - TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; - TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; - getService().apply(new UpdateSpecificRegatta(regattaName, startTimePoint, endTimePoint, - defaultCourseAreaUuid, convertToRegattaConfiguration(configurationDTO), buoyZoneRadiusInHullLengths, useStartTimeInference, controlTrackingFromStartAndFinishTimes)); + TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; + TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; + getService().apply(new UpdateSpecificRegatta(regattaName, startTimePoint, endTimePoint, defaultCourseAreaUuid, + convertToRegattaConfiguration(configurationDTO), buoyZoneRadiusInHullLengths, useStartTimeInference, + controlTrackingFromStartAndFinishTimes)); } @Override @@ -4383,41 +4694,45 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S List> columnNamesWithInsertIndex) { Regatta regatta = getService().getRegatta(regattaIdentifier); if (regatta != null) { - SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); + SecurityUtils.getSubject() + .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); } List result = new ArrayList(); for (Pair columnNameAndInsertIndex : columnNamesWithInsertIndex) { - RaceColumnInSeries raceColumnInSeries = getService().apply( - new AddColumnToSeries(columnNameAndInsertIndex.getB(), regattaIdentifier, seriesName, columnNameAndInsertIndex.getA())); + RaceColumnInSeries raceColumnInSeries = getService().apply(new AddColumnToSeries( + columnNameAndInsertIndex.getB(), regattaIdentifier, seriesName, columnNameAndInsertIndex.getA())); if (raceColumnInSeries != null) { result.add(convertToRaceColumnInSeriesDTO(raceColumnInSeries)); } } return result; } - + @Override - public void updateSeries(RegattaIdentifier regattaIdentifier, String seriesName, String newSeriesName, boolean isMedal, boolean isFleetsCanRunInParallel, - int[] resultDiscardingThresholds, boolean startsWithZeroScore, - boolean firstColumnIsNonDiscardableCarryForward, boolean hasSplitFleetContiguousScoring, - Integer maximumNumberOfDiscards, List fleets) { + public void updateSeries(RegattaIdentifier regattaIdentifier, String seriesName, String newSeriesName, + boolean isMedal, boolean isFleetsCanRunInParallel, int[] resultDiscardingThresholds, + boolean startsWithZeroScore, boolean firstColumnIsNonDiscardableCarryForward, + boolean hasSplitFleetContiguousScoring, Integer maximumNumberOfDiscards, List fleets) { Regatta regatta = getService().getRegatta(regattaIdentifier); if (regatta != null) { - SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); + SecurityUtils.getSubject() + .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); } - getService().apply( - new UpdateSeries(regattaIdentifier, seriesName, newSeriesName, isMedal, isFleetsCanRunInParallel, resultDiscardingThresholds, - startsWithZeroScore, firstColumnIsNonDiscardableCarryForward, hasSplitFleetContiguousScoring, - maximumNumberOfDiscards, fleets)); + getService() + .apply(new UpdateSeries(regattaIdentifier, seriesName, newSeriesName, isMedal, isFleetsCanRunInParallel, + resultDiscardingThresholds, startsWithZeroScore, firstColumnIsNonDiscardableCarryForward, + hasSplitFleetContiguousScoring, maximumNumberOfDiscards, fleets)); } @Override - public void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List columnNames) { + public void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, + List columnNames) { Regatta regatta = getService().getRegatta(regattaIdentifier); if (regatta != null) { - SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); + SecurityUtils.getSubject() + .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); } - for(String columnName: columnNames) { + for (String columnName : columnNames) { getService().apply(new RemoveColumnFromSeries(regattaIdentifier, seriesName, columnName)); } } @@ -4426,7 +4741,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public void moveRaceColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) { Regatta regatta = getService().getRegatta(regattaIdentifier); if (regatta != null) { - SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); + SecurityUtils.getSubject() + .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); } getService().apply(new MoveColumnInSeriesUp(regattaIdentifier, seriesName, columnName)); } @@ -4435,28 +4751,32 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public void moveRaceColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) { Regatta regatta = getService().getRegatta(regattaIdentifier); if (regatta != null) { - SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); + SecurityUtils.getSubject() + .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); } getService().apply(new MoveColumnInSeriesDown(regattaIdentifier, seriesName, columnName)); } @Override - public RegattaDTO createRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, Date startDate, Date endDate, - RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, - boolean persistent, ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, - boolean controlTrackingFromStartAndFinishTimes, RankingMetrics rankingMetricType) { - SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.CREATE, regattaName)); - TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; - TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; + public RegattaDTO createRegatta(String regattaName, String boatClassName, + boolean canBoatsOfCompetitorsChangePerRace, Date startDate, Date endDate, + RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, boolean persistent, + ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId, Double buoyZoneRadiusInHullLengths, + boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, + RankingMetrics rankingMetricType) { + SecurityUtils.getSubject() + .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.CREATE, regattaName)); + TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; + TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; Regatta regatta = getService().apply( - new AddSpecificRegatta( - regattaName, boatClassName, canBoatsOfCompetitorsChangePerRace, startTimePoint, endTimePoint, UUID.randomUUID(), - seriesNamesWithFleetNamesAndFleetOrderingAndMedal, - persistent, baseDomainFactory.createScoringScheme(scoringSchemeType), defaultCourseAreaId, buoyZoneRadiusInHullLengths, useStartTimeInference, - controlTrackingFromStartAndFinishTimes, rankingMetricType)); + new AddSpecificRegatta(regattaName, boatClassName, canBoatsOfCompetitorsChangePerRace, startTimePoint, + endTimePoint, UUID.randomUUID(), seriesNamesWithFleetNamesAndFleetOrderingAndMedal, persistent, + baseDomainFactory.createScoringScheme(scoringSchemeType), defaultCourseAreaId, + buoyZoneRadiusInHullLengths, useStartTimeInference, controlTrackingFromStartAndFinishTimes, + rankingMetricType)); return convertToRegattaDTO(regatta); } - + @Override public RegattaScoreCorrectionDTO getScoreCorrections(String scoreCorrectionProviderName, String eventName, String boatClassName, Date timePointWhenResultPublished) throws Exception { @@ -4489,7 +4809,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return new ScoreCorrectionEntryDTO(scoreCorrectionForCompetitor.getPoints(), scoreCorrectionForCompetitor.isDiscarded(), scoreCorrectionForCompetitor.getMaxPointsReason()); } - + @Override public List> getUrlResultProviderNamesAndOptionalSampleURL() { List> result = new ArrayList<>(); @@ -4524,18 +4844,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S ServerConfigurationDTO result = new ServerConfigurationDTO(sailingServerConfiguration.isStandaloneServer()); return result; } - + @Override public void updateServerConfiguration(ServerConfigurationDTO serverConfiguration) { - SailingServerConfiguration newServerConfiguration = new SailingServerConfigurationImpl(serverConfiguration.isStandaloneServer()); + SailingServerConfiguration newServerConfiguration = new SailingServerConfigurationImpl( + serverConfiguration.isStandaloneServer()); getService().apply(new UpdateServerConfiguration(newServerConfiguration)); } @Override public List getRemoteSailingServerReferences() { List result = new ArrayList(); - for (Entry, Exception>> remoteSailingServerRefAndItsCachedEvent : - getService().getPublicEventsOfAllSailingServers().entrySet()) { + for (Entry, Exception>> remoteSailingServerRefAndItsCachedEvent : getService() + .getPublicEventsOfAllSailingServers().entrySet()) { RemoteSailingServerReferenceDTO dto = createRemoteSailingServerReferenceDTO( remoteSailingServerRefAndItsCachedEvent.getKey(), remoteSailingServerRefAndItsCachedEvent.getValue()); @@ -4552,7 +4873,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public RemoteSailingServerReferenceDTO addRemoteSailingServerReference(RemoteSailingServerReferenceDTO sailingServer) throws MalformedURLException { + public RemoteSailingServerReferenceDTO addRemoteSailingServerReference( + RemoteSailingServerReferenceDTO sailingServer) throws MalformedURLException { final String expandedURL; if (sailingServer.getUrl().contains("//")) { expandedURL = sailingServer.getUrl(); @@ -4560,10 +4882,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S expandedURL = "http://" + sailingServer.getUrl(); } URL serverURL = new URL(expandedURL); - RemoteSailingServerReference serverRef = getService().apply(new AddRemoteSailingServerReference(sailingServer.getName(), serverURL)); - com.sap.sse.common.Util.Pair, Exception> eventsOrException = getService().updateRemoteServerEventCacheSynchronously(serverRef); + RemoteSailingServerReference serverRef = getService() + .apply(new AddRemoteSailingServerReference(sailingServer.getName(), serverURL)); + com.sap.sse.common.Util.Pair, Exception> eventsOrException = getService() + .updateRemoteServerEventCacheSynchronously(serverRef); return createRemoteSailingServerReferenceDTO(serverRef, eventsOrException); - + } @Override @@ -4602,13 +4926,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private ResultUrlRegistry getResultUrlRegistry() { return resultUrlRegistryServiceTracker.getService(); - } + } @Override public List getOverallLeaderboardNamesContaining(String leaderboardName) { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard == null) { - throw new IllegalArgumentException("Couldn't find leaderboard named "+leaderboardName); + throw new IllegalArgumentException("Couldn't find leaderboard named " + leaderboardName); } List result = new ArrayList(); for (Map.Entry leaderboardEntry : getService().getLeaderboards().entrySet()) { @@ -4624,7 +4948,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public List getPreviousSwissTimingArchiveConfigurations() { - Iterable configs = swissTimingAdapterPersistence.getSwissTimingArchiveConfigurations(); + Iterable configs = swissTimingAdapterPersistence + .getSwissTimingArchiveConfigurations(); List result = new ArrayList(); for (SwissTimingArchiveConfiguration stArchiveConfig : configs) { result.add(new SwissTimingArchiveConfigurationDTO(stArchiveConfig.getJsonUrl())); @@ -4634,8 +4959,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public void storeSwissTimingArchiveConfiguration(String swissTimingJsonUrl) { - swissTimingAdapterPersistence.storeSwissTimingArchiveConfiguration(swissTimingFactory.createSwissTimingArchiveConfiguration( - swissTimingJsonUrl)); + swissTimingAdapterPersistence.storeSwissTimingArchiveConfiguration( + swissTimingFactory.createSwissTimingArchiveConfiguration(swissTimingJsonUrl)); } protected com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory() { @@ -4644,18 +4969,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public List getRaceStateEntriesForLeaderboard(String leaderboardName, - boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, final List visibleRegattas) - throws NoWindException, InterruptedException, ExecutionException { + boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, + final List visibleRegattas) throws NoWindException, InterruptedException, ExecutionException { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - return getRaceStateEntriesForLeaderboard(leaderboard, showOnlyCurrentlyRunningRaces, showOnlyRacesOfSameDay, clientTimeZoneOffset, visibleRegattas); + return getRaceStateEntriesForLeaderboard(leaderboard, showOnlyCurrentlyRunningRaces, showOnlyRacesOfSameDay, + clientTimeZoneOffset, visibleRegattas); } /** - * The client's day starts at 00:00:00Z - clientTimeZoneOffset and ends at 23:59:59Z - clientTimeZoneOffset. + * The client's day starts at 00:00:00Z - clientTimeZoneOffset and ends at + * 23:59:59Z - clientTimeZoneOffset. */ private List getRaceStateEntriesForLeaderboard(Leaderboard leaderboard, - boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, final List visibleRegattas) - throws NoWindException, InterruptedException, ExecutionException { + boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, + final List visibleRegattas) throws NoWindException, InterruptedException, ExecutionException { List result = new ArrayList(); Calendar dayToCheck = Calendar.getInstance(); dayToCheck.setTime(new Date()); @@ -4663,7 +4990,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (leaderboard != null) { if (visibleRegattas != null && !visibleRegattas.contains(leaderboard.getName())) { return result; - } + } String regattaName = getRegattaNameFromLeaderboard(leaderboard); if (leaderboard instanceof RegattaLeaderboard) { RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; @@ -4680,7 +5007,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S result.addAll(getRegattaOverviewEntriesToBeShown(showOnlyCurrentlyRunningRaces, entriesPerFleet)); } - } else if(leaderboard instanceof FlexibleLeaderboard) { + } else if (leaderboard instanceof FlexibleLeaderboard) { BoatClass boatClass = null; for (TrackedRace trackedRace : leaderboard.getTrackedRaces()) { boatClass = trackedRace.getRace().getBoatClass(); @@ -4698,38 +5025,42 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return result; } - + private void createRegattaFromRegattaDTO(RegattaDTO regatta) { - SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.CREATE, regatta.getName())); - this.createRegatta(regatta.getName(), regatta.boatClass.getName(), regatta.canBoatsOfCompetitorsChangePerRace, regatta.startDate, regatta.endDate, - new RegattaCreationParametersDTO(getSeriesCreationParameters(regatta)), - true, regatta.scoringScheme, regatta.defaultCourseAreaUuid, regatta.buoyZoneRadiusInHullLengths, regatta.useStartTimeInference, - regatta.controlTrackingFromStartAndFinishTimes, regatta.rankingMetricType); + SecurityUtils.getSubject() + .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.CREATE, regatta.getName())); + this.createRegatta(regatta.getName(), regatta.boatClass.getName(), regatta.canBoatsOfCompetitorsChangePerRace, + regatta.startDate, regatta.endDate, + new RegattaCreationParametersDTO(getSeriesCreationParameters(regatta)), true, regatta.scoringScheme, + regatta.defaultCourseAreaUuid, regatta.buoyZoneRadiusInHullLengths, regatta.useStartTimeInference, + regatta.controlTrackingFromStartAndFinishTimes, regatta.rankingMetricType); } - + private SeriesParameters getSeriesParameters(SeriesDTO seriesDTO) { - SeriesParameters series = new SeriesParameters(false, false, false, null, seriesDTO.getMaximumNumberOfDiscards()); + SeriesParameters series = new SeriesParameters(false, false, false, null, + seriesDTO.getMaximumNumberOfDiscards()); series.setFirstColumnIsNonDiscardableCarryForward(seriesDTO.isFirstColumnIsNonDiscardableCarryForward()); series.setHasSplitFleetContiguousScoring(seriesDTO.hasSplitFleetContiguousScoring()); series.setStartswithZeroScore(seriesDTO.isStartsWithZeroScore()); series.setDiscardingThresholds(seriesDTO.getDiscardThresholds()); return series; } - + private LinkedHashMap getSeriesCreationParameters(RegattaDTO regattaDTO) { LinkedHashMap seriesCreationParams = new LinkedHashMap(); - for (SeriesDTO series : regattaDTO.series){ - SeriesParameters seriesParameters = getSeriesParameters(series); - seriesCreationParams.put(series.getName(), new SeriesCreationParametersDTO(series.getFleets(), - false, true, seriesParameters.isStartswithZeroScore(), seriesParameters.isFirstColumnIsNonDiscardableCarryForward(), - seriesParameters.getDiscardingThresholds(), seriesParameters.isHasSplitFleetContiguousScoring(), - seriesParameters.getMaximumNumberOfDiscards())); - } + for (SeriesDTO series : regattaDTO.series) { + SeriesParameters seriesParameters = getSeriesParameters(series); + seriesCreationParams.put(series.getName(), new SeriesCreationParametersDTO(series.getFleets(), false, true, + seriesParameters.isStartswithZeroScore(), + seriesParameters.isFirstColumnIsNonDiscardableCarryForward(), + seriesParameters.getDiscardingThresholds(), seriesParameters.isHasSplitFleetContiguousScoring(), + seriesParameters.getMaximumNumberOfDiscards())); + } return seriesCreationParams; } @Override - public Iterable getRegattas(String manage2SailJsonUrl) { + public Iterable getRegattas(String manage2SailJsonUrl) { StructureImporter structureImporter = new StructureImporter(new SetRacenumberFromSeries(), baseDomainFactory); Iterable parsedEvent = structureImporter.parseEvent(manage2SailJsonUrl); List regattaDTOs = new ArrayList(); @@ -4741,13 +5072,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** - * Uses {@link #addRaceColumnsToSeries} which also handles replication to update the regatta identified - * by regatta's {@link RegattaDTO#getRegattaIdentifier() identifier} with the race columns - * as specified by regatta. The domain regatta object is assumed to have no races associated - * when this method is called. + * Uses {@link #addRaceColumnsToSeries} which also handles replication to update the regatta identified by + * regatta's {@link RegattaDTO#getRegattaIdentifier() identifier} with the race columns as specified by + * regatta. The domain regatta object is assumed to have no races associated when this method is + * called. */ private void addRaceColumnsToRegattaSeries(RegattaDTO regatta) { - SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); + SecurityUtils.getSubject() + .checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName())); for (SeriesDTO series : regatta.series) { List> raceNamesAndInsertIndex = new ArrayList<>(); int insertIndex = 0; @@ -4760,7 +5092,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void createRegattaStructure(final Iterable regattas, final EventDTO newEvent) throws MalformedURLException { + public void createRegattaStructure(final Iterable regattas, final EventDTO newEvent) + throws MalformedURLException { final List leaderboardNames = new ArrayList(); for (RegattaDTO regatta : regattas) { createRegattaFromRegattaDTO(regatta); @@ -4771,11 +5104,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } createAndAddLeaderboardGroup(newEvent, leaderboardNames); - // TODO find a way to import the competitors for the selected regattas. You'll need the regattas as Iterable + // TODO find a way to import the competitors for the selected regattas. You'll need the regattas as + // Iterable // structureImporter.setCompetitors(regattas, ""); } - private void createAndAddLeaderboardGroup(final EventDTO newEvent, List leaderboardNames) throws MalformedURLException { + private void createAndAddLeaderboardGroup(final EventDTO newEvent, List leaderboardNames) + throws MalformedURLException { LeaderboardGroupDTO leaderboardGroupDTO = null; String description = ""; if (newEvent.getDescription() != null) { @@ -4786,29 +5121,31 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S // create Leaderboard Group if (getService().getLeaderboardGroupByName(eventName) == null) { - SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD_GROUP.getStringPermissionForObjects(Mode.CREATE, eventName)); + SecurityUtils.getSubject().checkPermission( + Permission.LEADERBOARD_GROUP.getStringPermissionForObjects(Mode.CREATE, eventName)); CreateLeaderboardGroup createLeaderboardGroupOp = new CreateLeaderboardGroup(eventName, description, eventName, false, leaderboardNames, null, null); leaderboardGroupDTO = convertToLeaderboardGroupDTO(getService().apply(createLeaderboardGroupOp), false, false); eventLeaderboardGroupUUIDs.add(leaderboardGroupDTO.getId()); } else { - updateLeaderboardGroup(eventName, eventName, newEvent.getDescription(), eventName, leaderboardNames, null, null); + updateLeaderboardGroup(eventName, eventName, newEvent.getDescription(), eventName, leaderboardNames, null, + null); leaderboardGroupDTO = getLeaderboardGroupByName(eventName, false); } for (LeaderboardGroupDTO lg : newEvent.getLeaderboardGroups()) { eventLeaderboardGroupUUIDs.add(lg.getId()); } updateEvent(newEvent.id, newEvent.getName(), description, newEvent.startDate, newEvent.endDate, newEvent.venue, - newEvent.isPublic, eventLeaderboardGroupUUIDs, newEvent.getOfficialWebsiteURL(), - newEvent.getBaseURL(), newEvent.getSailorsInfoWebsiteURLs(), newEvent.getImages(), newEvent.getVideos(), + newEvent.isPublic, eventLeaderboardGroupUUIDs, newEvent.getOfficialWebsiteURL(), newEvent.getBaseURL(), + newEvent.getSailorsInfoWebsiteURLs(), newEvent.getImages(), newEvent.getVideos(), newEvent.getWindFinderReviewedSpotsCollectionIds()); } - + @Override public List getRaceStateEntriesForRaceGroup(UUID eventId, List visibleCourseAreaIds, - List visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset) - throws NoWindException, InterruptedException, ExecutionException { + List visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, + Duration clientTimeZoneOffset) throws NoWindException, InterruptedException, ExecutionException { List result = new ArrayList(); Calendar dayToCheck = Calendar.getInstance(); dayToCheck.setTime(new Date()); @@ -4820,7 +5157,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final CourseArea leaderboardDefaultCourseArea = leaderboard.getDefaultCourseArea(); if (leaderboardDefaultCourseArea != null && leaderboardDefaultCourseArea.equals(courseArea)) { result.addAll(getRaceStateEntriesForLeaderboard(leaderboard.getName(), - showOnlyCurrentlyRunningRaces, showOnlyRacesOfSameDay, clientTimeZoneOffset, visibleRegattas)); + showOnlyCurrentlyRunningRaces, showOnlyRacesOfSameDay, clientTimeZoneOffset, + visibleRegattas)); } } } @@ -4830,7 +5168,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** - * The client's day starts at 00:00:00Z - clientTimeZoneOffset and ends at 23:59:59Z - clientTimeZoneOffset. + * The client's day starts at 00:00:00Z - clientTimeZoneOffset and ends at + * 23:59:59Z - clientTimeZoneOffset. */ private void getRegattaOverviewEntries(boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, Calendar dayToCheck, CourseArea courseArea, Leaderboard leaderboard, String boatClassName, @@ -4838,9 +5177,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Map> entriesPerFleet) { if (!raceColumn.isCarryForward()) { for (Fleet fleet : raceColumn.getFleets()) { - RegattaOverviewEntryDTO entry = createRegattaOverviewEntryDTO(courseArea, - leaderboard, boatClassName, regattaName, buyZoneRadius, seriesName, raceColumn, fleet, - showOnlyRacesOfSameDay, clientTimeZoneOffset, dayToCheck); + RegattaOverviewEntryDTO entry = createRegattaOverviewEntryDTO(courseArea, leaderboard, boatClassName, + regattaName, buyZoneRadius, seriesName, raceColumn, fleet, showOnlyRacesOfSameDay, + clientTimeZoneOffset, dayToCheck); if (entry != null) { addRegattaOverviewEntryToEntriesPerFleet(entriesPerFleet, fleet, entry); } @@ -4860,20 +5199,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (entry.raceInfo.lastStatus.equals(RaceLogRaceStatus.FINISHED)) { finishedEntries.add(entry); } else if (entry.raceInfo.lastStatus.equals(RaceLogRaceStatus.UNSCHEDULED)) { - //don't filter when the race is unscheduled and aborted before + // don't filter when the race is unscheduled and aborted before if (!entry.raceInfo.isRaceAbortedInPassBefore) { result.remove(entry); } - + } } } if (!finishedEntries.isEmpty()) { - //keep the last finished race in the list to be shown + // keep the last finished race in the list to be shown int indexOfLastElement = finishedEntries.size() - 1; finishedEntries.remove(indexOfLastElement); - - //... and remove all other finished races + + // ... and remove all other finished races result.removeAll(finishedEntries); } } @@ -4884,13 +5223,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private void addRegattaOverviewEntryToEntriesPerFleet(Map> entriesPerFleet, Fleet fleet, RegattaOverviewEntryDTO entry) { if (!entriesPerFleet.containsKey(fleet.getName())) { - entriesPerFleet.put(fleet.getName(), new ArrayList()); + entriesPerFleet.put(fleet.getName(), new ArrayList()); } entriesPerFleet.get(fleet.getName()).add(entry); } /** - * The client's day starts at 00:00:00Z - clientTimeZoneOffset and ends at 23:59:59Z - clientTimeZoneOffset. + * The client's day starts at 00:00:00Z - clientTimeZoneOffset and ends at + * 23:59:59Z - clientTimeZoneOffset. */ private RegattaOverviewEntryDTO createRegattaOverviewEntryDTO(CourseArea courseArea, Leaderboard leaderboard, String boatClassName, String regattaName, Distance buyZoneRadius, String seriesName, RaceColumn raceColumn, @@ -4933,7 +5273,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S try { getReplicationService().stopAllReplicas(); } catch (IOException e) { - logger.log(Level.SEVERE, "Exception trying to stop all replicas from receiving updates from this master", e); + logger.log(Level.SEVERE, "Exception trying to stop all replicas from receiving updates from this master", + e); throw new RuntimeException(e); } } @@ -4944,7 +5285,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S try { getReplicationService().unregisterReplica(uuid); } catch (IOException e) { - logger.log(Level.SEVERE, "Exception trying to unregister replica with UUID "+uuid, e); + logger.log(Level.SEVERE, "Exception trying to unregister replica with UUID " + uuid, e); throw new RuntimeException(e); } } @@ -4958,16 +5299,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public RaceLogDTO getRaceLog(String leaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet) { RaceLogDTO result = null; RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnDTO.getName(), fleet.getName()); - if(raceLog != null) { + if (raceLog != null) { List entries = new ArrayList(); - result = new RaceLogDTO(leaderboardName, raceColumnDTO.getName(), fleet.getName(), raceLog.getCurrentPassId(), entries); + result = new RaceLogDTO(leaderboardName, raceColumnDTO.getName(), fleet.getName(), + raceLog.getCurrentPassId(), entries); raceLog.lockForRead(); try { - for(RaceLogEvent raceLogEvent: raceLog.getRawFixes()) { - RaceLogEventDTO entry = new RaceLogEventDTO(raceLogEvent.getPassId(), - raceLogEvent.getAuthor().getName(), raceLogEvent.getAuthor().getPriority(), + for (RaceLogEvent raceLogEvent : raceLog.getRawFixes()) { + RaceLogEventDTO entry = new RaceLogEventDTO(raceLogEvent.getPassId(), + raceLogEvent.getAuthor().getName(), raceLogEvent.getAuthor().getPriority(), raceLogEvent.getCreatedAt() != null ? raceLogEvent.getCreatedAt().asDate() : null, - raceLogEvent.getLogicalTimePoint() != null ? raceLogEvent.getLogicalTimePoint().asDate() : null, + raceLogEvent.getLogicalTimePoint() != null ? raceLogEvent.getLogicalTimePoint().asDate() + : null, raceLogEvent.getClass().getSimpleName(), raceLogEvent.getShortInfo()); entries.add(entry); } @@ -4987,11 +5330,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S result = new RegattaLogDTO(leaderboardName, entries); regattaLog.lockForRead(); try { - for(RegattaLogEvent raceLogEvent: regattaLog.getRawFixes()) { - RegattaLogEventDTO entry = new RegattaLogEventDTO( - raceLogEvent.getAuthor().getName(), raceLogEvent.getAuthor().getPriority(), + for (RegattaLogEvent raceLogEvent : regattaLog.getRawFixes()) { + RegattaLogEventDTO entry = new RegattaLogEventDTO(raceLogEvent.getAuthor().getName(), + raceLogEvent.getAuthor().getPriority(), raceLogEvent.getCreatedAt() != null ? raceLogEvent.getCreatedAt().asDate() : null, - raceLogEvent.getLogicalTimePoint() != null ? raceLogEvent.getLogicalTimePoint().asDate() : null, + raceLogEvent.getLogicalTimePoint() != null ? raceLogEvent.getLogicalTimePoint().asDate() + : null, raceLogEvent.getClass().getSimpleName(), raceLogEvent.getShortInfo()); entries.add(entry); } @@ -5023,7 +5367,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return names; } catch (Exception e) { - throw new RuntimeException(e); + throw new RuntimeException(e); } finally { // close the connection if (connection != null && connection instanceof HttpURLConnection) { @@ -5043,9 +5387,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S * Strips off trailing slash and replaces an omitted or unknown protocol by HTTP */ private URL createBaseUrl(String urlAsString) throws MalformedURLException { - final String urlAsStringWithTrailingSlashRemoved = urlAsString == null ? - null : urlAsString.length()>0 && urlAsString.charAt(urlAsString.length()-1)=='/' ? - urlAsString.substring(0, urlAsString.length()-1) : urlAsString; + final String urlAsStringWithTrailingSlashRemoved = urlAsString == null ? null + : urlAsString.length() > 0 && urlAsString.charAt(urlAsString.length() - 1) == '/' + ? urlAsString.substring(0, urlAsString.length() - 1) + : urlAsString; URL url; try { url = new URL(urlAsStringWithTrailingSlashRemoved); @@ -5064,7 +5409,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public UUID importMasterData(final String urlAsString, final String[] groupNames, final boolean override, final boolean compress, final boolean exportWind, final boolean exportDeviceConfigurations) { final UUID importOperationId = UUID.randomUUID(); - getService().createOrUpdateDataImportProgressWithReplication(importOperationId, 0.0, DataImportSubProgress.INIT, 0.0); + getService().createOrUpdateDataImportProgressWithReplication(importOperationId, 0.0, DataImportSubProgress.INIT, + 0.0); // Create a progress indicator for as long as the server gets data from the other server. // As soon as the server starts the import operation, a progress object will be built on every server Runnable masterDataImportTask = new Runnable() { @@ -5088,7 +5434,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S serverAddress = createUrl(base, path, query); // the response can take a very long time for MDI that include foiling data or such connection = HttpUrlConnectionHelper.redirectConnection(serverAddress, Duration.ONE_HOUR.times(2)); - getService().createOrUpdateDataImportProgressWithReplication(importOperationId, 0.02, + getService().createOrUpdateDataImportProgressWithReplication(importOperationId, 0.02, DataImportSubProgress.CONNECTION_ESTABLISH, 0.5); if (compress) { InputStream timeoutExtendingInputStream = new TimeoutExtendingInputStream( @@ -5103,13 +5449,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } catch (Throwable e) { // do not assume that RuntimeException is logged properly logger.log(Level.SEVERE, e.getMessage(), e); - getService() - .setDataImportFailedWithReplication( - importOperationId, - e.getMessage() - + "\n\nHave you checked if the" - + " versions (commit-wise) of the importing and exporting servers are compatible with each other? " - + "If the error still occurs, when both servers are running the same version, please report the problem."); + getService().setDataImportFailedWithReplication(importOperationId, e.getMessage() + + "\n\nHave you checked if the" + + " versions (commit-wise) of the importing and exporting servers are compatible with each other? " + + "If the error still occurs, when both servers are running the same version, please report the problem."); throw new RuntimeException(e); } finally { // close the connection, set all objects to null @@ -5133,7 +5476,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S executor.execute(masterDataImportTask); return importOperationId; } - + private URL createUrl(URL base, String pathWithLeadingSlash, String query) throws Exception { URL url; if (query != null) { @@ -5153,20 +5496,21 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return 0; } - private String createLeaderboardQuery(String[] groupNames, boolean compress, boolean exportWind, boolean exportDeviceConfigurations) - throws UnsupportedEncodingException { + private String createLeaderboardQuery(String[] groupNames, boolean compress, boolean exportWind, + boolean exportDeviceConfigurations) throws UnsupportedEncodingException { StringBuffer queryStringBuffer = new StringBuffer(""); for (int i = 0; i < groupNames.length; i++) { String encodedGroupName = URLEncoder.encode(groupNames[i], "UTF-8"); queryStringBuffer.append("names[]=" + encodedGroupName + "&"); } - queryStringBuffer.append(String.format("compress=%s&exportWind=%s&exportDeviceConfigs=%s", compress, - exportWind, exportDeviceConfigurations)); + queryStringBuffer.append(String.format("compress=%s&exportWind=%s&exportDeviceConfigs=%s", compress, exportWind, + exportDeviceConfigurations)); return queryStringBuffer.toString(); } @Override - public Iterable getCompetitors(boolean filterCompetitorsWithBoat, boolean filterCompetitorsWithoutBoat) { + public Iterable getCompetitors(boolean filterCompetitorsWithBoat, + boolean filterCompetitorsWithoutBoat) { Iterable result; CompetitorAndBoatStore competitorStore = getService().getBaseDomainFactory().getCompetitorAndBoatStore(); if (filterCompetitorsWithBoat == false && filterCompetitorsWithoutBoat == false) { @@ -5188,11 +5532,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public Map getCompetitorsAndBoatsOfRace(String leaderboardName, String raceColumnName, String fleetName) { - Map competitorsAndBoats = getService().getCompetitorToBoatMappingsForRace(leaderboardName, raceColumnName, fleetName); + public Map getCompetitorsAndBoatsOfRace(String leaderboardName, + String raceColumnName, String fleetName) { + Map competitorsAndBoats = getService().getCompetitorToBoatMappingsForRace(leaderboardName, + raceColumnName, fleetName); return baseDomainFactory.convertToCompetitorAndBoatDTOs(competitorsAndBoats); } - + @Override public List addOrUpdateCompetitors(List competitors) throws URISyntaxException { final List result = new ArrayList<>(); @@ -5206,11 +5552,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return result; } - private CompetitorWithBoat addOrUpdateCompetitorWithBoatInternal(CompetitorWithBoatDTO competitor) throws URISyntaxException { + private CompetitorWithBoat addOrUpdateCompetitorWithBoatInternal(CompetitorWithBoatDTO competitor) + throws URISyntaxException { CompetitorWithBoat result; - CompetitorWithBoat existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorWithBoatByIdAsString(competitor.getIdAsString()); - Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null : - getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode()); + CompetitorWithBoat existingCompetitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorWithBoatByIdAsString(competitor.getIdAsString()); + Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null + || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null + : getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode()); if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) { // new competitor UUID competitorUUID = UUID.randomUUID(); @@ -5218,52 +5567,49 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null); // new boat DynamicBoat boat = (DynamicBoat) addOrUpdateBoatInternal(competitor.getBoat()); - result = getBaseDomainFactory().getOrCreateCompetitorWithBoat(competitorUUID, competitor.getName(), competitor.getShortName(), - competitor.getColor(), competitor.getEmail(), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, - competitor.getTimeOnTimeFactor(), - competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag(), boat); - + result = getBaseDomainFactory().getOrCreateCompetitorWithBoat(competitorUUID, competitor.getName(), + competitor.getShortName(), competitor.getColor(), competitor.getEmail(), + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, + competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), + competitor.getSearchTag(), boat); + } else { - Competitor updatedCompetitor = getService().apply( - new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), competitor.getShortName(), - competitor.getColor(), competitor.getEmail(), nationality, - competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), - competitor.getTimeOnTimeFactor(), - competitor.getTimeOnDistanceAllowancePerNauticalMile(), - competitor.getSearchTag())); + Competitor updatedCompetitor = getService().apply(new UpdateCompetitor(competitor.getIdAsString(), + competitor.getName(), competitor.getShortName(), competitor.getColor(), competitor.getEmail(), + nationality, competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), + competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), + competitor.getSearchTag())); DynamicBoat updatedBoat = (DynamicBoat) addOrUpdateBoatInternal(competitor.getBoat()); result = new CompetitorWithBoatImpl(updatedCompetitor, updatedBoat); } return result; } - private Competitor addOrUpdateCompetitorWithoutBoatInternal(CompetitorDTO competitor) throws URISyntaxException { Competitor result; - Competitor existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(competitor.getIdAsString()); - Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null : - getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode()); + Competitor existingCompetitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorByIdAsString(competitor.getIdAsString()); + Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null + || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null + : getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode()); if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) { // new competitor UUID competitorUUID = UUID.randomUUID(); DynamicPerson sailor = new PersonImpl(competitor.getName(), nationality, null, null); DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null); - result = getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(), competitor.getShortName(), - competitor.getColor(), competitor.getEmail(), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, - competitor.getTimeOnTimeFactor(), - competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag()); + result = getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(), + competitor.getShortName(), competitor.getColor(), competitor.getEmail(), + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, + competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), + competitor.getSearchTag()); } else { - result = getService().apply( - new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), competitor.getShortName(), - competitor.getColor(), competitor.getEmail(), nationality, - competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), - competitor.getTimeOnTimeFactor(), - competitor.getTimeOnDistanceAllowancePerNauticalMile(), - competitor.getSearchTag())); + result = getService().apply(new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), + competitor.getShortName(), competitor.getColor(), competitor.getEmail(), nationality, + competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), + competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), + competitor.getSearchTag())); } return result; } @@ -5273,18 +5619,21 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Competitor competitor = addOrUpdateCompetitorWithoutBoatInternal(competitorDTO); return getBaseDomainFactory().convertToCompetitorDTO(competitor); } - + @Override - public CompetitorWithBoatDTO addOrUpdateCompetitorWithBoat(CompetitorWithBoatDTO competitorDTO) throws URISyntaxException { + public CompetitorWithBoatDTO addOrUpdateCompetitorWithBoat(CompetitorWithBoatDTO competitorDTO) + throws URISyntaxException { CompetitorWithBoat competitor = addOrUpdateCompetitorWithBoatInternal(competitorDTO); return getBaseDomainFactory().convertToCompetitorWithBoatDTO(competitor); } @Override - public List addCompetitors(List competitorDescriptors, String searchTag) throws URISyntaxException { + public List addCompetitors(List competitorDescriptors, + String searchTag) throws URISyntaxException { List competitorsForSaving = new ArrayList<>(); for (final CompetitorDescriptor competitorDescriptor : competitorDescriptors) { - competitorsForSaving.add(getService().convertCompetitorDescriptorToCompetitorWithBoat(competitorDescriptor, searchTag)); + competitorsForSaving + .add(getService().convertCompetitorDescriptorToCompetitorWithBoat(competitorDescriptor, searchTag)); } getBaseDomainFactory().getCompetitorAndBoatStore().addNewCompetitorsWithBoat(competitorsForSaving); return convertToCompetitorWithBoatDTOs(competitorsForSaving); @@ -5321,10 +5670,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S // new boat UUID boatUUID = UUID.randomUUID(); BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(boat.getBoatClass().getName()); - result = getBaseDomainFactory().getOrCreateBoat(boatUUID, boat.getName(), boatClass, boat.getSailId(), boat.getColor()); + result = getBaseDomainFactory().getOrCreateBoat(boatUUID, boat.getName(), boatClass, boat.getSailId(), + boat.getColor()); } else { - result = getService().apply( - new UpdateBoat(boat.getIdAsString(), boat.getName(), boat.getColor(), boat.getSailId())); + result = getService() + .apply(new UpdateBoat(boat.getIdAsString(), boat.getName(), boat.getColor(), boat.getSailId())); } return result; } @@ -5339,23 +5689,27 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public boolean linkBoatToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString, String boatIdAsString) { + public boolean linkBoatToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, + String competitorIdAsString, String boatIdAsString) { boolean result = false; Boat existingBoat = getService().getCompetitorAndBoatStore().getExistingBoatByIdAsString(boatIdAsString); - Competitor existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(competitorIdAsString); + Competitor existingCompetitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorByIdAsString(competitorIdAsString); RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); if (raceLog != null && existingCompetitor != null && existingBoat != null) { - raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), + raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), getService().getServerAuthor(), raceLog.getCurrentPassId(), existingCompetitor, existingBoat)); result = true; - } + } return result; } @Override - public boolean unlinkBoatFromCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString) { + public boolean unlinkBoatFromCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, + String competitorIdAsString) { boolean result = false; - Competitor existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(competitorIdAsString); + Competitor existingCompetitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorByIdAsString(competitorIdAsString); RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); if (raceLog != null && existingCompetitor != null) { List linkEventsToRevoke = new ArrayList<>(); @@ -5373,15 +5727,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } result = true; - } + } return result; } @Override - public BoatDTO getBoatLinkedToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString) { + public BoatDTO getBoatLinkedToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, + String competitorIdAsString) { BoatDTO result = null; - Competitor existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(competitorIdAsString); - Map competitorToBoatMappingsForRace = getService().getCompetitorToBoatMappingsForRace(leaderboardName, raceColumnName, fleetName); + Competitor existingCompetitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorByIdAsString(competitorIdAsString); + Map competitorToBoatMappingsForRace = getService() + .getCompetitorToBoatMappingsForRace(leaderboardName, raceColumnName, fleetName); if (existingCompetitor != null) { Boat boatOfCompetitor = competitorToBoatMappingsForRace.get(existingCompetitor); if (boatOfCompetitor != null) { @@ -5394,8 +5751,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public List getDeviceConfigurationMatchers() { List configs = new ArrayList(); - for (Entry entry : - getService().getAllDeviceConfigurations().entrySet()) { + for (Entry entry : getService().getAllDeviceConfigurations() + .entrySet()) { DeviceConfigurationMatcher matcher = entry.getKey(); configs.add(convertToDeviceConfigurationMatcherDTO(matcher)); } @@ -5414,7 +5771,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public DeviceConfigurationMatcherDTO createOrUpdateDeviceConfiguration(DeviceConfigurationMatcherDTO matcherDTO, DeviceConfigurationDTO configurationDTO) { + public DeviceConfigurationMatcherDTO createOrUpdateDeviceConfiguration(DeviceConfigurationMatcherDTO matcherDTO, + DeviceConfigurationDTO configurationDTO) { DeviceConfigurationMatcher matcher = convertToDeviceConfigurationMatcher(matcherDTO.clients); DeviceConfiguration configuration = convertToDeviceConfiguration(configurationDTO); getService().createOrUpdateDeviceConfiguration(matcher, configuration); @@ -5431,10 +5789,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private DeviceConfigurationMatcherDTO convertToDeviceConfigurationMatcherDTO(DeviceConfigurationMatcher matcher) { List clients = new ArrayList(); if (matcher instanceof DeviceConfigurationMatcherSingle) { - clients.add(((DeviceConfigurationMatcherSingle)matcher).getClientIdentifier()); + clients.add(((DeviceConfigurationMatcherSingle) matcher).getClientIdentifier()); } - DeviceConfigurationMatcherDTO dto = new DeviceConfigurationMatcherDTO( - clients); + DeviceConfigurationMatcherDTO dto = new DeviceConfigurationMatcherDTO(clients); return dto; } @@ -5459,26 +5816,29 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return null; } DeviceConfigurationDTO.RegattaConfigurationDTO dto = new DeviceConfigurationDTO.RegattaConfigurationDTO(); - + dto.defaultRacingProcedureType = configuration.getDefaultRacingProcedureType(); dto.defaultCourseDesignerMode = configuration.getDefaultCourseDesignerMode(); dto.defaultProtestTimeDuration = configuration.getDefaultProtestTimeDuration(); - + if (configuration.getRRS26Configuration() != null) { dto.rrs26Configuration = new DeviceConfigurationDTO.RegattaConfigurationDTO.RRS26ConfigurationDTO(); copyBasicRacingProcedureProperties(configuration.getRRS26Configuration(), dto.rrs26Configuration); - copyRacingProcedureWithConfigurableStartModeFlagProperties(configuration.getRRS26Configuration(), dto.rrs26Configuration); + copyRacingProcedureWithConfigurableStartModeFlagProperties(configuration.getRRS26Configuration(), + dto.rrs26Configuration); } if (configuration.getSWCStartConfiguration() != null) { dto.swcStartConfiguration = new DeviceConfigurationDTO.RegattaConfigurationDTO.SWCStartConfigurationDTO(); copyBasicRacingProcedureProperties(configuration.getSWCStartConfiguration(), dto.swcStartConfiguration); - copyRacingProcedureWithConfigurableStartModeFlagProperties(configuration.getSWCStartConfiguration(), dto.swcStartConfiguration); + copyRacingProcedureWithConfigurableStartModeFlagProperties(configuration.getSWCStartConfiguration(), + dto.swcStartConfiguration); } if (configuration.getGateStartConfiguration() != null) { dto.gateStartConfiguration = new DeviceConfigurationDTO.RegattaConfigurationDTO.GateStartConfigurationDTO(); copyBasicRacingProcedureProperties(configuration.getGateStartConfiguration(), dto.gateStartConfiguration); dto.gateStartConfiguration.hasPathfinder = configuration.getGateStartConfiguration().hasPathfinder(); - dto.gateStartConfiguration.hasAdditionalGolfDownTime = configuration.getGateStartConfiguration().hasAdditionalGolfDownTime(); + dto.gateStartConfiguration.hasAdditionalGolfDownTime = configuration.getGateStartConfiguration() + .hasAdditionalGolfDownTime(); } if (configuration.getESSConfiguration() != null) { dto.essConfiguration = new DeviceConfigurationDTO.RegattaConfigurationDTO.ESSConfigurationDTO(); @@ -5494,19 +5854,23 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return dto; } - - private void copyBasicRacingProcedureProperties(RacingProcedureConfiguration configuration, final RacingProcedureConfigurationDTO racingProcedureConfigurationDTO) { + + private void copyBasicRacingProcedureProperties(RacingProcedureConfiguration configuration, + final RacingProcedureConfigurationDTO racingProcedureConfigurationDTO) { racingProcedureConfigurationDTO.classFlag = configuration.getClassFlag(); racingProcedureConfigurationDTO.hasIndividualRecall = configuration.hasIndividualRecall(); racingProcedureConfigurationDTO.isResultEntryEnabled = configuration.isResultEntryEnabled(); } - private void copyRacingProcedureWithConfigurableStartModeFlagProperties(ConfigurableStartModeFlagRacingProcedureConfiguration configuration, final RacingProcedureWithConfigurableStartModeFlagConfigurationDTO racingProcedureConfigurationDTO) { + private void copyRacingProcedureWithConfigurableStartModeFlagProperties( + ConfigurableStartModeFlagRacingProcedureConfiguration configuration, + final RacingProcedureWithConfigurableStartModeFlagConfigurationDTO racingProcedureConfigurationDTO) { racingProcedureConfigurationDTO.startModeFlags = configuration.getStartModeFlags(); } private DeviceConfigurationImpl convertToDeviceConfiguration(DeviceConfigurationDTO dto) { - DeviceConfigurationImpl configuration = new DeviceConfigurationImpl(convertToRegattaConfiguration(dto.regattaConfiguration)); + DeviceConfigurationImpl configuration = new DeviceConfigurationImpl( + convertToRegattaConfiguration(dto.regattaConfiguration)); configuration.setAllowedCourseAreaNames(dto.allowedCourseAreaNames); configuration.setResultsMailRecipient(dto.resultsMailRecipient); configuration.setByNameDesignerCourseNames(dto.byNameDesignerCourseNames); @@ -5558,8 +5922,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return configuration; } - private void applyGeneralRacingProcedureConfigProperties(RacingProcedureConfigurationDTO racingProcedureConfigurationDTO, - RacingProcedureConfigurationImpl config) { + private void applyGeneralRacingProcedureConfigProperties( + RacingProcedureConfigurationDTO racingProcedureConfigurationDTO, RacingProcedureConfigurationImpl config) { config.setClassFlag(racingProcedureConfigurationDTO.classFlag); config.setHasIndividualRecall(racingProcedureConfigurationDTO.hasIndividualRecall); config.setResultEntryEnabled(racingProcedureConfigurationDTO.isResultEntryEnabled); @@ -5570,26 +5934,25 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S RacingProcedureWithConfigurableStartModeFlagConfigurationImpl config) { config.setStartModeFlags(racingProcedureConfigurationDTO.startModeFlags); } - + @Override public boolean setStartTimeAndProcedure(RaceLogSetStartTimeAndProcedureDTO dto) { - TimePoint newStartTime = getService().setStartTimeAndProcedure(dto.leaderboardName, dto.raceColumnName, - dto.fleetName, dto.authorName, dto.authorPriority, - dto.passId, new MillisecondsTimePoint(dto.logicalTimePoint), new MillisecondsTimePoint(dto.startTime), + TimePoint newStartTime = getService().setStartTimeAndProcedure(dto.leaderboardName, dto.raceColumnName, + dto.fleetName, dto.authorName, dto.authorPriority, dto.passId, + new MillisecondsTimePoint(dto.logicalTimePoint), new MillisecondsTimePoint(dto.startTime), dto.racingProcedure); return new MillisecondsTimePoint(dto.startTime).equals(newStartTime); } - + @Override public Pair setFinishingAndEndTime(RaceLogSetFinishingAndFinishTimeDTO dto) { - TimePoint newFinsihingTime = getService().setFinishingTime(dto.leaderboardName, dto.raceColumnName, - dto.fleetName, dto.authorName, dto.authorPriority, - dto.passId, new MillisecondsTimePoint(dto.finishingTime)); - - TimePoint newEndTime = getService().setEndTime(dto.leaderboardName, dto.raceColumnName, - dto.fleetName, dto.authorName, dto.authorPriority, - dto.passId, new MillisecondsTimePoint(dto.finishTime)); - + TimePoint newFinsihingTime = getService().setFinishingTime(dto.leaderboardName, dto.raceColumnName, + dto.fleetName, dto.authorName, dto.authorPriority, dto.passId, + new MillisecondsTimePoint(dto.finishingTime)); + + TimePoint newEndTime = getService().setEndTime(dto.leaderboardName, dto.raceColumnName, dto.fleetName, + dto.authorName, dto.authorPriority, dto.passId, new MillisecondsTimePoint(dto.finishTime)); + return new Pair(new MillisecondsTimePoint(dto.finishingTime).equals(newFinsihingTime), new MillisecondsTimePoint(dto.finishTime).equals(newEndTime)); } @@ -5601,49 +5964,63 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final LogEventAuthorImpl author = new LogEventAuthorImpl(dto.authorName, dto.authorPriority); if (!Util.equalsWithNull(dto.newStartOfTracking, dto.currentStartOfTracking)) { if (dto.newStartOfTracking != null) { - raceLog.add(new RaceLogStartOfTrackingEventImpl(dto.newStartOfTracking.getTimePoint(), - author, raceLog.getCurrentPassId())); + raceLog.add(new RaceLogStartOfTrackingEventImpl(dto.newStartOfTracking.getTimePoint(), author, + raceLog.getCurrentPassId())); } else { - final Pair trackingTimesEvents = new TrackingTimesEventFinder(raceLog).analyze(); - // we assume to find a valid "set start of tracking time" event that matches the old start of tracking time; + final Pair trackingTimesEvents = new TrackingTimesEventFinder( + raceLog).analyze(); + // we assume to find a valid "set start of tracking time" event that matches the old start of tracking + // time; // if the time doesn't match dto.currentStartOfTracking, the revocation is rejected with an exception; // the result of trying to revoke is returned otherwise, and it may not be the result intended in case // the author's priority was lower than that of the author of the event that is to be revoked. - if (trackingTimesEvents == null || trackingTimesEvents.getA() == null || - !Util.equalsWithNull(trackingTimesEvents.getA().getLogicalTimePoint(), dto.currentStartOfTracking==null?null:dto.currentStartOfTracking.getTimePoint())) { - throw new NotFoundException("Old start of tracking time in the race log ("+ - (trackingTimesEvents==null||trackingTimesEvents.getA()==null?"unset":trackingTimesEvents.getA().getLogicalTimePoint())+ - ") does not match start of tracking time at transaction start ("+dto.currentStartOfTracking==null?null:dto.currentStartOfTracking.getTimePoint()+")"); + if (trackingTimesEvents == null || trackingTimesEvents.getA() == null || !Util.equalsWithNull( + trackingTimesEvents.getA().getLogicalTimePoint(), + dto.currentStartOfTracking == null ? null : dto.currentStartOfTracking.getTimePoint())) { + throw new NotFoundException("Old start of tracking time in the race log (" + + (trackingTimesEvents == null || trackingTimesEvents.getA() == null ? "unset" + : trackingTimesEvents.getA().getLogicalTimePoint()) + + ") does not match start of tracking time at transaction start (" + + dto.currentStartOfTracking == null ? null + : dto.currentStartOfTracking.getTimePoint() + ")"); } else { try { raceLog.revokeEvent(author, trackingTimesEvents.getA(), "resetting tracking start time"); } catch (NotRevokableException e) { - logger.log(Level.WARNING, "Internal error: event "+trackingTimesEvents.getA()+" was expected to be revokable", e); + logger.log(Level.WARNING, + "Internal error: event " + trackingTimesEvents.getA() + " was expected to be revokable", + e); } } } } if (!Util.equalsWithNull(dto.newEndOfTracking, dto.currentEndOfTracking)) { if (dto.newEndOfTracking != null) { - raceLog.add(new RaceLogEndOfTrackingEventImpl( - dto.newEndOfTracking.getTimePoint(), author, + raceLog.add(new RaceLogEndOfTrackingEventImpl(dto.newEndOfTracking.getTimePoint(), author, raceLog.getCurrentPassId())); } else { - final Pair trackingTimesEvents = new TrackingTimesEventFinder(raceLog).analyze(); - // we assume to find a valid "set start of tracking time" event that matches the old start of tracking time; + final Pair trackingTimesEvents = new TrackingTimesEventFinder( + raceLog).analyze(); + // we assume to find a valid "set start of tracking time" event that matches the old start of tracking + // time; // if the time doesn't match dto.currentStartOfTracking, the revocation is rejected with an exception; // the result of trying to revoke is returned otherwise, and it may not be the result intended in case // the author's priority was lower than that of the author of the event that is to be revoked. - if (trackingTimesEvents == null || trackingTimesEvents.getB() == null || - !Util.equalsWithNull(trackingTimesEvents.getB().getLogicalTimePoint(), dto.currentEndOfTracking==null?null:dto.currentEndOfTracking.getTimePoint())) { - throw new NotFoundException("Old end of tracking time in the race log ("+ - (trackingTimesEvents==null||trackingTimesEvents.getB()==null?"unset":trackingTimesEvents.getB().getLogicalTimePoint())+ - ") does not match end of tracking time at transaction start ("+dto.currentEndOfTracking==null?null:dto.currentEndOfTracking.getTimePoint()+")"); + if (trackingTimesEvents == null || trackingTimesEvents.getB() == null + || !Util.equalsWithNull(trackingTimesEvents.getB().getLogicalTimePoint(), + dto.currentEndOfTracking == null ? null : dto.currentEndOfTracking.getTimePoint())) { + throw new NotFoundException("Old end of tracking time in the race log (" + + (trackingTimesEvents == null || trackingTimesEvents.getB() == null ? "unset" + : trackingTimesEvents.getB().getLogicalTimePoint()) + + ") does not match end of tracking time at transaction start (" + + dto.currentEndOfTracking == null ? null : dto.currentEndOfTracking.getTimePoint() + ")"); } else { try { raceLog.revokeEvent(author, trackingTimesEvents.getB(), "resetting tracking end time"); } catch (NotRevokableException e) { - logger.log(Level.WARNING, "Internal error: event "+trackingTimesEvents.getB()+" was expected to be revokable", e); + logger.log(Level.WARNING, + "Internal error: event " + trackingTimesEvents.getB() + " was expected to be revokable", + e); } } } @@ -5651,7 +6028,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public Pair getTrackingTimes(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { + public Pair getTrackingTimes( + String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { final Pair times; final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); if (raceLog != null) { @@ -5663,18 +6041,22 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public com.sap.sse.common.Util.Triple getStartTimeAndProcedure(String leaderboardName, String raceColumnName, String fleetName) { - com.sap.sse.common.Util.Triple result = getService().getStartTimeAndProcedure(leaderboardName, raceColumnName, fleetName); + public com.sap.sse.common.Util.Triple getStartTimeAndProcedure( + String leaderboardName, String raceColumnName, String fleetName) { + com.sap.sse.common.Util.Triple result = getService() + .getStartTimeAndProcedure(leaderboardName, raceColumnName, fleetName); if (result == null || result.getA() == null) { return null; } - return new com.sap.sse.common.Util.Triple(result.getA() == null ? null : result.getA().asDate(), result.getB(), result.getC()); + return new com.sap.sse.common.Util.Triple( + result.getA() == null ? null : result.getA().asDate(), result.getB(), result.getC()); } - @Override - public com.sap.sse.common.Util.Triple getFinishingAndFinishTime(String leaderboardName, String raceColumnName, String fleetName) { - com.sap.sse.common.Util.Triple result = getService().getFinishingAndFinishTime(leaderboardName, raceColumnName, fleetName); + public com.sap.sse.common.Util.Triple getFinishingAndFinishTime(String leaderboardName, + String raceColumnName, String fleetName) { + com.sap.sse.common.Util.Triple result = getService() + .getFinishingAndFinishTime(leaderboardName, raceColumnName, fleetName); if (result == null) { return null; } @@ -5694,7 +6076,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private IgtimiConnectionFactory getIgtimiConnectionFactory() { return igtimiAdapterTracker.getService(); } - + protected RaceLogTrackingAdapterFactory getRaceLogTrackingAdapterFactory() { return raceLogTrackingAdapterTracker.getService(); } @@ -5704,7 +6086,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public String getIgtimiAuthorizationUrl(String redirectProtocol, String redirectHostname, String redirectPort) throws MalformedURLException, UnsupportedEncodingException { + public String getIgtimiAuthorizationUrl(String redirectProtocol, String redirectHostname, String redirectPort) + throws MalformedURLException, UnsupportedEncodingException { return getIgtimiConnectionFactory().getAuthorizationUrl(redirectProtocol, redirectHostname, redirectPort); } @@ -5720,8 +6103,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public Map importWindFromIgtimi(List selectedRaces, boolean correctByDeclination) throws IllegalStateException, - ClientProtocolException, IOException, org.json.simple.parser.ParseException { + public Map importWindFromIgtimi(List selectedRaces, + boolean correctByDeclination) + throws IllegalStateException, ClientProtocolException, IOException, org.json.simple.parser.ParseException { final IgtimiConnectionFactory igtimiConnectionFactory = getIgtimiConnectionFactory(); final Iterable trackedRaces; if (selectedRaces != null && !selectedRaces.isEmpty()) { @@ -5744,12 +6128,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (i == null) { i = 0; } - numberOfWindFixesImportedPerRace.put(key, i+resultForAccount.getValue()); + numberOfWindFixesImportedPerRace.put(key, i + resultForAccount.getValue()); } } for (final TrackedRace trackedRace : trackedRaces) { - // update polar sheets: - getService().getPolarDataService().insertExistingFixes(trackedRace); + // update polar sheets: + getService().getPolarDataService().insertExistingFixes(trackedRace); } return numberOfWindFixesImportedPerRace; } @@ -5776,11 +6160,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private class TimeoutExtendingInputStream extends FilterInputStream { - // default timeout is high to ensure that long running client operations - // such as compressing data will not have the server run into a timeout. - // this especially applies to foiling data where compression on slower machines - // can take up to two hours. - private static final int DEFAULT_TIMEOUT_IN_SECONDS = 60*60*2; + // default timeout is high to ensure that long running client operations + // such as compressing data will not have the server run into a timeout. + // this especially applies to foiling data where compression on slower machines + // can take up to two hours. + private static final int DEFAULT_TIMEOUT_IN_SECONDS = 60 * 60 * 2; private final URLConnection connection; @@ -5791,50 +6175,52 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public int read() throws IOException { - connection.setReadTimeout(DEFAULT_TIMEOUT_IN_SECONDS*1000); + connection.setReadTimeout(DEFAULT_TIMEOUT_IN_SECONDS * 1000); return super.read(); } @Override public int read(byte[] b) throws IOException { - connection.setReadTimeout(DEFAULT_TIMEOUT_IN_SECONDS*1000); + connection.setReadTimeout(DEFAULT_TIMEOUT_IN_SECONDS * 1000); return super.read(b); } @Override public int read(byte[] b, int off, int len) throws IOException { - connection.setReadTimeout(DEFAULT_TIMEOUT_IN_SECONDS*1000); + connection.setReadTimeout(DEFAULT_TIMEOUT_IN_SECONDS * 1000); return super.read(b, off, len); } } @Override - public Boolean denoteForRaceLogTracking(String leaderboardName, - String raceColumnName, String fleetName) throws NotFoundException, NotDenotableForRaceLogTrackingException { + public Boolean denoteForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) + throws NotFoundException, NotDenotableForRaceLogTrackingException { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - Fleet fleet = getFleetByName(raceColumn, fleetName); - return getRaceLogTrackingAdapter().denoteRaceForRaceLogTracking(getService(), leaderboard, raceColumn, fleet, null); + RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); + Fleet fleet = getFleetByName(raceColumn, fleetName); + return getRaceLogTrackingAdapter().denoteRaceForRaceLogTracking(getService(), leaderboard, raceColumn, fleet, + null); } - + @Override - public void removeDenotationForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { + public void removeDenotationForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) + throws NotFoundException { RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); getRaceLogTrackingAdapter().removeDenotationForRaceLogTracking(getService(), raceLog); } - + @Override public void denoteForRaceLogTracking(String leaderboardName) throws Exception { denoteForRaceLogTracking(leaderboardName, /* race name prefix */ null); } - + @Override public void denoteForRaceLogTracking(String leaderboardName, String prefix) throws Exception { - Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); getRaceLogTrackingAdapter().denoteAllRacesForRaceLogTracking(getService(), leaderboard, prefix); } - + /** * @param triple * leaderboard and racecolumn and fleet names @@ -5842,16 +6228,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private RaceLog getRaceLog(com.sap.sse.common.Util.Triple triple) throws NotFoundException { return getRaceLog(triple.getA(), triple.getB(), triple.getC()); } - + private RegattaLog getRegattaLogInternal(String leaderboardName) throws DoesNotHaveRegattaLogException { Leaderboard l = getService().getLeaderboardByName(leaderboardName); - if (! (l instanceof HasRegattaLike)) { + if (!(l instanceof HasRegattaLike)) { throw new DoesNotHaveRegattaLogException(); } return ((HasRegattaLike) l).getRegattaLike().getRegattaLog(); } - - private RaceLog getRaceLog(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { + + private RaceLog getRaceLog(String leaderboardName, String raceColumnName, String fleetName) + throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); return raceColumn.getRaceLog(fleet); @@ -5860,7 +6247,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private Competitor getCompetitor(CompetitorDTO dto) { return getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(dto.getIdAsString()); } - + private CompetitorWithBoat getCompetitor(CompetitorWithBoatDTO dto) { return getService().getCompetitorAndBoatStore().getExistingCompetitorWithBoatByIdAsString(dto.getIdAsString()); } @@ -5875,21 +6262,26 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException { Map competitorToBoatMappingsToRegister = new HashMap<>(); for (Entry competitorAndBoatEntry : competitorAndBoatDTOs.entrySet()) { - competitorToBoatMappingsToRegister.put(getCompetitor(competitorAndBoatEntry.getKey()), getBoat(competitorAndBoatEntry.getValue())); + competitorToBoatMappingsToRegister.put(getCompetitor(competitorAndBoatEntry.getKey()), + getBoat(competitorAndBoatEntry.getValue())); } RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); - final Iterable competitorRegistrationsToRemove = filterCompetitorDuplicates(competitorToBoatMappingsToRegister, raceColumn.getCompetitorsRegisteredInRacelog(fleet)); + final Iterable competitorRegistrationsToRemove = filterCompetitorDuplicates( + competitorToBoatMappingsToRegister, raceColumn.getCompetitorsRegisteredInRacelog(fleet)); raceColumn.deregisterCompetitors(competitorRegistrationsToRemove, fleet); // we assume that the competitors id of type Competitor here, so we need to find the corresponding boat - for (final Entry competitorAndBoatToRegister : competitorToBoatMappingsToRegister.entrySet()) { - raceColumn.registerCompetitor(competitorAndBoatToRegister.getKey(), competitorAndBoatToRegister.getValue(), fleet); + for (final Entry competitorAndBoatToRegister : competitorToBoatMappingsToRegister + .entrySet()) { + raceColumn.registerCompetitor(competitorAndBoatToRegister.getKey(), competitorAndBoatToRegister.getValue(), + fleet); } } - + @Override public void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, - Set competitorDTOs) throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException { + Set competitorDTOs) + throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException { Map competitorsToRegister = new HashMap<>(); for (CompetitorWithBoatDTO dto : competitorDTOs) { competitorsToRegister.put(getCompetitor(dto), getBoat(dto.getBoat())); @@ -5900,24 +6292,27 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (final Entry e : raceColumn.getCompetitorsRegisteredInRacelog(fleet).entrySet()) { competitorsRegisteredInRaceLog.put((CompetitorWithBoat) e.getKey(), e.getValue()); } - final Iterable competitorSetToRemove = filterCompetitorDuplicates(competitorsToRegister, competitorsRegisteredInRaceLog); + final Iterable competitorSetToRemove = filterCompetitorDuplicates(competitorsToRegister, + competitorsRegisteredInRaceLog); raceColumn.deregisterCompetitors(competitorSetToRemove, fleet); // we assume that the competitors id of type Competitor here, so we need to find the corresponding boat for (CompetitorWithBoat competitorToRegister : competitorsToRegister.keySet()) { if (competitorToRegister.hasBoat()) { - raceColumn.registerCompetitor(competitorToRegister, fleet); + raceColumn.registerCompetitor(competitorToRegister, fleet); } else { - logger.warning("The competitor "+competitorToRegister.getName()+" does not have a boat associated but should have; "+ - "competitor is not registered for race log of race "+raceColumnName+" in leaderboard "+leaderboardName+" for fleet "+fleetName); + logger.warning("The competitor " + competitorToRegister.getName() + + " does not have a boat associated but should have; " + + "competitor is not registered for race log of race " + raceColumnName + " in leaderboard " + + leaderboardName + " for fleet " + fleetName); } } } - + @Override - public void setCompetitorRegistrationsInRegattaLog(String leaderboardName, Set competitorDTOs) - throws DoesNotHaveRegattaLogException, NotFoundException { + public void setCompetitorRegistrationsInRegattaLog(String leaderboardName, + Set competitorDTOs) throws DoesNotHaveRegattaLogException, NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (!(leaderboard instanceof HasRegattaLike)){ + if (!(leaderboard instanceof HasRegattaLike)) { throw new DoesNotHaveRegattaLogException(); } Map competitorsToRegister = new HashMap<>(); @@ -5927,21 +6322,26 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S HasRegattaLike hasRegattaLike = (HasRegattaLike) leaderboard; Map competitorsAlreadyRegistered = new HashMap<>(); for (final Competitor c : leaderboard.getAllCompetitors()) { - competitorsAlreadyRegistered.put(c, /* boat doesn't matter here */ null); + competitorsAlreadyRegistered.put(c, /* boat doesn't matter here */ null); } - final Iterable competitorSetToRemove = filterCompetitorDuplicates(competitorsToRegister, competitorsAlreadyRegistered); + final Iterable competitorSetToRemove = filterCompetitorDuplicates(competitorsToRegister, + competitorsAlreadyRegistered); hasRegattaLike.deregisterCompetitors(competitorSetToRemove); hasRegattaLike.registerCompetitors(competitorsToRegister.keySet()); } /** - * Removes competitors already registered to the same boats (those in {@code competitorsRegistered}) from {@code competitorsToRegister} to avoid - * registering them again and then returns those competitors that need to be de-registered. Those to de-register includes those registered but - * to a different boat, and those will be left in the {@code competitorToBoatMappingsToRegister} map. + * Removes competitors already registered to the same boats (those in {@code competitorsRegistered}) from + * {@code competitorsToRegister} to avoid registering them again and then returns those competitors that need to be + * de-registered. Those to de-register includes those registered but to a different boat, and those will be left in + * the {@code competitorToBoatMappingsToRegister} map. * - * @param competitorToBoatMappingsToRegister will be modified by removing all competitors in {@code competitorsRegistered} - * @param competitorToBoatMappingsRegistered the competitors already registered; those will be removed from {@code competitorsToRegister} - * @return the competitors to de-register because they were in {@code competitorsRegistered} but are not in {@code competitorsToRegister} + * @param competitorToBoatMappingsToRegister + * will be modified by removing all competitors in {@code competitorsRegistered} + * @param competitorToBoatMappingsRegistered + * the competitors already registered; those will be removed from {@code competitorsToRegister} + * @return the competitors to de-register because they were in {@code competitorsRegistered} but are not in + * {@code competitorsToRegister} */ private Iterable filterCompetitorDuplicates( Map competitorToBoatMappingsToRegister, @@ -5954,7 +6354,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final Boat boatOfCompetitorToRegister = competitorToBoatMappingsToRegister.get(competitor); final Boat boatOfRegisteredCompetitor = e.getValue(); if (boatOfCompetitorToRegister == boatOfRegisteredCompetitor) { - // User wants to map competitor to boat, and that mapping already exists; neither add nor remove this registration but leave as is: + // User wants to map competitor to boat, and that mapping already exists; neither add nor remove + // this registration but leave as is: competitorToBoatMappingsToRegister.remove(competitor); competitorsToUnregister.remove(competitor); } @@ -5987,20 +6388,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return result; } - + /** - * Also finds the last position of the marks if set by pinging them as long as currently a {@link TrackedRace} exists - * whose tracking interval spans the current time. If at least a non-spanning {@link TrackedRace} can be found in the - * scope of the leaderboard, the time-wise closest position fix for the mark will be used as its position. - * If the mark has been pinged through the {@link RegattaLog} but no {@link TrackedRace} exists that has loaded that ping, - * the ping won't be visible to this API. + * Also finds the last position of the marks if set by pinging them as long as currently a {@link TrackedRace} + * exists whose tracking interval spans the current time. If at least a non-spanning {@link TrackedRace} can be + * found in the scope of the leaderboard, the time-wise closest position fix for the mark will be used + * as its position. If the mark has been pinged through the {@link RegattaLog} but no {@link TrackedRace} exists + * that has loaded that ping, the ping won't be visible to this API. */ private MarkDTO convertToMarkDTO(LeaderboardThatHasRegattaLike leaderboard, Mark mark) { final TimePoint now = MillisecondsTimePoint.now(); final Position lastPos = getService().getMarkPosition(mark, leaderboard, now); return convertToMarkDTO(mark, lastPos); } - + @Override public void addMarkToRegattaLog(String leaderboardName, MarkDTO markDTO) throws DoesNotHaveRegattaLogException { Mark mark = convertToMark(markDTO, false); @@ -6010,15 +6411,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S getService().getServerAuthor(), MillisecondsTimePoint.now(), UUID.randomUUID(), mark); regattaLog.add(event); } - + @Override - public void revokeMarkDefinitionEventInRegattaLog(String leaderboardName, MarkDTO markDTO) throws DoesNotHaveRegattaLogException { + public void revokeMarkDefinitionEventInRegattaLog(String leaderboardName, MarkDTO markDTO) + throws DoesNotHaveRegattaLogException { RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); - final List regattaLogDefineMarkEvents = new AllEventsOfTypeFinder<>(regattaLog, /* only unrevoked */ true, RegattaLogDefineMarkEvent.class).analyze(); + final List regattaLogDefineMarkEvents = new AllEventsOfTypeFinder<>(regattaLog, + /* only unrevoked */ true, RegattaLogDefineMarkEvent.class).analyze(); RegattaLogDefineMarkEvent eventToRevoke = null; for (RegattaLogEvent event : regattaLogDefineMarkEvents) { RegattaLogDefineMarkEvent defineMarkEvent = (RegattaLogDefineMarkEvent) event; - if (defineMarkEvent.getMark().getId().toString().equals(markDTO.getIdAsString())){ + if (defineMarkEvent.getMark().getId().toString().equals(markDTO.getIdAsString())) { eventToRevoke = defineMarkEvent; break; } @@ -6028,23 +6431,25 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public void addCourseDefinitionToRaceLog(String leaderboardName, String raceColumnName, String fleetName, - List> courseDTO) throws NotFoundException { + List> courseDTO) + throws NotFoundException { RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); String courseName = "Course of " + raceColumnName; if (!LeaderboardNameConstants.DEFAULT_FLEET_NAME.equals(fleetName)) { - courseName += " - " + fleetName; + courseName += " - " + fleetName; } - CourseBase lastPublishedCourse = new LastPublishedCourseDesignFinder(raceLog, /* onlyCoursesWithValidWaypointList */ false).analyze(); + CourseBase lastPublishedCourse = new LastPublishedCourseDesignFinder(raceLog, + /* onlyCoursesWithValidWaypointList */ false).analyze(); if (lastPublishedCourse == null) { lastPublishedCourse = new CourseDataImpl(courseName); } - + List> controlPoints = new ArrayList<>(); for (Pair waypointDTO : courseDTO) { controlPoints.add(new Pair<>(getOrCreateControlPoint(waypointDTO.getA()), waypointDTO.getB())); } Course course = new CourseImpl(courseName, lastPublishedCourse.getWaypoints()); - + try { course.update(controlPoints, baseDomainFactory); } catch (Exception e) { @@ -6063,8 +6468,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S SecurityUtils.getSubject().checkPermission( Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName)); RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); - raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, isPublic, raceTimepoint, getService().getServerAuthor(), - raceLog.getCurrentPassId())); + raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, isPublic, raceTimepoint, + getService().getServerAuthor(), raceLog.getCurrentPassId())); } catch (AuthorizationException e) { successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagMissingPermissions"), null, null); @@ -6116,7 +6521,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S * the mark positions and attach to the {@link MarkDTO}s. If null, the current time point * will be used as default. */ - private WaypointDTO convertToWaypointDTO(Waypoint waypoint, Map controlPointCache, MarkPositionFinder positionFinder, TimePoint timePoint) { + private WaypointDTO convertToWaypointDTO(Waypoint waypoint, Map controlPointCache, + MarkPositionFinder positionFinder, TimePoint timePoint) { ControlPointDTO cp = controlPointCache.get(waypoint.getControlPoint().getId()); if (cp == null) { cp = convertToControlPointDTO(waypoint.getControlPoint(), positionFinder, timePoint); @@ -6124,7 +6530,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return new WaypointDTO(waypoint.getName(), cp, waypoint.getPassingInstructions()); } - + /** * @param course * the course to convert @@ -6135,7 +6541,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S * the mark positions and attach to the {@link MarkDTO}s. If null, the current time point * will be used as default. */ - private RaceCourseDTO convertToRaceCourseDTO(CourseBase course, MarkPositionFinder positionFinder, TimePoint timePoint) { + private RaceCourseDTO convertToRaceCourseDTO(CourseBase course, MarkPositionFinder positionFinder, + TimePoint timePoint) { final RaceCourseDTO result; if (course != null) { List waypointDTOs = new ArrayList(); @@ -6149,26 +6556,29 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return result; } - + @Override - public RaceCourseDTO getLastCourseDefinitionInRaceLog(final String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { + public RaceCourseDTO getLastCourseDefinitionInRaceLog(final String leaderboardName, String raceColumnName, + String fleetName) throws NotFoundException { final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); // only look for course definitions that really define waypoints; ignore by-name course updates - CourseBase lastPublishedCourse = new LastPublishedCourseDesignFinder(raceLog, /* onlyCoursesWithValidWaypointList */ true).analyze(); + CourseBase lastPublishedCourse = new LastPublishedCourseDesignFinder(raceLog, + /* onlyCoursesWithValidWaypointList */ true).analyze(); if (lastPublishedCourse == null) { lastPublishedCourse = new CourseDataImpl(""); } return convertToRaceCourseDTO(lastPublishedCourse, new MarkPositionFinder() { @Override public Position find(Mark mark, TimePoint at) { - return getService().getMarkPosition(mark, (LeaderboardThatHasRegattaLike) getService().getLeaderboardByName(leaderboardName), at); + return getService().getMarkPosition(mark, + (LeaderboardThatHasRegattaLike) getService().getLeaderboardByName(leaderboardName), at); } }, /* timePoint */ MillisecondsTimePoint.now()); } - + @Override - public void pingMark(String leaderboardName, - MarkDTO markDTO, TimePoint timePoint, Position positionDTO) throws DoesNotHaveRegattaLogException { + public void pingMark(String leaderboardName, MarkDTO markDTO, TimePoint timePoint, Position positionDTO) + throws DoesNotHaveRegattaLogException { final RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); final Mark mark = convertToMark(markDTO, true); final TimePoint time = timePoint == null ? MillisecondsTimePoint.now() : timePoint; @@ -6176,7 +6586,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final GPSFix fix = new GPSFixImpl(position, time); getRaceLogTrackingAdapter().pingMark(regattaLog, mark, fix, getService()); } - + @Override public void copyCourseToOtherRaceLogs(com.sap.sse.common.Util.Triple fromTriple, Set> toTriples) throws NotFoundException { @@ -6187,7 +6597,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } getRaceLogTrackingAdapter().copyCourse(fromRaceLog, toRaceLogs, baseDomainFactory, getService()); } - + @Override public void copyCompetitorsToOtherRaceLogs(com.sap.sse.common.Util.Triple fromTriple, Set> toTriples) throws NotFoundException { @@ -6200,31 +6610,33 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } getRaceLogTrackingAdapter().copyCompetitors(raceColumn, getFleetByName(raceColumn, fromTriple.getC()), toRaces); } - + private TypeBasedServiceFinder getDeviceIdentifierStringSerializerHandlerFinder( boolean withFallback) { TypeBasedServiceFinderFactory factory = getService().getTypeBasedServiceFinderFactory(); - TypeBasedServiceFinder finder = factory.createServiceFinder(DeviceIdentifierStringSerializationHandler.class); + TypeBasedServiceFinder finder = factory + .createServiceFinder(DeviceIdentifierStringSerializationHandler.class); if (withFallback) { finder.setFallbackService(new PlaceHolderDeviceIdentifierStringSerializationHandler()); } return finder; } - - private DeviceIdentifier deserializeDeviceIdentifier(String type, String deviceId) throws NoCorrespondingServiceRegisteredException, - TransformationException { - DeviceIdentifierStringSerializationHandler handler = - getDeviceIdentifierStringSerializerHandlerFinder(false).findService(type); + + private DeviceIdentifier deserializeDeviceIdentifier(String type, String deviceId) + throws NoCorrespondingServiceRegisteredException, TransformationException { + DeviceIdentifierStringSerializationHandler handler = getDeviceIdentifierStringSerializerHandlerFinder(false) + .findService(type); return handler.deserialize(deviceId, type, deviceId); } - + private String serializeDeviceIdentifier(DeviceIdentifier deviceId) throws TransformationException { - return getDeviceIdentifierStringSerializerHandlerFinder(true).findService( - deviceId.getIdentifierType()).serialize(deviceId).getB(); + return getDeviceIdentifierStringSerializerHandlerFinder(true).findService(deviceId.getIdentifierType()) + .serialize(deviceId).getB(); } - + private DeviceMappingDTO convertToDeviceMappingDTO(DeviceMapping mapping) throws TransformationException { - final Map lastFixes = getService().getSensorFixStore().getLastFix(Collections.singleton(mapping.getDevice())); + final Map lastFixes = getService().getSensorFixStore() + .getLastFix(Collections.singleton(mapping.getDevice())); final Timed lastFix; if (lastFixes != null && lastFixes.containsKey(mapping.getDevice())) { lastFix = lastFixes.get(mapping.getDevice()); @@ -6232,10 +6644,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S lastFix = null; } String deviceId = serializeDeviceIdentifier(mapping.getDevice()); - Date from = mapping.getTimeRange().from() == null || mapping.getTimeRange().from().equals(TimePoint.BeginningOfTime) ? - null : mapping.getTimeRange().from().asDate(); - Date to = mapping.getTimeRange().to() == null || mapping.getTimeRange().to().equals(TimePoint.EndOfTime) ? - null : mapping.getTimeRange().to().asDate(); + Date from = mapping.getTimeRange().from() == null + || mapping.getTimeRange().from().equals(TimePoint.BeginningOfTime) ? null + : mapping.getTimeRange().from().asDate(); + Date to = mapping.getTimeRange().to() == null || mapping.getTimeRange().to().equals(TimePoint.EndOfTime) ? null + : mapping.getTimeRange().to().asDate(); MappableToDevice item = null; final WithID mappedTo = mapping.getMappedTo(); if (mappedTo == null) { @@ -6250,53 +6663,52 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S throw new RuntimeException("Can only handle Competitor, Boat or Mark as mapped item type, but not " + mappedTo.getClass().getName()); } - //Only deal with UUIDs - otherwise we would have to pass Serializable to browser context - which - //has a large performance implact for GWT. - //As any Serializable subclass is converted to String by the BaseRaceLogEventSerializer, and only UUIDs are - //recovered by the BaseRaceLogEventDeserializer, only UUIDs are safe to use anyway. + // Only deal with UUIDs - otherwise we would have to pass Serializable to browser context - which + // has a large performance implact for GWT. + // As any Serializable subclass is converted to String by the BaseRaceLogEventSerializer, and only UUIDs are + // recovered by the BaseRaceLogEventDeserializer, only UUIDs are safe to use anyway. List originalRaceLogEventUUIDs = new ArrayList(); for (Serializable id : mapping.getOriginalRaceLogEventIds()) { - if (! (id instanceof UUID)) { + if (!(id instanceof UUID)) { logger.log(Level.WARNING, "Got RaceLogEvent with id that was not UUID, but " + id.getClass().getName()); throw new TransformationException("Could not send device mapping to browser: can only deal with UUIDs"); } originalRaceLogEventUUIDs.add((UUID) id); } - return new DeviceMappingDTO(new DeviceIdentifierDTO(mapping.getDevice().getIdentifierType(), - deviceId), from, to, item, originalRaceLogEventUUIDs, lastFix==null?null:lastFix.getTimePoint()); + return new DeviceMappingDTO(new DeviceIdentifierDTO(mapping.getDevice().getIdentifierType(), deviceId), from, + to, item, originalRaceLogEventUUIDs, lastFix == null ? null : lastFix.getTimePoint()); } - - private List> getLogHierarchy(String leaderboardName, String raceColumnName, - String fleetName) throws NotFoundException { + + private List> getLogHierarchy(String leaderboardName, String raceColumnName, String fleetName) + throws NotFoundException { List> result = new ArrayList<>(); RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); - - if (raceLog != null){ + + if (raceLog != null) { result.add(raceLog); } - + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); if (leaderboard instanceof HasRegattaLike) { result.add(((HasRegattaLike) leaderboard).getRegattaLike().getRegattaLog()); } return result; } - - private List getDeviceMappings(RegattaLog regattaLog) - throws TransformationException { + + private List getDeviceMappings(RegattaLog regattaLog) throws TransformationException { List result = new ArrayList(); - for (List> list : new RegattaLogDeviceMappingFinder<>( - regattaLog).analyze().values()) { + for (List> list : new RegattaLogDeviceMappingFinder<>(regattaLog).analyze() + .values()) { for (DeviceMapping mapping : list) { result.add(convertToDeviceMappingDTO(mapping)); } } return result; } - + @Override - public void addDeviceMappingToRegattaLog(String leaderboardName, - DeviceMappingDTO dto) throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException { + public void addDeviceMappingToRegattaLog(String leaderboardName, DeviceMappingDTO dto) + throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException { RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); DeviceMapping mapping = convertToDeviceMapping(dto); TimePoint now = MillisecondsTimePoint.now(); @@ -6304,31 +6716,30 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S TimePoint from = mapping.getTimeRange().hasOpenBeginning() ? null : mapping.getTimeRange().from(); TimePoint to = mapping.getTimeRange().hasOpenEnd() ? null : mapping.getTimeRange().to(); if (dto.mappedTo instanceof MarkDTO) { - Mark mark = convertToMark(((MarkDTO) dto.mappedTo), true); - event = new RegattaLogDeviceMarkMappingEventImpl(now, now, getService().getServerAuthor(), UUID.randomUUID(), - mark, mapping.getDevice(), from, to); + Mark mark = convertToMark(((MarkDTO) dto.mappedTo), true); + event = new RegattaLogDeviceMarkMappingEventImpl(now, now, getService().getServerAuthor(), + UUID.randomUUID(), mark, mapping.getDevice(), from, to); } else if (dto.mappedTo instanceof CompetitorWithBoatDTO) { - Competitor competitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString( - ((CompetitorWithBoatDTO) dto.mappedTo).getIdAsString()); + Competitor competitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorByIdAsString(((CompetitorWithBoatDTO) dto.mappedTo).getIdAsString()); if (mapping.getDevice().getIdentifierType().equals(ExpeditionSensorDeviceIdentifier.TYPE)) { - event = new RegattaLogDeviceCompetitorExpeditionExtendedMappingEventImpl( - now, now, getService().getServerAuthor(), UUID.randomUUID(), - competitor, mapping.getDevice(), from, to); + event = new RegattaLogDeviceCompetitorExpeditionExtendedMappingEventImpl(now, now, + getService().getServerAuthor(), UUID.randomUUID(), competitor, mapping.getDevice(), from, to); } else { - event = new RegattaLogDeviceCompetitorMappingEventImpl(now, now, getService().getServerAuthor(), UUID.randomUUID(), - competitor, mapping.getDevice(), from, to); + event = new RegattaLogDeviceCompetitorMappingEventImpl(now, now, getService().getServerAuthor(), + UUID.randomUUID(), competitor, mapping.getDevice(), from, to); } } else if (dto.mappedTo instanceof BoatDTO) { final Boat boat = getService().getCompetitorAndBoatStore() .getExistingBoatByIdAsString(((BoatDTO) dto.mappedTo).getIdAsString()); - event = new RegattaLogDeviceBoatMappingEventImpl(now, now, getService().getServerAuthor(), UUID.randomUUID(), - boat, mapping.getDevice(), from, to); + event = new RegattaLogDeviceBoatMappingEventImpl(now, now, getService().getServerAuthor(), + UUID.randomUUID(), boat, mapping.getDevice(), from, to); } else { throw new RuntimeException("Can only map devices to competitors, boats or marks"); } regattaLog.add(event); } - + @Override public void addTypedDeviceMappingToRegattaLog(String leaderboardName, TypedDeviceMappingDTO dto) throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException { @@ -6351,31 +6762,34 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } regattaLog.add(event); } - + @Override public List getDeserializableDeviceIdentifierTypes() { List result = new ArrayList(); - for (ServiceReference reference : - deviceIdentifierStringSerializationHandlerTracker.getServiceReferences()) { + for (ServiceReference reference : deviceIdentifierStringSerializationHandlerTracker + .getServiceReferences()) { result.add((String) reference.getProperty(TypeBasedServiceFinder.TYPE)); } return result; } - + private DeviceMapping convertToDeviceMapping(DeviceMappingDTO dto) throws NoCorrespondingServiceRegisteredException, TransformationException { - DeviceIdentifier device = deserializeDeviceIdentifier(dto.deviceIdentifier.deviceType, dto.deviceIdentifier.deviceId); + DeviceIdentifier device = deserializeDeviceIdentifier(dto.deviceIdentifier.deviceType, + dto.deviceIdentifier.deviceId); TimePoint from = dto.from == null ? null : new MillisecondsTimePoint(dto.from); TimePoint to = dto.to == null ? null : new MillisecondsTimePoint(dto.to); TimeRange timeRange = new TimeRangeImpl(from, to); if (dto.mappedTo instanceof MarkDTO) { Mark mark = convertToMark(((MarkDTO) dto.mappedTo), true); - //expect UUIDs - return new DeviceMappingImpl(mark, device, timeRange, dto.originalRaceLogEventIds, RegattaLogDeviceMarkMappingEventImpl.class); + // expect UUIDs + return new DeviceMappingImpl(mark, device, timeRange, dto.originalRaceLogEventIds, + RegattaLogDeviceMarkMappingEventImpl.class); } else if (dto.mappedTo instanceof CompetitorWithBoatDTO) { - Competitor competitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString( - ((CompetitorWithBoatDTO) dto.mappedTo).getIdAsString()); - return new DeviceMappingImpl(competitor, device, timeRange, dto.originalRaceLogEventIds, RegattaLogDeviceCompetitorMappingEventImpl.class); + Competitor competitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorByIdAsString(((CompetitorWithBoatDTO) dto.mappedTo).getIdAsString()); + return new DeviceMappingImpl(competitor, device, timeRange, dto.originalRaceLogEventIds, + RegattaLogDeviceCompetitorMappingEventImpl.class); } else if (dto.mappedTo instanceof BoatDTO) { final Boat boat = getService().getCompetitorAndBoatStore() .getExistingBoatByIdAsString(dto.mappedTo.getIdAsString()); @@ -6386,7 +6800,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } - private void closeOpenEndedDeviceMapping(RegattaLog regattaLog, DeviceMappingDTO mappingDTO, Date closingTimePoint) throws TransformationException, UnableToCloseDeviceMappingException { + private void closeOpenEndedDeviceMapping(RegattaLog regattaLog, DeviceMappingDTO mappingDTO, Date closingTimePoint) + throws TransformationException, UnableToCloseDeviceMappingException { boolean successfullyClosed = false; List closingEvents = null; regattaLog.lockForRead(); @@ -6395,8 +6810,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (event != null) { successfullyClosed = true; DeviceMapping mapping = convertToDeviceMapping(mappingDTO); - closingEvents = new RegattaLogOpenEndedDeviceMappingCloser(regattaLog, mapping, getService().getServerAuthor(), - new MillisecondsTimePoint(closingTimePoint)).analyze(); + closingEvents = new RegattaLogOpenEndedDeviceMappingCloser(regattaLog, mapping, + getService().getServerAuthor(), new MillisecondsTimePoint(closingTimePoint)).analyze(); } } finally { regattaLog.unlockAfterRead(); @@ -6410,37 +6825,37 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S throw new UnableToCloseDeviceMappingException(); } } - + @Override public void revokeRaceAndRegattaLogEvents(String leaderboardName, String raceColumnName, String fleetName, List eventIds) throws NotRevokableException, NotFoundException { List> logs = getLogHierarchy(leaderboardName, raceColumnName, fleetName); revokeEventsFromLogs(logs, eventIds); } - + @Override - public void revokeRaceAndRegattaLogEvents(String leaderboardName, - List eventIds) throws NotRevokableException, DoesNotHaveRegattaLogException { + public void revokeRaceAndRegattaLogEvents(String leaderboardName, List eventIds) + throws NotRevokableException, DoesNotHaveRegattaLogException { List> logs = getLogHierarchy(leaderboardName); revokeEventsFromLogs(logs, eventIds); } - - private void revokeEventsFromLogs(List> logs, List eventIds) throws NotRevokableException{ + + private void revokeEventsFromLogs(List> logs, List eventIds) throws NotRevokableException { boolean eventRevoked = false; for (Serializable idToRevoke : eventIds) { eventRevoked = false; for (AbstractLog abstractLog : logs) { eventRevoked = revokeEvent(eventRevoked, idToRevoke, abstractLog); } - if (!eventRevoked){ - logger.warning("Could not revoke event with id "+idToRevoke); + if (!eventRevoked) { + logger.warning("Could not revoke event with id " + idToRevoke); } } } - private , VisitorT> boolean revokeEvent(boolean eventRevoked, Serializable idToRevoke, AbstractLog abstractLog) - throws NotRevokableException { - final EventT event; + private , VisitorT> boolean revokeEvent(boolean eventRevoked, + Serializable idToRevoke, AbstractLog abstractLog) throws NotRevokableException { + final EventT event; abstractLog.lockForRead(); try { event = abstractLog.getEventById(idToRevoke); @@ -6448,21 +6863,23 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S abstractLog.unlockAfterRead(); } if (event != null) { - abstractLog.revokeEvent(getService().getServerAuthor(), event, "revoke triggered by GWT user action"); + abstractLog.revokeEvent(getService().getServerAuthor(), event, "revoke triggered by GWT user action"); eventRevoked = true; } return eventRevoked; } - + @Override - public void startRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, final boolean trackWind, final boolean correctWindByDeclination) + public void startRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, + final boolean trackWind, final boolean correctWindByDeclination) throws NotDenotedForRaceLogTrackingException, Exception { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); Fleet fleet = raceColumn.getFleetByName(fleetName); - getRaceLogTrackingAdapter().startTracking(getService(), leaderboard, raceColumn, fleet, trackWind, correctWindByDeclination); + getRaceLogTrackingAdapter().startTracking(getService(), leaderboard, raceColumn, fleet, trackWind, + correctWindByDeclination); } - + @Override public void startRaceLogTracking(List> leaderboardRaceColumnFleetNames, final boolean trackWind, final boolean correctWindByDeclination) @@ -6472,17 +6889,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S leaderboardRaceColumnFleetName.getC(), trackWind, correctWindByDeclination); } } - + @Override public Collection getGPSFixImporterTypes() { return getRegisteredImporterTypes(GPSFixImporter.class); } - + @Override public Collection getSensorDataImporterTypes() { return getRegisteredImporterTypes(DoubleVectorFixImporter.class); } - + private Collection getRegisteredImporterTypes(Class referenceClass) { Set result = new HashSet<>(); for (ServiceReference reference : getRegisteredServiceReferences(referenceClass)) { @@ -6490,7 +6907,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return result; } - + private S getRegisteredImporter(Class referenceClass, String type) throws NoCorrespondingServiceRegisteredException { for (ServiceReference reference : getRegisteredServiceReferences(referenceClass)) { @@ -6499,9 +6916,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return importer; } } - throw new NoCorrespondingServiceRegisteredException("No importer service found!", type, referenceClass.getName()); + throw new NoCorrespondingServiceRegisteredException("No importer service found!", type, + referenceClass.getName()); } - + private Collection> getRegisteredServiceReferences(Class referenceClass) { try { return Activator.getDefault().getServiceReferences(referenceClass, null); @@ -6510,7 +6928,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return Collections.emptyList(); } - + @Override public List getTrackFileImportDeviceIds(List uuids) throws NoCorrespondingServiceRegisteredException, TransformationException { @@ -6523,8 +6941,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S TimeRange timeRange = getService().getSensorFixStore().getTimeRangeCoveredByFixes(device); Date from = timeRange == null ? null : timeRange.from().asDate(); Date to = timeRange == null ? null : timeRange.to().asDate(); - result.add(new TrackFileImportDeviceIdentifierDTO(uuidAsString, device.getFileName(), device.getTrackName(), - numFixes, from, to)); + result.add(new TrackFileImportDeviceIdentifierDTO(uuidAsString, device.getFileName(), + device.getTrackName(), numFixes, from, to)); } return result; } catch (Exception e) { @@ -6542,7 +6960,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S newStartTimeReceived == null ? null : new MillisecondsTimePoint(newStartTimeReceived)); return baseDomainFactory.createRaceDTO(getService(), false, regattaAndRaceIdentifier, trackedRace); } - + @Override public ArrayList getEventsForLeaderboard(String leaderboardName) { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); @@ -6560,7 +6978,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public Map getCompetitorRaceLogMarkPassingData(String leaderboardName, String raceColumnName, String fleetName, CompetitorDTO competitor) { + public Map getCompetitorRaceLogMarkPassingData(String leaderboardName, String raceColumnName, + String fleetName, CompetitorDTO competitor) { Map result = new HashMap<>(); RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); for (Triple fixedEvent : new MarkPassingDataFinder(raceLog).analyze()) { @@ -6578,13 +6997,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void updateFixedMarkPassing(String leaderboardName, String raceColumnName, String fleetName, Integer indexOfWaypoint, - Date dateOfMarkPassing, CompetitorDTO competitorDTO) { + public void updateFixedMarkPassing(String leaderboardName, String raceColumnName, String fleetName, + Integer indexOfWaypoint, Date dateOfMarkPassing, CompetitorDTO competitorDTO) { RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); Competitor competitor = getCompetitor(competitorDTO); RaceLogFixedMarkPassingEvent oldFixedMarkPassingEvent = null; for (RaceLogEvent event : raceLog.getUnrevokedEvents()) { - if (event instanceof RaceLogFixedMarkPassingEventImpl && event.getInvolvedCompetitors().contains(competitor)) { + if (event instanceof RaceLogFixedMarkPassingEventImpl + && event.getInvolvedCompetitors().contains(competitor)) { RaceLogFixedMarkPassingEvent fixedEvent = (RaceLogFixedMarkPassingEvent) event; if (Util.equalsWithNull(fixedEvent.getZeroBasedIndexOfPassedWaypoint(), indexOfWaypoint)) { oldFixedMarkPassingEvent = fixedEvent; @@ -6599,12 +7019,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } if (dateOfMarkPassing != null) { - raceLog.add(new RaceLogFixedMarkPassingEventImpl(MillisecondsTimePoint.now(), getService() - .getServerAuthor(), competitor, raceLog.getCurrentPassId(), + raceLog.add(new RaceLogFixedMarkPassingEventImpl(MillisecondsTimePoint.now(), + getService().getServerAuthor(), competitor, raceLog.getCurrentPassId(), new MillisecondsTimePoint(dateOfMarkPassing), indexOfWaypoint)); } } - + @Override public void updateSuppressedMarkPassings(String leaderboardName, String raceColumnName, String fleetName, Integer newZeroBasedIndexOfSuppressedMarkPassing, CompetitorDTO competitorDTO) { @@ -6613,12 +7033,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Competitor competitor = getCompetitor(competitorDTO); NavigableSet unrevokedEvents = raceLog.getUnrevokedEvents(); for (RaceLogEvent event : unrevokedEvents) { - if (event instanceof RaceLogSuppressedMarkPassingsEvent && event.getInvolvedCompetitors().contains(competitor)) { + if (event instanceof RaceLogSuppressedMarkPassingsEvent + && event.getInvolvedCompetitors().contains(competitor)) { oldSuppressedMarkPassingEvent = (RaceLogSuppressedMarkPassingsEvent) event; break; } } - + final boolean create; final boolean revoke; if (oldSuppressedMarkPassingEvent == null) { @@ -6635,7 +7056,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S create = false; } else { boolean equal = Util.equalsWithNull(newZeroBasedIndexOfSuppressedMarkPassing, - oldSuppressedMarkPassingEvent.getZeroBasedIndexOfFirstSuppressedWaypoint()); + oldSuppressedMarkPassingEvent.getZeroBasedIndexOfFirstSuppressedWaypoint()); create = !equal; revoke = !equal; } @@ -6647,18 +7068,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } if (create) { - raceLog.add(new RaceLogSuppressedMarkPassingsEventImpl(MillisecondsTimePoint.now(), getService() - .getServerAuthor(), competitor, raceLog.getCurrentPassId(), + raceLog.add(new RaceLogSuppressedMarkPassingsEventImpl(MillisecondsTimePoint.now(), + getService().getServerAuthor(), competitor, raceLog.getCurrentPassId(), newZeroBasedIndexOfSuppressedMarkPassing)); } } @Override - public Map getCompetitorMarkPassings(RegattaAndRaceIdentifier race, CompetitorDTO competitorDTO, boolean waitForCalculations) { + public Map getCompetitorMarkPassings(RegattaAndRaceIdentifier race, CompetitorDTO competitorDTO, + boolean waitForCalculations) { Map result = new HashMap<>(); final TrackedRace trackedRace = getExistingTrackedRace(race); if (trackedRace != null) { - Competitor competitor = getCompetitorByIdAsString(trackedRace.getRace().getCompetitors(), competitorDTO.getIdAsString()); + Competitor competitor = getCompetitorByIdAsString(trackedRace.getRace().getCompetitors(), + competitorDTO.getIdAsString()); Set competitorMarkPassings; competitorMarkPassings = trackedRace.getMarkPassings(competitor, waitForCalculations); Iterable waypoints = trackedRace.getRace().getCourse().getWaypoints(); @@ -6683,15 +7106,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } for (double windInKnots = 0.1; windInKnots < 30; windInKnots = windInKnots + 0.1) { for (LegType legType : new LegType[] { LegType.UPWIND, LegType.DOWNWIND }) { - for (Tack tack : new Tack[] { Tack.PORT, Tack.STARBOARD }) { + for (Tack tack : new Tack[] { Tack.PORT, Tack.STARBOARD }) { try { SpeedWithBearingWithConfidence averageUpwindStarboardRegression = getService() - .getPolarDataService().getAverageSpeedWithBearing(boatClass, - new KnotSpeedImpl(windInKnots), legType, tack); + .getPolarDataService() + .getAverageSpeedWithBearing(boatClass, new KnotSpeedImpl(windInKnots), legType, tack); - regressionSpeedDataLists.get(new Pair(legType, tack)).add( - new Pair(windInKnots, averageUpwindStarboardRegression.getObject() - .getKnots())); + regressionSpeedDataLists.get(new Pair(legType, tack)) + .add(new Pair(windInKnots, + averageUpwindStarboardRegression.getObject().getKnots())); } catch (NotEnoughDataHasBeenAddedException e) { // Do not add a point to the result } @@ -6703,14 +7126,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return data; } - + private FileStorageService getFileStorageService(String name) { if (name == null || name.equals("")) { return null; } return getService().getFileStorageManagementService().getFileStorageService(name); } - + private Locale getLocale(String localeInfoName) { return ResourceBundleStringMessages.Util.getLocaleFor(localeInfoName); } @@ -6718,7 +7141,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public FileStorageServiceDTO[] getAvailableFileStorageServices(String localeInfoName) { List serviceDtos = new ArrayList<>(); - final FileStorageManagementService fileStorageManagementService = getService().getFileStorageManagementService(); + final FileStorageManagementService fileStorageManagementService = getService() + .getFileStorageManagementService(); if (fileStorageManagementService != null) { for (FileStorageService s : fileStorageManagementService.getAvailableFileStorageServices()) { serviceDtos.add(FileStorageServiceDTOUtils.convert(s, getLocale(localeInfoName))); @@ -6732,15 +7156,16 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (Entry p : properties.entrySet()) { try { getService().getFileStorageManagementService() - .setFileStorageServiceProperty(getFileStorageService(serviceName), p.getKey(), p.getValue()); + .setFileStorageServiceProperty(getFileStorageService(serviceName), p.getKey(), p.getValue()); } catch (NoCorrespondingServiceRegisteredException | IllegalArgumentException e) { - //ignore, doing refresh afterwards anyways + // ignore, doing refresh afterwards anyways } } } @Override - public FileStorageServicePropertyErrorsDTO testFileStorageServiceProperties(String serviceName, String localeInfoName) throws IOException { + public FileStorageServicePropertyErrorsDTO testFileStorageServiceProperties(String serviceName, + String localeInfoName) throws IOException { try { FileStorageService service = getFileStorageService(serviceName); if (service != null) { @@ -6760,7 +7185,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public String getActiveFileStorageServiceName() { try { - final FileStorageService activeFileStorageService = getService().getFileStorageManagementService().getActiveFileStorageService(); + final FileStorageService activeFileStorageService = getService().getFileStorageManagementService() + .getActiveFileStorageService(); return activeFileStorageService == null ? null : activeFileStorageService.getName(); } catch (NoCorrespondingServiceRegisteredException e) { return null; @@ -6777,18 +7203,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S competitors.add(getCompetitor(c)); } Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - getRaceLogTrackingAdapter().inviteCompetitorsForTrackingViaEmail(event, leaderboard, serverUrlWithoutTrailingSlash, - competitors, iOSAppUrl, androidAppUrl, getLocale(localeInfoName)); + getRaceLogTrackingAdapter().inviteCompetitorsForTrackingViaEmail(event, leaderboard, + serverUrlWithoutTrailingSlash, competitors, iOSAppUrl, androidAppUrl, getLocale(localeInfoName)); } - + @Override public void inviteBuoyTenderViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, String leaderboardName, String emails, String iOSAppUrl, String androidAppUrl, String localeInfoName) throws MailException { Event event = getService().getEvent(eventDto.id); Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - getRaceLogTrackingAdapter().inviteBuoyTenderViaEmail(event, leaderboard, serverUrlWithoutTrailingSlash, - emails, iOSAppUrl, androidAppUrl, getLocale(localeInfoName)); + getRaceLogTrackingAdapter().inviteBuoyTenderViaEmail(event, leaderboard, serverUrlWithoutTrailingSlash, emails, + iOSAppUrl, androidAppUrl, getLocale(localeInfoName)); } @Override @@ -6797,7 +7223,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (event == null) { throw new RuntimeException("Event not found"); } - + ArrayList result = new ArrayList<>(); for (LeaderboardGroup lg : event.getLeaderboardGroups()) { result.add(convertToLeaderboardGroupDTO(lg, /* withGeoLocationData */false, true)); @@ -6807,18 +7233,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S /** * Gets all Marks defined in the RegattaLog and the trackedRace - * @throws DoesNotHaveRegattaLogException + * + * @throws DoesNotHaveRegattaLogException */ @Override public Iterable getMarksInRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException { final Leaderboard l = getService().getLeaderboardByName(leaderboardName); - if (! (l instanceof HasRegattaLike)) { + if (!(l instanceof HasRegattaLike)) { throw new DoesNotHaveRegattaLogException(); } final LeaderboardThatHasRegattaLike leaderboard = (LeaderboardThatHasRegattaLike) l; final RegattaLog regattaLog = leaderboard.getRegattaLike().getRegattaLog(); final Set markDTOs = new HashSet<>(); - final List markEvents = new AllEventsOfTypeFinder<>(regattaLog, /* only unrevoked */ true, RegattaLogDefineMarkEvent.class).analyze(); + final List markEvents = new AllEventsOfTypeFinder<>(regattaLog, /* only unrevoked */ true, + RegattaLogDefineMarkEvent.class).analyze(); for (RegattaLogEvent regattaLogEvent : markEvents) { final RegattaLogDefineMarkEvent defineMarkEvent = (RegattaLogDefineMarkEvent) regattaLogEvent; markDTOs.add(convertToMarkDTO(leaderboard, defineMarkEvent.getMark())); @@ -6827,13 +7255,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void closeOpenEndedDeviceMapping(String leaderboardName, DeviceMappingDTO mappingDTO, Date closingTimePoint) throws TransformationException, DoesNotHaveRegattaLogException, UnableToCloseDeviceMappingException { + public void closeOpenEndedDeviceMapping(String leaderboardName, DeviceMappingDTO mappingDTO, Date closingTimePoint) + throws TransformationException, DoesNotHaveRegattaLogException, UnableToCloseDeviceMappingException { RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); closeOpenEndedDeviceMapping(regattaLog, mappingDTO, closingTimePoint); } /** * Gets all the logs corresponding to a leaderboard. This includes all the RaceLogs of the leaderBoard's raceColumns + * * @param leaderboardName * @return */ @@ -6855,7 +7285,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } return result; - } + } public boolean doesRegattaLogContainCompetitors(String leaderboardName) throws DoesNotHaveRegattaLogException { RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); @@ -6884,29 +7314,31 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public Collection getCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, - String fleetName) throws NotFoundException { + public Collection getCompetitorRegistrationsForRace(String leaderboardName, + String raceColumnName, String fleetName) throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); return convertToCompetitorAndBoatDTOs(raceColumn.getAllCompetitorsAndTheirBoats(fleet)); } - + @Override - public Collection getCompetitorRegistrationsForLeaderboard(String leaderboardName) throws NotFoundException { + public Collection getCompetitorRegistrationsForLeaderboard(String leaderboardName) + throws NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); return convertToCompetitorDTOs(leaderboard.getAllCompetitors()); } @Override - public Collection getCompetitorRegistrationsInRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException, NotFoundException { + public Collection getCompetitorRegistrationsInRegattaLog(String leaderboardName) + throws DoesNotHaveRegattaLogException, NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (! (leaderboard instanceof HasRegattaLike)) { + if (!(leaderboard instanceof HasRegattaLike)) { throw new DoesNotHaveRegattaLogException(); } HasRegattaLike regattaLikeLeaderboard = ((HasRegattaLike) leaderboard); return convertToCompetitorDTOs(regattaLikeLeaderboard.getCompetitorsRegisteredInRegattaLog()); } - + @Override public List getCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { @@ -6914,18 +7346,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Fleet fleet = getFleetByName(raceColumn, fleetName); return convertToCompetitorAndBoatDTOs(raceColumn.getCompetitorsRegisteredInRacelog(fleet)); } - + @Override - public Map getCompetitorAndBoatRegistrationsInRaceLog(String leaderboardName, String raceColumnName, - String fleetName) throws NotFoundException { + public Map getCompetitorAndBoatRegistrationsInRaceLog(String leaderboardName, + String raceColumnName, String fleetName) throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); - Map competitorsAndBoatsRegisteredInRacelog = raceColumn.getCompetitorsRegisteredInRacelog(fleet); + Map competitorsAndBoatsRegisteredInRacelog = raceColumn + .getCompetitorsRegisteredInRacelog(fleet); return baseDomainFactory.convertToCompetitorAndBoatDTOs(competitorsAndBoatsRegisteredInRacelog); } @Override - public Collection getBoatRegistrationsInRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException, NotFoundException { + public Collection getBoatRegistrationsInRegattaLog(String leaderboardName) + throws DoesNotHaveRegattaLogException, NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); if (!(leaderboard instanceof HasRegattaLike)) { throw new DoesNotHaveRegattaLogException(); @@ -6933,28 +7367,28 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S HasRegattaLike regattaLikeLeaderboard = ((HasRegattaLike) leaderboard); return convertToBoatDTOs(regattaLikeLeaderboard.getBoatsRegisteredInRegattaLog()); } - + @Override public void setBoatRegistrationsInRegattaLog(String leaderboardName, Set boatDTOs) throws DoesNotHaveRegattaLogException, NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (!(leaderboard instanceof HasRegattaLike)){ + if (!(leaderboard instanceof HasRegattaLike)) { throw new DoesNotHaveRegattaLogException(); } - + Set boatsToRegister = new HashSet(); for (BoatDTO dto : boatDTOs) { boatsToRegister.add(getBoat(dto)); } - + HasRegattaLike hasRegattaLike = (HasRegattaLike) leaderboard; Iterable boatsToRemove = leaderboard.getAllBoats(); HashSet boatSetToRemove = new HashSet<>(); Util.addAll(boatsToRemove, boatSetToRemove); filterBoatDuplicates(boatsToRegister, boatSetToRemove); - + hasRegattaLike.deregisterBoats(boatSetToRemove); - hasRegattaLike.registerBoats(boatsToRegister); + hasRegattaLike.registerBoats(boatsToRegister); } @Override @@ -6970,46 +7404,48 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Fleet fleet = getFleetByName(raceColumn, fleetName); return raceColumn.isCompetitorRegistrationInRacelogEnabled(fleet); } - - private Fleet getFleetByName(RaceColumn raceColumn, String fleetName) throws NotFoundException{ + + private Fleet getFleetByName(RaceColumn raceColumn, String fleetName) throws NotFoundException { Fleet fleet = raceColumn.getFleetByName(fleetName); - if (fleet == null){ - throw new NotFoundException("fleet with name "+fleetName+" not found"); + if (fleet == null) { + throw new NotFoundException("fleet with name " + fleetName + " not found"); } return fleet; } - - private Leaderboard getLeaderboardByName(String leaderboardName) throws NotFoundException{ + + private Leaderboard getLeaderboardByName(String leaderboardName) throws NotFoundException { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - if (leaderboard == null){ - throw new NotFoundException("Leaderboard with name "+leaderboardName+" not found"); + if (leaderboard == null) { + throw new NotFoundException("Leaderboard with name " + leaderboardName + " not found"); } return leaderboard; } - - private RaceColumn getRaceColumn(String leaderboardName, String raceColumnName) throws NotFoundException{ + + private RaceColumn getRaceColumn(String leaderboardName, String raceColumnName) throws NotFoundException { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - if (leaderboard == null){ - throw new NotFoundException("leaderboard with name "+leaderboardName+" not found"); - } + if (leaderboard == null) { + throw new NotFoundException("leaderboard with name " + leaderboardName + " not found"); + } RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - if (raceColumn == null){ - throw new NotFoundException("raceColumn with name "+raceColumnName+" not found"); + if (raceColumn == null) { + throw new NotFoundException("raceColumn with name " + raceColumnName + " not found"); } return raceColumn; } @Override - public void disableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) throws NotRevokableException, NotFoundException { - if (areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)){ + public void disableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) + throws NotRevokableException, NotFoundException { + if (areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)) { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); raceColumn.disableCompetitorRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); } } @Override - public void enableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) throws IllegalArgumentException, NotFoundException { - if (!areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)){ + public void enableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) + throws IllegalArgumentException, NotFoundException { + if (!areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)) { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); raceColumn.enableCompetitorRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); } @@ -7030,14 +7466,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (Fleet fleet : raceColumn.getFleets()) { RaceLog raceLog = raceColumn.getRaceLog(fleet); if (raceLog != raceLogToIgnore) { - LastPublishedCourseDesignFinder finder = new LastPublishedCourseDesignFinder(raceLog, /* onlyCoursesWithValidWaypointList */ true); + LastPublishedCourseDesignFinder finder = new LastPublishedCourseDesignFinder(raceLog, + /* onlyCoursesWithValidWaypointList */ true); CourseBase course = finder.analyze(); if (course != null) { for (Waypoint waypoint : course.getWaypoints()) { for (Mark mark : waypoint.getMarks()) { if (markIds.contains(mark.getId().toString())) { - racesContainingMarksToDeleteInCourse.add(raceColumn.getName() + "/" - + fleet.getName()); + racesContainingMarksToDeleteInCourse + .add(raceColumn.getName() + "/" + fleet.getName()); marksAreUsedInOtherRaceLogs = true; } } @@ -7045,13 +7482,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } } - } + } StringBuilder racesInCollision = new StringBuilder(); for (String raceName : racesContainingMarksToDeleteInCourse) { - racesInCollision.append(raceName+", "); + racesInCollision.append(raceName + ", "); } - return new Pair(marksAreUsedInOtherRaceLogs, - racesInCollision.substring(0, Math.max(0, racesInCollision.length()-2))); + return new Pair(marksAreUsedInOtherRaceLogs, + racesInCollision.substring(0, Math.max(0, racesInCollision.length() - 2))); } @Override @@ -7060,7 +7497,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); return getDeviceMappings(regattaLog); } - + @Override public Iterable getMarksInTrackedRace(String leaderboardName, String raceColumnName, String fleetName) { final List marks = new ArrayList<>(); @@ -7088,7 +7525,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return new MarkTracksDTO(markTracks); } - + private MarkTrackDTO getMarkTrack(Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet, String markIdAsString) { MarkDTO markDTO = null; @@ -7140,9 +7577,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return null; } - + @Override - public MarkTrackDTO getMarkTrack(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString) { + public MarkTrackDTO getMarkTrack(String leaderboardName, String raceColumnName, String fleetName, + String markIdAsString) { final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard != null) { final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -7155,10 +7593,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return null; } - + /** - * Uses all fixed from {@code track} with the outliers removed, {@link #convertToGPSFixDTO(GPSFix) converts} each - * of them to a {@link GPSFixDTO} and adds them to the resulting list. + * Uses all fixed from {@code track} with the outliers removed, {@link #convertToGPSFixDTO(GPSFix) converts} each of + * them to a {@link GPSFixDTO} and adds them to the resulting list. */ private Iterable convertToGPSFixDTOTrack(Track track) { final List result = new ArrayList<>(); @@ -7172,7 +7610,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return result; } - + private GPSFixDTO convertToGPSFixDTO(GPSFix fix) { final GPSFixDTO result; if (fix == null) { @@ -7193,7 +7631,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (raceColumn != null) { final TimePoint fixTimePoint = new MillisecondsTimePoint(fix.timepoint); final RegattaLog regattaLog = raceColumn.getRegattaLog(); - final BaseRegattaLogDeviceMappingFinder mappingFinder = new RegattaLogDeviceMarkMappingFinder(regattaLog); + final BaseRegattaLogDeviceMappingFinder mappingFinder = new RegattaLogDeviceMarkMappingFinder( + regattaLog); final Fleet fleet = raceColumn.getFleetByName(fleetName); if (fleet != null) { for (final Mark mark : raceColumn.getAvailableMarks(fleet)) { @@ -7211,14 +7650,16 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO fix) throws NotRevokableException { + public void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO fix) throws NotRevokableException { final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard != null) { final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); if (raceColumn != null) { final TimePoint fixTimePoint = new MillisecondsTimePoint(fix.timepoint); final RegattaLog regattaLog = raceColumn.getRegattaLog(); - final BaseRegattaLogDeviceMappingFinder mappingFinder = new RegattaLogDeviceMarkMappingFinder(regattaLog); + final BaseRegattaLogDeviceMappingFinder mappingFinder = new RegattaLogDeviceMarkMappingFinder( + regattaLog); final Fleet fleet = raceColumn.getFleetByName(fleetName); if (fleet != null) { for (final Mark mark : raceColumn.getAvailableMarks(fleet)) { @@ -7232,7 +7673,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void addMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO newFix) { + public void addMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO newFix) { final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard != null) { final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -7280,11 +7722,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public Map, Pair> getTrackingTimes( Collection> leaderboardRaceColumnFleetNames) { - Map, Pair> trackingTimes = new HashMap<>(); + Map, Pair> trackingTimes = new HashMap<>(); for (Triple leaderboardRaceColumnFleetName : leaderboardRaceColumnFleetNames) { try { - trackingTimes.put(leaderboardRaceColumnFleetName, getTrackingTimes(leaderboardRaceColumnFleetName.getA(), - leaderboardRaceColumnFleetName.getB(), leaderboardRaceColumnFleetName.getC())); + trackingTimes.put(leaderboardRaceColumnFleetName, + getTrackingTimes(leaderboardRaceColumnFleetName.getA(), leaderboardRaceColumnFleetName.getB(), + leaderboardRaceColumnFleetName.getC())); } catch (Exception e) { trackingTimes.put(leaderboardRaceColumnFleetName, null); } @@ -7296,12 +7739,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public Collection getEliminatedCompetitors(String leaderboardName) { final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard == null || !(leaderboard instanceof RegattaLeaderboardWithEliminations)) { - throw new IllegalArgumentException(leaderboardName+" does not match a regatta leaderboard with eliminations"); + throw new IllegalArgumentException( + leaderboardName + " does not match a regatta leaderboard with eliminations"); } final RegattaLeaderboardWithEliminations rlwe = (RegattaLeaderboardWithEliminations) leaderboard; return convertToCompetitorDTOs(rlwe.getEliminatedCompetitors()); } - + @Override public void setEliminatedCompetitors(String leaderboardName, Set newEliminatedCompetitorDTOs) { Set newEliminatedCompetitors = new HashSet<>(); @@ -7312,7 +7756,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public Iterable determineDetailTypesForCompetitorChart(String leaderboardGroupName, RegattaAndRaceIdentifier identifier) { + public Iterable determineDetailTypesForCompetitorChart(String leaderboardGroupName, + RegattaAndRaceIdentifier identifier) { final List availableDetailsTypes = new ArrayList<>(); availableDetailsTypes.addAll(DetailType.getAutoplayDetailTypesForChart()); availableDetailsTypes.removeAll(DetailType.getRaceBravoDetailTypes()); @@ -7320,7 +7765,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (trackedRace != null) { boolean hasBravoTrack = false; boolean hasExtendedBravoFixes = false; - for (BravoFixTrack track : trackedRace.>getSensorTracks(BravoFixTrack.TRACK_NAME)) { + for (BravoFixTrack track : trackedRace + .> getSensorTracks(BravoFixTrack.TRACK_NAME)) { hasBravoTrack = true; if (track.hasExtendedFixes()) { hasExtendedBravoFixes = true; @@ -7371,19 +7817,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S expeditionConnector.removeDeviceConfiguration(deviceConfiguration); } } - + @Override public PairingListTemplateDTO calculatePairingListTemplate(final int flightCount, final int groupCount, final int competitorCount, final int flightMultiplier) { - PairingListTemplate template = getService().createPairingListTemplate(flightCount, groupCount, competitorCount, + PairingListTemplate template = getService().createPairingListTemplate(flightCount, groupCount, competitorCount, flightMultiplier); - return new PairingListTemplateDTO(flightCount, groupCount, competitorCount, flightMultiplier, + return new PairingListTemplateDTO(flightCount, groupCount, competitorCount, flightMultiplier, template.getPairingListTemplate(), template.getQuality()); } - + @Override public PairingListDTO getPairingListFromTemplate(final String leaderboardName, final int flightMultiplier, - final Iterable selectedRaceColumnNames, PairingListTemplateDTO templateDTO) + final Iterable selectedRaceColumnNames, PairingListTemplateDTO templateDTO) throws NotFoundException, PairingListCreationException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); List selectedRaces = new ArrayList(); @@ -7406,15 +7852,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (Pair competitorAndBoatPair : pairingList.getCompetitors(raceColumn, fleet)) { final Boat boat = competitorAndBoatPair.getB(); if (competitorAndBoatPair.getA() != null) { - fleetList.add(new Pair<>( - baseDomainFactory.convertToCompetitorDTO(competitorAndBoatPair.getA()), - new BoatDTO(boat.getId().toString(), boat.getName(), convertToBoatClassDTO(boat.getBoatClass()), - boat.getSailID(), + fleetList.add(new Pair<>(baseDomainFactory.convertToCompetitorDTO(competitorAndBoatPair.getA()), + new BoatDTO(boat.getId().toString(), boat.getName(), + convertToBoatClassDTO(boat.getBoatClass()), boat.getSailID(), boat.getColor()))); } else { fleetList.add(new Pair<>(/* no competitor */ null, - new BoatDTO(boat.getId().toString(), boat.getName(), convertToBoatClassDTO(boat.getBoatClass()), - boat.getSailID(), + new BoatDTO(boat.getId().toString(), boat.getName(), + convertToBoatClassDTO(boat.getBoatClass()), boat.getSailID(), boat.getColor()))); } } @@ -7424,7 +7869,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return new PairingListDTO(result, Util.asList(selectedRaceColumnNames)); } - + @Override public PairingListDTO getPairingListFromRaceLogs(final String leaderboardName) throws NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); @@ -7438,9 +7883,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S List> fleetList = new ArrayList<>(); for (Pair competitorAndBoatPair : adapter.getCompetitors(raceColumn, fleet)) { final Boat boat = competitorAndBoatPair.getB(); - fleetList.add(new Pair(baseDomainFactory.convertToCompetitorDTO(competitorAndBoatPair.getA()), + fleetList.add(new Pair( + baseDomainFactory.convertToCompetitorDTO(competitorAndBoatPair.getA()), new BoatDTO(boat.getId().toString(), boat.getName(), - convertToBoatClassDTO(boat.getBoatClass()), boat.getSailID(), + convertToBoatClassDTO(boat.getBoatClass()), boat.getSailID(), boat.getColor()))); } if (fleetList.size() > 0) { @@ -7457,7 +7903,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return new PairingListDTO(result, raceColumnNames); } - + @Override public void fillRaceLogsFromPairingListTemplate(final String leaderboardName, final int flightMultiplier, final Iterable selectedFlightNames, final PairingListDTO pairingListDTO) @@ -7492,21 +7938,23 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } if (leaderboard instanceof LeaderboardThatHasRegattaLike && flightMultiplier > 1) { final IsRegattaLike regattaLike = ((LeaderboardThatHasRegattaLike) leaderboard).getRegattaLike(); - logger.info("Updating regatta "+regattaLike.getRegattaLikeIdentifier().getName()+ - ", setting flag that fleets can run in parallel because a pairing list with flight multiplier "+ - flightMultiplier+" has been used."); + logger.info("Updating regatta " + regattaLike.getRegattaLikeIdentifier().getName() + + ", setting flag that fleets can run in parallel because a pairing list with flight multiplier " + + flightMultiplier + " has been used."); regattaLike.setFleetsCanRunInParallelToTrue(); } } - - public List getRaceDisplayNamesFromLeaderboard(String leaderboardName,List raceColumnNames) throws NotFoundException { + + public List getRaceDisplayNamesFromLeaderboard(String leaderboardName, List raceColumnNames) + throws NotFoundException { Leaderboard leaderboard = this.getLeaderboardByName(leaderboardName); List result = new ArrayList<>(); for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { if (raceColumn.hasTrackedRaces()) { if (raceColumnNames.contains(raceColumn.getName())) { for (Fleet fleet : raceColumn.getFleets()) { - if(raceColumn.getTrackedRace(fleet) != null && raceColumn.getTrackedRace(fleet).getRaceIdentifier()!=null) { + if (raceColumn.getTrackedRace(fleet) != null + && raceColumn.getTrackedRace(fleet).getRaceIdentifier() != null) { result.add(raceColumn.getTrackedRace(fleet).getRaceIdentifier().getRaceName()); } else { break; @@ -7517,13 +7965,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S break; } } - if (result.size()==raceColumnNames.size()*Util.size(leaderboard.getRaceColumnByName(raceColumnNames.get(0)).getFleets())) { + if (result.size() == raceColumnNames.size() + * Util.size(leaderboard.getRaceColumnByName(raceColumnNames.get(0)).getFleets())) { return result; } result.clear(); for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - for (Fleet fleet: raceColumn.getFleets()) { - NavigableSet set=raceColumn.getRaceLog(fleet).getUnrevokedEvents(); + for (Fleet fleet : raceColumn.getFleets()) { + NavigableSet set = raceColumn.getRaceLog(fleet).getUnrevokedEvents(); for (RaceLogEvent raceLogEvent : set) { if (raceLogEvent instanceof RaceLogDenoteForTrackingEvent) { RaceLogDenoteForTrackingEvent denoteEvent = (RaceLogDenoteForTrackingEvent) raceLogEvent; @@ -7533,18 +7982,21 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } } - if (result.size()==raceColumnNames.size()*Util.size(leaderboard.getRaceColumnByName(raceColumnNames.get(0)).getFleets())) { + if (result.size() == raceColumnNames.size() + * Util.size(leaderboard.getRaceColumnByName(raceColumnNames.get(0)).getFleets())) { return result; } result.clear(); - for (int count=1;count<=raceColumnNames.size()*Util.size(leaderboard.getRaceColumnByName(raceColumnNames.get(0)).getFleets());count++) { - result.add("Race "+count); + for (int count = 1; count <= raceColumnNames.size() + * Util.size(leaderboard.getRaceColumnByName(raceColumnNames.get(0)).getFleets()); count++) { + result.add("Race " + count); } return result; } @Override - public Iterable getAvailableDetailTypesForLeaderboard(String leaderboardName, RegattaAndRaceIdentifier raceIdentifierOrNull) { + public Iterable getAvailableDetailTypesForLeaderboard(String leaderboardName, + RegattaAndRaceIdentifier raceIdentifierOrNull) { final Set allowed = new HashSet<>(); allowed.addAll(DetailType.getAllNonRestrictedDetailTypes()); final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); @@ -7556,13 +8008,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (raceIdentifierOrNull != null && !raceIdentifierOrNull.equals(race.getRaceIdentifier(fleet))) { continue; } - + final TrackedRace trace = race.getTrackedRace(fleet); if (trace != null) { final DynamicTrackedRace trackedRace = getService().getTrackedRace(trace.getRaceIdentifier()); if (trackedRace != null) { for (BravoFixTrack track : trackedRace - .>getSensorTracks(BravoFixTrack.TRACK_NAME)) { + .> getSensorTracks(BravoFixTrack.TRACK_NAME)) { hasBravoTrack = true; if (track.hasExtendedFixes()) { hasExtendedBravoFixes = true; @@ -7587,7 +8039,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return allowed; } - public SpotDTO getWindFinderSpot(String spotId) throws MalformedURLException, IOException, org.json.simple.parser.ParseException, InterruptedException, ExecutionException { + public SpotDTO getWindFinderSpot(String spotId) throws MalformedURLException, IOException, + org.json.simple.parser.ParseException, InterruptedException, ExecutionException { final SpotDTO result; final WindFinderTrackerFactory windFinderTrackerFactory = windFinderTrackerFactoryServiceTracker.getService(); if (windFinderTrackerFactory != null) { @@ -7602,7 +8055,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return result; } - + @Override public boolean canSliceRace(RegattaAndRaceIdentifier raceIdentifier) { final Regatta regatta = getService().getRegattaByName(raceIdentifier.getRegattaName()); @@ -7613,12 +8066,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S || trackedRace.getStartOfTracking() == null || !isSmartphoneTrackingEnabled(trackedRace)) { result = false; } else { - final Pair raceColumnAndFleetOfRaceToSlice = regattaLeaderboard.getRaceColumnAndFleet(trackedRace); - result = (raceColumnAndFleetOfRaceToSlice != null); // is the TrackedRace associated to the given RegattaLeaderboard? + final Pair raceColumnAndFleetOfRaceToSlice = regattaLeaderboard + .getRaceColumnAndFleet(trackedRace); + result = (raceColumnAndFleetOfRaceToSlice != null); // is the TrackedRace associated to the given + // RegattaLeaderboard? } return result; } - + private boolean isSmartphoneTrackingEnabled(DynamicTrackedRace trackedRace) { boolean result = false; for (RaceLog raceLog : trackedRace.getAttachedRaceLogs()) { @@ -7630,7 +8085,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return result; } - + @Override public SliceRacePreperationDTO prepareForSlicingOfRace(final RegattaAndRaceIdentifier raceIdentifier) { final Leaderboard regattaLeaderboard = getService().getLeaderboardByName(raceIdentifier.getRegattaName()); @@ -7652,13 +8107,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S currentCount++; return new SliceRacePreperationDTO(prefix + currentCount, alreadyUsedRaceNames); } - + @Override public RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException { final Locale locale = getClientLocale(); - - SecurityUtils.getSubject().checkPermission(Permission.MANAGE_TRACKED_RACES.getStringPermissionForObjects(Mode.UPDATE)); + + SecurityUtils.getSubject() + .checkPermission(Permission.MANAGE_TRACKED_RACES.getStringPermissionForObjects(Mode.UPDATE)); if (!canSliceRace(raceIdentifier)) { throw new ServiceException(serverStringMessages.get(locale, "slicingCannotSliceRace")); } @@ -7675,8 +8131,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S || (endOfTrackingOfRaceToSlice != null && endOfTrackingOfRaceToSlice.before(sliceTo))) { throw new ServiceException(serverStringMessages.get(locale, "slicingTimeRangeOutOfBounds")); } - final RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) getService().getLeaderboardByName(raceIdentifier.getRegattaName()); - final Pair raceColumnAndFleetOfRaceToSlice = regattaLeaderboard.getRaceColumnAndFleet(trackedRaceToSlice); + final RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) getService() + .getLeaderboardByName(raceIdentifier.getRegattaName()); + final Pair raceColumnAndFleetOfRaceToSlice = regattaLeaderboard + .getRaceColumnAndFleet(trackedRaceToSlice); // RaceColumns in a RegattaLeaderboard are always RaceColumnInSeries instances final RaceColumnInSeries raceColumnOfRaceToSlice = (RaceColumnInSeries) raceColumnAndFleetOfRaceToSlice.getA(); final Fleet fleet = raceColumnAndFleetOfRaceToSlice.getB(); @@ -7691,7 +8149,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S raceLog.add(new RaceLogStartOfTrackingEventImpl(startOfTracking, author, raceLog.getCurrentPassId())); raceLog.add(new RaceLogEndOfTrackingEventImpl(endOfTracking, author, raceLog.getCurrentPassId())); final TimeRange timeRange = new TimeRangeImpl(sliceFrom, sliceTo); - final StartTimeFinderResult startTimeFinderResult = new StartTimeFinder(getService(), raceLogOfRaceToSlice).analyze(); + final StartTimeFinderResult startTimeFinderResult = new StartTimeFinder(getService(), raceLogOfRaceToSlice) + .analyze(); final TimePoint startTime = startTimeFinderResult.getStartTime(); final boolean hasStartTime = startTime != null && timeRange.includes(startTime); final boolean dependentStartTime = startTimeFinderResult.isDependentStartTime(); @@ -7710,7 +8169,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S hasFinishingTime = false; hasFinishedTime = false; } - + // Only wind fixes in the new tracking interval as well as the best fallback fixes are added to the new RaceLog final LogEventTimeRangeWithFallbackFilter windFixEvents = new LogEventTimeRangeWithFallbackFilter<>( timeRange); @@ -7727,50 +8186,51 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S event.getStartTimeDifference(), event.getNextStatus())); } } - + @Override public void visit(RaceLogStartTimeEvent event) { if (!dependentStartTime && isLatestPass(event)) { raceLog.add(new RaceLogStartTimeEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), - event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), event.getStartTime(), - event.getNextStatus())); + event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), + event.getStartTime(), event.getNextStatus())); } } - + @Override public void visit(RaceLogRegisterCompetitorEvent event) { raceLog.add(new RaceLogRegisterCompetitorEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), event.getCompetitor(), event.getBoat())); } - + @Override public void visit(RaceLogWindFixEvent event) { windFixEvents.addEvent(event); } - + @Override public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(event.getCreatedAt(), event.getAuthor(), - event.getLogicalTimePoint(), UUID.randomUUID(), raceLog.getCurrentPassId())); + raceLog.add( + new RaceLogUseCompetitorsFromRaceLogEventImpl(event.getCreatedAt(), event.getAuthor(), + event.getLogicalTimePoint(), UUID.randomUUID(), raceLog.getCurrentPassId())); } - + @Override public void visit(RaceLogCourseDesignChangedEvent event) { raceLog.add(new RaceLogCourseDesignChangedEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), event.getCourseDesign(), event.getCourseDesignerMode())); } - + @Override public void visit(RaceLogFlagEvent event) { if (hasStartTime && isLatestPass(event) && !event.getLogicalTimePoint().after(sliceTo)) { raceLog.add(new RaceLogFlagEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), - event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), event.getUpperFlag(), - event.getLowerFlag(), event.isDisplayed())); + event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), + event.getUpperFlag(), event.getLowerFlag(), event.isDisplayed())); } } - + @Override public void visit(RaceLogStartProcedureChangedEvent event) { if (hasStartTime && isLatestPass(event)) { @@ -7779,35 +8239,38 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S raceLog.getCurrentPassId(), event.getStartProcedureType())); } } - + @Override public void visit(RaceLogFinishPositioningConfirmedEvent event) { if (hasFinishedTime && isLatestPass(event)) { raceLog.add(new RaceLogFinishPositioningConfirmedEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); + raceLog.getCurrentPassId(), + event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); } } - + @Override public void visit(RaceLogFinishPositioningListChangedEvent event) { if (hasFinishedTime && isLatestPass(event)) { raceLog.add(new RaceLogFinishPositioningListChangedEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); + raceLog.getCurrentPassId(), + event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); } } - + @Override public void visit(RaceLogFixedMarkPassingEvent event) { - if (hasStartTime && isLatestPass(event) && timeRange.includes(event.getTimePointOfFixedPassing())) { + if (hasStartTime && isLatestPass(event) + && timeRange.includes(event.getTimePointOfFixedPassing())) { raceLog.add(new RaceLogFixedMarkPassingEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), event.getInvolvedCompetitors(), raceLog.getCurrentPassId(), event.getTimePointOfFixedPassing(), event.getZeroBasedIndexOfPassedWaypoint())); } } - + @Override public void visit(RaceLogSuppressedMarkPassingsEvent event) { if (hasStartTime && isLatestPass(event) && timeRange.includes(event.getLogicalTimePoint())) { @@ -7817,7 +8280,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S event.getZeroBasedIndexOfFirstSuppressedWaypoint())); } } - + @Override public void visit(RaceLogProtestStartTimeEvent event) { if (hasFinishedTime && isLatestPass(event)) { @@ -7826,7 +8289,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S raceLog.getCurrentPassId(), event.getProtestTime())); } } - + @Override public void visit(RaceLogAdditionalScoringInformationEvent event) { if (hasFinishedTime && isLatestPass(event)) { @@ -7835,16 +8298,16 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S raceLog.getCurrentPassId(), event.getType())); } } - + @Override public void visit(RaceLogPathfinderEvent event) { if (hasStartTime && isLatestPass(event)) { - raceLog.add(new RaceLogPathfinderEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), - event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), - event.getPathfinderId())); + raceLog.add(new RaceLogPathfinderEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getPathfinderId())); } } - + @Override public void visit(RaceLogGateLineOpeningTimeEvent event) { if (hasStartTime && isLatestPass(event)) { @@ -7854,31 +8317,32 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S event.getGateLineOpeningTimes().getGolfDownTime())); } } - + @Override public void visit(RaceLogRaceStatusEvent event) { if (isLatestPass(event) && !(event instanceof RaceLogDependentStartTimeEvent) && !(event instanceof RaceLogStartTimeEvent)) { - if ((hasStartTime - && event.getNextStatus().getOrderNumber() <= RaceLogRaceStatus.RUNNING.getOrderNumber()) + if ((hasStartTime && event.getNextStatus().getOrderNumber() <= RaceLogRaceStatus.RUNNING + .getOrderNumber()) || (hasFinishingTime && event.getNextStatus() == RaceLogRaceStatus.FINISHING) || (hasFinishedTime && event.getNextStatus() == RaceLogRaceStatus.FINISHED)) { - raceLog.add(new RaceLogRaceStatusEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), - event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), - event.getNextStatus())); + raceLog.add(new RaceLogRaceStatusEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getNextStatus())); } } } - + @Override public void visit(RaceLogTagEvent event) { // TODO check if if condition is correct D067890 if (hasStartTime && isLatestPass(event)) { - raceLog.add(new RaceLogTagEventImpl(event.getTag(), event.getComment(), event.getImageURL(), event.isVisibleForPublic(), event.getCreatedAt(), event.getLogicalTimePoint(), + raceLog.add(new RaceLogTagEventImpl(event.getTag(), event.getComment(), event.getImageURL(), + event.isVisibleForPublic(), event.getCreatedAt(), event.getLogicalTimePoint(), event.getAuthor(), raceLog.getCurrentPassId())); } } - + private boolean isLatestPass(RaceLogEvent event) { return event.getPassId() == raceLogOfRaceToSlice.getCurrentPassId(); } @@ -7892,16 +8356,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), event.getWindFix(), event.isMagnetic()))); final 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, - author, raceLog.getCurrentPassId(), trackedRaceName, regatta.getBoatClass(), UUID.randomUUID())); + raceLog.add(new RaceLogDenoteForTrackingEventImpl(denotationTimePoint, author, raceLog.getCurrentPassId(), + trackedRaceName, regatta.getBoatClass(), UUID.randomUUID())); raceLog.add(new RaceLogStartTrackingEventImpl(startTrackingTimePoint, author, raceLog.getCurrentPassId())); try { final RaceHandle raceHandle = getRaceLogTrackingAdapter().startTracking(getService(), regattaLeaderboard, raceColumn, fleet, /* trackWind */ true, /* correctWindDirectionByMagneticDeclination */ true); - + // wait for the RaceDefinition to be created raceHandle.getRace(); @@ -7914,7 +8379,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final WindTrack windTrackToCopyFrom = trackedRaceToSlice.getOrCreateWindTrack(windSourceToCopy); windTrackToCopyFrom.lockForRead(); try { - for (Wind windToCopy : windTrackToCopyFrom.getFixes(startOfTracking, true, endOfTracking, true)) { + for (Wind windToCopy : windTrackToCopyFrom.getFixes(startOfTracking, true, endOfTracking, + true)) { trackedRace.recordWind(windToCopy, windSourceToCopy); } } finally { @@ -7922,7 +8388,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } } - + final Iterable mediaTracksForOriginalRace = getService().getMediaTracksForRace(raceIdentifier); for (MediaTrack mediaTrack : mediaTracksForOriginalRace) { if (mediaTrack.overlapsWith(sliceFrom, sliceTo)) { @@ -7960,7 +8426,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S ShardingType identifiedShardingType = null; try { if (req instanceof HttpServletRequest) { - identifiedShardingType = ShardingContext.identifyAndSetShardingConstraint(((HttpServletRequest) req).getPathInfo()); + identifiedShardingType = ShardingContext + .identifyAndSetShardingConstraint(((HttpServletRequest) req).getPathInfo()); } super.service(req, res); } finally { diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java index 23ae8b143e9..157ba46f350 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogTagEventDeserializer.java @@ -28,7 +28,7 @@ public class RaceLogTagEventDeserializer extends BaseRaceLogEventDeserializer{ String tag = object.get(RaceLogTagEventSerializer.FIELD_TAG).toString(); String comment = object.get(RaceLogTagEventSerializer.FIELD_COMMENT).toString(); String imageURL = object.get(RaceLogTagEventSerializer.FIELD_URL).toString(); - boolean isPublic = (boolean) object.get(RaceLogTagEventSerializer.FIELD_IS_PUBLIC); + boolean isPublic = (boolean) object.get(RaceLogTagEventSerializer.FIELD_IS_VISIBLE_FOR_PUBLIC); return new RaceLogTagEventImpl(tag, comment, imageURL, isPublic, createdAt, timePoint, author, id, passId); } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java index 69879d7d5e3..4a64abf89bb 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogTagEventSerializer.java @@ -7,13 +7,13 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.serialization.JsonSerializer; -public class RaceLogTagEventSerializer extends BaseRaceLogEventSerializer{ - +public class RaceLogTagEventSerializer extends BaseRaceLogEventSerializer { + public static final String VALUE_CLASS = RaceLogTagEvent.class.getSimpleName(); public static final String FIELD_TAG = "tag"; public static final String FIELD_COMMENT = "comment"; public static final String FIELD_URL = "url"; - public static final String FIELD_IS_PUBLIC = "ispublic"; + public static final String FIELD_IS_VISIBLE_FOR_PUBLIC = "ispublic"; public RaceLogTagEventSerializer(JsonSerializer competitorSerializer) { super(competitorSerializer); @@ -31,7 +31,7 @@ public class RaceLogTagEventSerializer extends BaseRaceLogEventSerializer{ result.put(FIELD_TAG, tagEvent.getTag()); result.put(FIELD_COMMENT, tagEvent.getComment()); result.put(FIELD_URL, tagEvent.getImageURL()); - result.put(FIELD_IS_PUBLIC, tagEvent.isVisibleForPublic()); + result.put(FIELD_IS_VISIBLE_FOR_PUBLIC, tagEvent.isVisibleForPublic()); return result; } } \ No newline at end of file From db5b00a3935de225e81e0b06b97ace00f07537cb Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Thu, 16 Aug 2018 16:03:09 +0200 Subject: [PATCH 147/292] Bug 4104: Removed debugging console log & changed tag button UI --- .../java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.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/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 710dd2914a8..e9fe3c64e37 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -280,6 +280,7 @@ public class TaggingPanel extends ComponentWithoutSettings this.imageURL = imageURL; this.comment = comment; setStyleName(TagPanelResources.INSTANCE.style().footerButton()); + addStyleName("gwt-Button"); addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -1042,7 +1043,6 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onSelectionChange(SelectionChangeEvent event) { // set time slider to corresponding position - GWT.log(event.getSource().toString()); timer.setTime(tagSelectionModel.getSelectedObject().getRaceTimepoint().asMillis()); } }); From bb4e36a5564fda1cba9229a3b8cab3429f24e1e5 Mon Sep 17 00:00:00 2001 From: D067890 Date: Thu, 16 Aug 2018 16:08:39 +0200 Subject: [PATCH 148/292] bug4104: Only private tags contain visibleForPublic image --- .../gwt/ui/raceboard/TaggingPanel.java | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 7c053833445..778db3001b5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -101,9 +101,6 @@ public class TaggingPanel extends ComponentWithoutSettings @Source("com/sap/sailing/gwt/ui/client/images/edit.png") ImageResource editIcon(); - @Source("com/sap/sailing/gwt/ui/client/images/unlock.png") - ImageResource publicIcon(); - @Source("com/sap/sailing/gwt/ui/client/images/lock.png") ImageResource privateIcon(); @@ -211,12 +208,20 @@ public class TaggingPanel extends ComponentWithoutSettings } public interface TagCellTemplate extends SafeHtmlTemplates { - @Template("

{3}
{4}
{5}
") + @Template("
{3}
{4}
{5}
") SafeHtml cell(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, SafeHtml createdAt, - SafeHtml content, SafeUri safeUri); + SafeHtml content); + + @Template("
{3}
{4}
{5}
") + SafeHtml cellRemovable(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, + SafeHtml createdAt, SafeHtml content); + + @Template("
{3}
{4}
{5}
") + SafeHtml privateCell(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, + SafeHtml createdAt, SafeHtml content, SafeUri safeUri); @Template("
{3}
{4}
{5}
") - SafeHtml cellRemovable(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, + SafeHtml privateCellRemovable(String styleTag, String styleTagHeading, String styleTagCreated, SafeHtml tag, SafeHtml createdAt, SafeHtml content, SafeUri safeUri); @Template("
{3}
") @@ -253,9 +258,7 @@ public class TaggingPanel extends ComponentWithoutSettings SafeHtml safeComment = SafeHtmlUtils.fromString(tag.getComment()); SafeUri trustedImageURL = UriUtils.fromTrustedString(tag.getImageURL()); - SafeUri safeIsVisibelForPublicImageUri = tag.isVisibleForPublic() - ? TagPanelResources.INSTANCE.publicIcon().getSafeUri() - : TagPanelResources.INSTANCE.privateIcon().getSafeUri(); + SafeUri safeIsPrivateImageUri = TagPanelResources.INSTANCE.privateIcon().getSafeUri(); SafeHtml content = SafeHtmlUtils.EMPTY_SAFE_HTML; @@ -272,11 +275,22 @@ public class TaggingPanel extends ComponentWithoutSettings if (!isPreviewCell && userService.getCurrentUser() != null && (tag.getUsername().equals(userService.getCurrentUser().getName()) || userService.getCurrentUser().hasRole("admin"))) { - cell = tagCellTemplate.cellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), safeTag, safeCreated, content, safeIsVisibelForPublicImageUri); + if (tag.isVisibleForPublic()) { + cell = tagCellTemplate.cellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), + tagPanelStyle.tagCreated(), safeTag, safeCreated, content); + } else { + cell = tagCellTemplate.privateCellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), + tagPanelStyle.tagCreated(), safeTag, safeCreated, content, safeIsPrivateImageUri); + } + } else { - cell = tagCellTemplate.cell(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), tagPanelStyle.tagCreated(), - safeTag, safeCreated, content, safeIsVisibelForPublicImageUri); + if (tag.isVisibleForPublic()) { + cell = tagCellTemplate.cell(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), + tagPanelStyle.tagCreated(), safeTag, safeCreated, content); + } else { + cell = tagCellTemplate.privateCell(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), + tagPanelStyle.tagCreated(), safeTag, safeCreated, content, safeIsPrivateImageUri); + } } htmlBuilder.append(cell); } From 855d3493bc0f8b503ce1e77aefe7a082820ed414 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Thu, 16 Aug 2018 16:10:16 +0200 Subject: [PATCH 149/292] Bug 4104: Added confirmation dialog when deleting tags or tag buttons & hide tag button table when no tag button is set. --- .../sailing/gwt/ui/client/StringMessages.java | 6 ++ .../gwt/ui/client/StringMessages.properties | 6 ++ .../ui/client/StringMessages_de.properties | 14 +++- .../gwt/ui/raceboard/TaggingPanel.java | 81 ++++++++++++++++--- 4 files changed, 90 insertions(+), 17 deletions(-) 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 f16a955e84c..e03ac33e962 100755 --- 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 @@ -2124,4 +2124,10 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String tagEditCustomTagButton(); String tagSaveCustomTagButton(); String tagPreview(); + String tagConfirmDeletionHeading(); + String tagConfirmDeletion(String tag); + String tagButtonConfirmDeletionHeading(); + String tagButtonConfirmDeletion(String tagButton); + String confirm(); + String cancel(); } 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 2eef32796d1..0ae4e4f519d 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 @@ -2119,3 +2119,9 @@ tagEditFilter=Edit filter tagEditCustomTagButton=Edit tag button tagSaveCustomTagButton=Save tagPreview=Tag preview: +tagConfirmDeletionHeading=Delete tag +tagConfirmDeletion=This will delete the tag "{0}". Do you really want to continue? +tagButtonConfirmDeletionHeading=Delete tag button +tagButtonConfirmDeletion=This will delete the tag button "{0}". Do you really want to continue? +confirm=Confirm +cancel=Cancel 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 fecad35cc5e..6288f62ca28 100755 --- 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 @@ -2107,10 +2107,16 @@ tagLabelComment=Kommentar tagLabelImageURL=Bild URL tagLabelAction=Aktion tagCreateTag=Tag hinzufügen -tagEditCustomTagButtons=Tag Buttons bearbeiten -tagAddCustomTagButton=Tag Button hinzufügen +tagEditCustomTagButtons=Tag-Buttons bearbeiten +tagAddCustomTagButton=Tag-Button hinzufügen tagNotSpecified=Tag darf nicht leer sein! tagEditFilter=Bearbeite Filter -tagEditCustomTagButton=Bearbeite Tag Button +tagEditCustomTagButton=Bearbeite Tag-Button tagSaveCustomTagButton=Speichern -tagPreview=Tag Vorschau: \ No newline at end of file +tagPreview=Tag Vorschau: +tagConfirmDeletionHeading=Tag löschen +tagConfirmDeletion=Dies wird den Tag "{0}" endgütltig löschen. Willst du wirklich fortfahren? +tagButtonConfirmDeletionHeading=Tag-Button löschen +tagButtonConfirmDeletion=Dies wird den Tag-Button "{0}" endgütltig löschen. Willst du wirklich fortfahren? +confirm=Fortfahren +cancel=Abbrechen diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index e9fe3c64e37..ebc5c88ca3b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.function.Consumer; import com.google.gwt.cell.client.AbstractCell; import com.google.gwt.cell.client.FieldUpdater; @@ -246,7 +247,12 @@ public class TaggingPanel extends ComponentWithoutSettings } Element button = parent.getElementsByTagName("button").getItem(0); if (button != null && button.isOrHasChild(Element.as(eventTarget))) { - removeTagFromRaceLog(tag); + new ConfirmationDialog(stringMessages.tagConfirmDeletionHeading(), + stringMessages.tagConfirmDeletion(tag.getTag()), (confirmed) -> { + if (confirmed) { + removeTagFromRaceLog(tag); + } + }); } } } @@ -545,19 +551,23 @@ public class TaggingPanel extends ComponentWithoutSettings if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { final int heightOfTagButtonPanel = customButtonsPanel.getOffsetHeight(); - customTagButtons.remove(button); - customButtonsPanel.remove(button); - customTagButtonsTable.setRowData(customTagButtons); + new ConfirmationDialog(stringMessages.tagButtonConfirmDeletionHeading(), stringMessages.tagButtonConfirmDeletion(button.getTag()), (confirmed) -> { + if (confirmed) { + customTagButtons.remove(button); + customButtonsPanel.remove(button); + setRowData(customTagButtons); - final int deltaHeight = customButtonsPanel.getOffsetHeight() - heightOfTagButtonPanel; - /* - * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), the - * footerWidget of the TaggingPanel has a different height, which in this case might cause the - * contentWidget to be to small. - */ - if (deltaHeight != 0) { - panel.setContentWidget(contentPanel); - } + final int deltaHeight = customButtonsPanel.getOffsetHeight() - heightOfTagButtonPanel; + /* + * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), the + * footerWidget of the TaggingPanel has a different height, which in this case might cause the + * contentWidget to be to small. + */ + if (deltaHeight != 0) { + panel.setContentWidget(contentPanel); + } + } + }); } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { selectedTagButton = button; @@ -696,6 +706,51 @@ public class TaggingPanel extends ComponentWithoutSettings } } + private class ConfirmationDialog extends DialogBox { + + private final FlowPanel panel; + private final TagPanelStyle style = TagPanelResources.INSTANCE.style(); + + public ConfirmationDialog(String title, String text, Consumer consumer) { + panel = new FlowPanel(); + setGlassEnabled(true); + + Label label = new Label(text); + label.getElement().getStyle().setMarginBottom(10, Unit.PX); + + Button confirm = new Button(stringMessages.confirm()); + confirm.setStyleName(style.footerButton()); + confirm.addStyleName("gwt-Button"); + confirm.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + consumer.accept(true); + hide(); + } + }); + + Button cancel = new Button(stringMessages.cancel()); + cancel.setStyleName(style.footerButton()); + cancel.addStyleName("gwt-Button"); + cancel.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + consumer.accept(false); + hide(); + } + }); + + panel.add(label); + panel.add(cancel); + panel.add(confirm); + + setText(title); + getElement().getStyle().setBackgroundColor("white"); + setWidget(panel); + center(); + } + } + private class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWithUI { private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailingAnalytics.raceBoard.tagsFilterSets"; From 38805c236eac3613bff422838580f6aff88fb9b1 Mon Sep 17 00:00:00 2001 From: D067890 Date: Thu, 16 Aug 2018 16:29:16 +0200 Subject: [PATCH 150/292] bug4104: reordered dialog --- .../com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java | 5 ++++- .../com/sap/sailing/gwt/ui/raceboard/tagging-panel.css | 7 +++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 778db3001b5..31ecfe3444b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -661,6 +661,7 @@ public class TaggingPanel extends ComponentWithoutSettings saveChangesButton.setVisible(true); cancelChangesButton.setVisible(true); + closeButton.setVisible(false); addCustomTagButton.setVisible(false); customTagButtonsTable.setVisible(false); } @@ -729,6 +730,7 @@ public class TaggingPanel extends ComponentWithoutSettings saveChangesButton.setVisible(false); cancelChangesButton.setVisible(false); + closeButton.setVisible(true); addCustomTagButton.setVisible(true); selectedTagButton = null; setRowData(customTagButtons); @@ -748,6 +750,7 @@ public class TaggingPanel extends ComponentWithoutSettings tagPreviewPanel.renderPreview(); saveChangesButton.setVisible(false); cancelChangesButton.setVisible(false); + closeButton.setVisible(true); addCustomTagButton.setVisible(true); setRowData(customTagButtons); } @@ -761,6 +764,7 @@ public class TaggingPanel extends ComponentWithoutSettings hideDialog(); } }); + controlButttonPanel.add(closeButton); controlButttonPanel.add(addCustomTagButton); controlButttonPanel.add(cancelChangesButton); controlButttonPanel.add(saveChangesButton); @@ -771,7 +775,6 @@ public class TaggingPanel extends ComponentWithoutSettings mainPanel.add(inputPanel); mainPanel.add(controlButttonPanel); mainPanel.add(tagPreviewPanel); - mainPanel.add(closeButton); getElement().getStyle().setBackgroundColor("white"); setWidget(mainPanel); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css index e6f750cbb45..6c3f0338bd2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css @@ -113,18 +113,17 @@ b { border: 1px solid #cecece; margin-top: -1px; resize: none; - border-radius: 0px 0px 0px 4px; width: 100%; } -.inputPanelIsVisibleForPublic { - float: right; +.inputPanelIsVisibleForPublic { + width: 100%; padding: 2px; border: 1px solid #cecece; resize: none; border-radius: 0px 0px 4px 4px; margin-bottom: 5px; - margin-top: -3px; + margin-top: -2px; } /**************************** Tag filtering ****************************/ From 3cc9cca1e56da0cf907d71e7149a66beb5a57f46 Mon Sep 17 00:00:00 2001 From: D067890 Date: Thu, 16 Aug 2018 16:45:11 +0200 Subject: [PATCH 151/292] bug4104: Added visibility column in tag button table --- .../sailing/gwt/ui/client/StringMessages.java | 2 ++ .../gwt/ui/client/StringMessages.properties | 3 ++- .../gwt/ui/client/StringMessages_de.properties | 3 ++- .../sailing/gwt/ui/raceboard/TaggingPanel.java | 16 +++++++++++++++- 4 files changed, 21 insertions(+), 3 deletions(-) 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 f8428cf38e8..6425d29ee36 100755 --- 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 @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.i18n.client.LocalizableResource.DefaultLocale; import com.google.gwt.json.client.JSONValue; import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.user.cellview.client.Header; import com.sap.sailing.domain.common.i18n.CommonStringMessages; import com.sap.sse.gwt.client.DefaultRule_0_1_n; import com.sap.sse.gwt.client.DefaultRule_1_0n; @@ -2126,4 +2127,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String tagSaveCustomTagButton(); String tagPreview(); String tagVisibleForPublicCheckBox(); + String tagVisibility(); } 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 e66079c90f9..5a9c2ac49bb 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 @@ -2119,4 +2119,5 @@ tagEditFilter=Edit filter tagEditCustomTagButton=Edit tag button tagSaveCustomTagButton=Save tagPreview=Tag preview: -tagVisibleForPublicCheckBox=Visible for public \ No newline at end of file +tagVisibleForPublicCheckBox=Visible for public +tagVisibility=Visibility \ 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 543a3fe00af..d66170a443b 100755 --- 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 @@ -2114,4 +2114,5 @@ tagEditFilter=Bearbeite Filter tagEditCustomTagButton=Bearbeite Tag Button tagSaveCustomTagButton=Speichern tagPreview=Tag Vorschau: -tagVisibleForPublicCheckBox=Für alle sichtbar \ No newline at end of file +tagVisibleForPublicCheckBox=Für alle sichtbar +tagVisibility=Sichtbarkeit \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 31ecfe3444b..1bd26200c89 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -9,6 +9,7 @@ import java.util.Map; import com.google.gwt.cell.client.AbstractCell; import com.google.gwt.cell.client.FieldUpdater; +import com.google.gwt.cell.client.ImageResourceCell; import com.google.gwt.cell.client.ValueUpdater; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.shared.GWT; @@ -38,6 +39,7 @@ import com.google.gwt.safehtml.shared.UriUtils; import com.google.gwt.storage.client.Storage; import com.google.gwt.user.cellview.client.CellList; import com.google.gwt.user.cellview.client.CellTable; +import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; @@ -602,7 +604,7 @@ public class TaggingPanel extends ComponentWithoutSettings TagPanelStyle style = TagPanelResources.INSTANCE.style(); setGlassEnabled(true); setText(stringMessages.tagEditCustomTagButtons()); - setWidth("350px"); + setWidth("450px"); mainPanel = new FlowPanel(); mainPanel.setWidth("100%"); @@ -628,6 +630,17 @@ public class TaggingPanel extends ComponentWithoutSettings return button.getComment(); } }; + Column isPrivateColumn = new Column( + new ImageResourceCell()) { + @Override + public ImageResource getValue(TagButton tagButton) { + if (tagButton.isVisibleForPublic()) { + return null; + } else { + return TagPanelResources.INSTANCE.privateIcon(); + } + } + }; ImagesBarColumn actionsColumn = new ImagesBarColumn( new EditTagButtonsImagesBarCell(stringMessages)); @@ -671,6 +684,7 @@ public class TaggingPanel extends ComponentWithoutSettings customTagButtonsTable.addColumn(tagColumn, stringMessages.tagLabelTag()); customTagButtonsTable.addColumn(imageURLColumn, stringMessages.tagLabelImageURL()); customTagButtonsTable.addColumn(commentColumn, stringMessages.tagLabelComment()); + customTagButtonsTable.addColumn(isPrivateColumn, stringMessages.tagVisibility()); customTagButtonsTable.addColumn(actionsColumn, stringMessages.tagLabelAction()); setRowData(customTagButtons); From feb23b8997c9fd48d119bb2de80e47f93634796b Mon Sep 17 00:00:00 2001 From: D067890 Date: Thu, 16 Aug 2018 17:15:30 +0200 Subject: [PATCH 152/292] bug4104: minor improvements --- .../gwt/ui/raceboard/TaggingPanel.java | 42 ++++--------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java index 1bd26200c89..953fe638b97 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/TaggingPanel.java @@ -106,6 +106,9 @@ public class TaggingPanel extends ComponentWithoutSettings @Source("com/sap/sailing/gwt/ui/client/images/lock.png") ImageResource privateIcon(); + @Source("com/sap/sailing/gwt/ui/client/images/unlock.png") + ImageResource publicIcon(); + @Source("com/sap/sailing/gwt/ui/client/images/SAP_RV_Clear.png") ImageResource clearButton(); @@ -127,62 +130,35 @@ public class TaggingPanel extends ComponentWithoutSettings public interface TagPanelStyle extends CssResource { // tags String tag(); - String tagPanel(); - String tagHeading(); - String tagCreated(); - String tagComment(); - String tagImage(); - String button(); - String footerButton(); - String tagButtonTable(); - String inputPanelTag(); - String inputPanelComment(); - String inputPanelImageURL(); - String footerPanel(); - String tagPreviewPanel(); // filter tags String tagFilterButton(); - String tagFilterHiddenButton(); - String tagFilterClearButton(); - String tagFilterSearchButton(); - String tagFilterSettingsButton(); - String tagFilterFilterButton(); - String tagFilterContainer(); - String tagFilterSearchBox(); - String tagFilterSearchInput(); - String filterInactiveButtonBackgroundImage(); - String filterActiveButtonBackgroundImage(); - String clearButtonBackgroundImage(); - String searchButtonBackgroundImage(); - String settingsButtonBackgroundImage(); - String inputPanelIsVisibleForPublic(); } } @@ -196,15 +172,10 @@ public class TaggingPanel extends ComponentWithoutSettings public interface CellListStyle extends CellList.Style { String cellListEventItem(); - String cellListWidget(); - String cellListEvenItem(); - String cellListOddItem(); - String cellListSelectedItem(); - String cellListKeyboardSelectedItem(); } } @@ -535,6 +506,7 @@ public class TaggingPanel extends ComponentWithoutSettings visibleForPublicCheckBox = new CheckBox(stringMessages.tagVisibleForPublicCheckBox()); visibleForPublicCheckBox.setStyleName(style.inputPanelIsVisibleForPublic()); + visibleForPublicCheckBox.setValue(true); add(visibleForPublicCheckBox); } @@ -635,7 +607,7 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public ImageResource getValue(TagButton tagButton) { if (tagButton.isVisibleForPublic()) { - return null; + return TagPanelResources.INSTANCE.publicIcon(); } else { return TagPanelResources.INSTANCE.privateIcon(); } @@ -1280,6 +1252,10 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onUserStatusChange(UserDTO user, boolean preAuthenticated) { + tagListProvider.getAllTags().clear(); + raceTimesInfoProvider.getRaceIdentifiers().forEach((raceIdentifier) -> { + raceTimesInfoProvider.setLatestReceivedTagTime(raceIdentifier, null); + }); updateContent(); } From d38c823edad40fbc9e27960574410c45aab41097 Mon Sep 17 00:00:00 2001 From: Henri Kohlberg Date: Fri, 17 Aug 2018 15:55:57 +0200 Subject: [PATCH 153/292] Bug 4104: Major code refactoring, part 1 --- .../impl/MongoObjectFactoryImpl.java | 1 + .../race/impl/RaceLogTagEventImpl.java | 24 +- .../sailing/gwt/ui/client/StringMessages.java | 3 +- .../gwt/ui/client/StringMessages.properties | 1 + .../ui/client/StringMessages_de.properties | 1 + .../gwt/ui/client/TagListProvider.java | 45 +- ...TagsFilterSets.java => TagFilterSets.java} | 4 +- ...tsDialog.java => TagFilterSetsDialog.java} | 14 +- .../TagsFilterSetsJsonDeSerializer.java | 10 +- .../gwt/ui/raceboard/TaggingPanel.java | 1044 +++++++++-------- .../gwt/ui/raceboard/tagging-panel.css | 2 +- .../com/sap/sailing/gwt/ui/shared/TagDTO.java | 14 +- 12 files changed, 589 insertions(+), 574 deletions(-) rename java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/{TagsFilterSets.java => TagFilterSets.java} (97%) rename java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/{TagsFilterSetsDialog.java => TagFilterSetsDialog.java} (96%) diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index c368a687510..83b8c9d7374 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -1103,6 +1103,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { result.put(FieldNames.RACE_LOG_TAG.name(), event.getTag()); result.put(FieldNames.RACE_LOG_COMMENT.name(), event.getComment()); result.put(FieldNames.RACE_LOG_IMAGE_URL.name(), event.getImageURL()); + result.put(FieldNames.RACE_LOG_IS_PUBLIC.name(), event.isVisibleForPublic()); return result; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index f131a7a99e3..a74a4a6be38 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -11,20 +11,20 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE private static final long serialVersionUID = 7213518902555323432L; - private String tag, comment, imageURL, username; - private TimePoint revokedAt; + private final String tag, comment, imageURL, username; private final boolean visibleForPublic; + private TimePoint revokedAt; - public RaceLogTagEventImpl(String pTag, String pComment, String pImageURL, boolean pVisibleForPublic, - TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, - int pPassId) { - super(createdAt, logicalTimePoint, author, pId, pPassId); - tag = pTag; - comment = pComment; - imageURL = pImageURL; + public RaceLogTagEventImpl(String tag, String comment, String imageURL, boolean visibleForPublic, + TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, + int passId) { + super(createdAt, logicalTimePoint, author, id, passId); + this.tag = tag; + this.comment = comment; + this.imageURL = imageURL; + this.visibleForPublic = visibleForPublic; username = author.getName(); - visibleForPublic = pVisibleForPublic; - this.revokedAt = null; + revokedAt = null; } public RaceLogTagEventImpl(String tag, String comment, String imageURL, boolean visibleForPublic, @@ -58,7 +58,7 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE } /** - * Only sets revokedAt if tag is not revoked already and given timepoint is not null. + * Only sets revokedAt if tag is not already revoked and given timepoint is not null. */ @Override public void markAsRevoked(TimePoint revokedAt) { 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 81963aae2d3..e6544fd906d 100755 --- 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 @@ -5,8 +5,6 @@ import java.util.UUID; import com.google.gwt.core.client.GWT; import com.google.gwt.i18n.client.LocalizableResource.DefaultLocale; import com.google.gwt.json.client.JSONValue; -import com.google.gwt.safehtml.shared.SafeHtml; -import com.google.gwt.user.cellview.client.Header; import com.sap.sailing.domain.common.i18n.CommonStringMessages; import com.sap.sse.gwt.client.DefaultRule_0_1_n; import com.sap.sse.gwt.client.DefaultRule_1_0n; @@ -2132,6 +2130,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String tagConfirmDeletion(String tag); String tagButtonConfirmDeletionHeading(); String tagButtonConfirmDeletion(String tagButton); + String tagFilterNotSavable(); String confirm(); String cancel(); } 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 04c77507159..2237573ffae 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 @@ -2125,5 +2125,6 @@ tagConfirmDeletionHeading=Delete tag tagConfirmDeletion=This will delete the tag "{0}". Do you really want to continue? tagButtonConfirmDeletionHeading=Delete tag button tagButtonConfirmDeletion=This will delete the tag button "{0}". Do you really want to continue? +tagFilterNotSavable=Could not save filter to local browser storage! confirm=Confirm cancel=Cancel \ 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 10d48012ea0..99f9f3d078f 100755 --- 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 @@ -2120,5 +2120,6 @@ tagConfirmDeletionHeading=Tag löschen tagConfirmDeletion=Dies wird den Tag "{0}" endgütltig löschen. Willst du wirklich fortfahren? tagButtonConfirmDeletionHeading=Tag-Button löschen tagButtonConfirmDeletion=Dies wird den Tag-Button "{0}" endgütltig löschen. Willst du wirklich fortfahren? +tagFilterNotSavable=Tag-Filter konnte nicht im lokalen Browser Speicher gespeichert werden! confirm=Fortfahren cancel=Abbrechen \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java index 4fba9a88866..82b1d2dc178 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TagListProvider.java @@ -5,7 +5,7 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; -import com.google.gwt.user.client.ui.Label; +import com.google.gwt.core.client.GWT; import com.google.gwt.view.client.ListDataProvider; import com.sap.sailing.gwt.ui.shared.TagDTO; import com.sap.sse.common.Util; @@ -13,19 +13,14 @@ import com.sap.sse.common.filter.Filter; import com.sap.sse.common.filter.FilterSet; /** - * @author Julian Rendl(D067890) - * Used to store tags and filter sets and to apply these filters on the tags + * @author Julian Rendl(D067890) Used to store tags and filter sets and to apply these filters on the tags */ public class TagListProvider extends ListDataProvider { - private List allTags = new ArrayList(); - private FilterSet> currentFilterSet; - private Label filterInformationLabel; + private List allTags = new ArrayList(); + private FilterSet> currentFilterSet; - - - public TagListProvider(Label filterInformationLabel) { - this.filterInformationLabel = filterInformationLabel; + public TagListProvider() { } public List getAllTags() { @@ -33,8 +28,11 @@ public class TagListProvider extends ListDataProvider { } /** - * adds new tags, call {@link #updateFilteredTags() updateFilteredTags} afterwards so list of filtered tags can contain new tags - * @param list of tags which shall be added + * adds new tags, call {@link #updateFilteredTags() updateFilteredTags} afterwards so list of filtered tags can + * contain new tags + * + * @param list + * of tags which shall be added */ public void addTags(final List tags) { if (tags != null) { @@ -45,8 +43,11 @@ public class TagListProvider extends ListDataProvider { } /** - * adds a new tag, call {@link #updateFilteredTags() updateFilteredTags} afterwards so list of filtered tag can contain new tags - * @param tag which shall be added + * adds a new tag, call {@link #updateFilteredTags() updateFilteredTags} afterwards so list of filtered tag can + * contain new tags + * + * @param tag + * which shall be added */ public void addTag(final TagDTO tag) { if (tag != null) { @@ -63,7 +64,6 @@ public class TagListProvider extends ListDataProvider { */ public void updateFilteredTags() { List currentFilteredList = new ArrayList(getAllTags()); - if (currentFilterSet != null) { for (Filter filter : currentFilterSet.getFilters()) { for (Iterator i = currentFilteredList.iterator(); i.hasNext();) { @@ -74,6 +74,7 @@ public class TagListProvider extends ListDataProvider { } } } + currentFilteredList.sort(new Comparator() { @Override public int compare(TagDTO tag1, TagDTO tag2) { @@ -85,23 +86,13 @@ public class TagListProvider extends ListDataProvider { setList(currentFilteredList); } - public FilterSet> getTagsFilterSet() { + public FilterSet> getTagFilterSet() { return currentFilterSet; } public void setTagsFilterSet(FilterSet> tagsFilterSet) { - if(filterInformationLabel != null) { - if(tagsFilterSet != null) { - filterInformationLabel.setText(tagsFilterSet.getName()); - filterInformationLabel.setVisible(true); - } - else { - filterInformationLabel.setVisible(false); - } - } - - updateFilteredTags(); currentFilterSet = tagsFilterSet; + updateFilteredTags(); refresh(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagsFilterSets.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagFilterSets.java similarity index 97% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagsFilterSets.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagFilterSets.java index 78817505e66..ac60a318a7f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagsFilterSets.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagFilterSets.java @@ -12,12 +12,12 @@ import com.sap.sse.common.filter.FilterSet; * */ -public class TagsFilterSets { +public class TagFilterSets { private List>> filterSets; private FilterSet> activeFilterSet; - public TagsFilterSets() { + public TagFilterSets() { filterSets = new ArrayList>>(); activeFilterSet = null; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagsFilterSetsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagFilterSetsDialog.java similarity index 96% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagsFilterSetsDialog.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagFilterSetsDialog.java index ceffc4cbc44..bd95dbc4884 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagsFilterSetsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagFilterSetsDialog.java @@ -22,8 +22,8 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog; * @author Julian Rendl (D067890) * */ -public class TagsFilterSetsDialog extends DataEntryDialog { - private final TagsFilterSets tagsFilterSets; +public class TagFilterSetsDialog extends DataEntryDialog { + private final TagFilterSets tagsFilterSets; private final StringMessages stringMessages; private final Button addFilterSetButton; @@ -39,18 +39,18 @@ public class TagsFilterSetsDialog extends DataEntryDialog { private final String ACTIVE_FILTERSET_RADIOBUTTON_GROUPNAME = "ActiveFilterSetRB"; private final String filterNothingFiltersetName; - protected static class TagsFilterSetsValidator implements Validator { + protected static class TagsFilterSetsValidator implements Validator { public TagsFilterSetsValidator() { super(); } @Override - public String getErrorMessage(TagsFilterSets tagsFilterSets) { + public String getErrorMessage(TagFilterSets tagsFilterSets) { return null; } } - public TagsFilterSetsDialog(TagsFilterSets tagsFilterSets, StringMessages stringMessages, DialogCallback callback) { + public TagFilterSetsDialog(TagFilterSets tagsFilterSets, StringMessages stringMessages, DialogCallback callback) { super(stringMessages.tagsFilter(), null, stringMessages.ok(), stringMessages.cancel(), new TagsFilterSetsValidator(), callback); this.tagsFilterSets = tagsFilterSets; this.stringMessages = stringMessages; @@ -214,8 +214,8 @@ public class TagsFilterSetsDialog extends DataEntryDialog { } @Override - protected TagsFilterSets getResult() { - TagsFilterSets result = new TagsFilterSets(); + protected TagFilterSets getResult() { + TagFilterSets result = new TagFilterSets(); int filterSetCount = activeFilterSetRadioButtons.size(); for (int i = 0; i < filterSetCount; i++) { FilterSet> filterSet = filterSets.get(i); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagsFilterSetsJsonDeSerializer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagsFilterSetsJsonDeSerializer.java index 2bb4e042fb2..e5b6b9bdc79 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagsFilterSetsJsonDeSerializer.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/TagsFilterSetsJsonDeSerializer.java @@ -11,7 +11,7 @@ import com.sap.sailing.gwt.ui.shared.TagDTO; import com.sap.sse.common.filter.FilterSet; import com.sap.sse.common.filter.ValueFilter; -public class TagsFilterSetsJsonDeSerializer implements GwtJsonDeSerializer { +public class TagsFilterSetsJsonDeSerializer implements GwtJsonDeSerializer { public static final String FIELD_ACTIVE_FILTERSET = "activeFilterSet"; public static final String FIELD_FILTERSETS = "filterSets"; public static final String FIELD_FILTERSET_NAME = "name"; @@ -19,7 +19,7 @@ public class TagsFilterSetsJsonDeSerializer implements GwtJsonDeSerializer { + private final TagCellTemplate tagCellTemplate = GWT.create(TagCellTemplate.class); - private final TagPanelResources tagPanelRes = GWT.create(TagPanelResources.class); - private final TagPanelStyle tagPanelStyle = tagPanelRes.style(); private final boolean isPreviewCell; public TagCell(boolean isPreviewCell) { @@ -231,17 +236,17 @@ public class TaggingPanel extends ComponentWithoutSettings SafeHtml safeComment = SafeHtmlUtils.fromString(tag.getComment()); SafeUri trustedImageURL = UriUtils.fromTrustedString(tag.getImageURL()); - SafeUri safeIsPrivateImageUri = TagPanelResources.INSTANCE.privateIcon().getSafeUri(); + SafeUri safeIsPrivateImageUri = resources.privateIcon().getSafeUri(); SafeHtml content = SafeHtmlUtils.EMPTY_SAFE_HTML; - if (tag.getComment().length() > 0 && tag.getImageURL().length() <= 0) { - content = tagCellTemplate.contentWithCommentWithoutImage(tagPanelStyle.tagComment(), safeComment); - } else if (tag.getComment().length() <= 0 && tag.getImageURL().length() > 0) { - content = tagCellTemplate.contentWithoutCommentWithImage(tagPanelStyle.tagImage(), trustedImageURL); - } else if (tag.getComment().length() > 0 && tag.getImageURL().length() > 0) { - content = tagCellTemplate.contentWithCommentWithImage(tagPanelStyle.tagImage(), - tagPanelStyle.tagComment(), trustedImageURL, safeComment); + if (!tag.getComment().isEmpty() && tag.getImageURL().isEmpty()) { + content = tagCellTemplate.contentWithCommentWithoutImage(style.tagComment(), safeComment); + } else if (tag.getComment().isEmpty() && !tag.getImageURL().isEmpty()) { + content = tagCellTemplate.contentWithoutCommentWithImage(style.tagImage(), trustedImageURL); + } else if (!tag.getComment().isEmpty() && !tag.getImageURL().isEmpty()) { + content = tagCellTemplate.contentWithCommentWithImage(style.tagImage(), style.tagComment(), + trustedImageURL, safeComment); } SafeHtml cell; @@ -249,20 +254,20 @@ public class TaggingPanel extends ComponentWithoutSettings && (tag.getUsername().equals(userService.getCurrentUser().getName()) || userService.getCurrentUser().hasRole("admin"))) { if (tag.isVisibleForPublic()) { - cell = tagCellTemplate.cellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), safeTag, safeCreated, content); + cell = tagCellTemplate.cellRemovable(style.tag(), style.tagHeading(), style.tagCreated(), safeTag, + safeCreated, content); } else { - cell = tagCellTemplate.privateCellRemovable(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), safeTag, safeCreated, content, safeIsPrivateImageUri); + cell = tagCellTemplate.privateCellRemovable(style.tag(), style.tagHeading(), style.tagCreated(), + safeTag, safeCreated, content, safeIsPrivateImageUri); } } else { if (tag.isVisibleForPublic()) { - cell = tagCellTemplate.cell(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), safeTag, safeCreated, content); + cell = tagCellTemplate.cell(style.tag(), style.tagHeading(), style.tagCreated(), safeTag, + safeCreated, content); } else { - cell = tagCellTemplate.privateCell(tagPanelStyle.tag(), tagPanelStyle.tagHeading(), - tagPanelStyle.tagCreated(), safeTag, safeCreated, content, safeIsPrivateImageUri); + cell = tagCellTemplate.privateCell(style.tag(), style.tagHeading(), style.tagCreated(), safeTag, + safeCreated, content, safeIsPrivateImageUri); } } htmlBuilder.append(cell); @@ -290,25 +295,9 @@ public class TaggingPanel extends ComponentWithoutSettings } } - private class EditTagButtonsImagesBarCell extends ImagesBarCell { - public static final String ACTION_REMOVE = "ACTION_REMOVE"; - public static final String ACTION_EDIT = "ACTION_EDIT"; - private final StringMessages stringMessages; - - public EditTagButtonsImagesBarCell(StringMessages stringMessages) { - this.stringMessages = stringMessages; - } - - @Override - protected Iterable getImageSpecs() { - return Arrays.asList( - new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), - makeImagePrototype(TagPanelResources.INSTANCE.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), - makeImagePrototype(IconResources.INSTANCE.removeIcon()))); - } - } - + /** + * Used to store tag button data and creates new tag event when clicking the button. + */ private class TagButton extends Button { private String tag, imageURL, comment; private boolean visibleForPublic; @@ -319,7 +308,7 @@ public class TaggingPanel extends ComponentWithoutSettings this.imageURL = imageURL; this.comment = comment; this.visibleForPublic = visibleForPublic; - setStyleName(TagPanelResources.INSTANCE.style().footerButton()); + setStyleName(style.footerButton()); addStyleName("gwt-Button"); addClickHandler(new ClickHandler() { @Override @@ -356,28 +345,27 @@ public class TaggingPanel extends ComponentWithoutSettings public void setComment(String comment) { this.comment = comment; } - } + /* Panel */ + /** + * Panel used to create tags and tag buttons in side menu of RaceBoard. + */ private class TagCreationPanel extends FlowPanel { - private final Panel customButtonsPanel; - private final Panel standardButtonsPanel; - private final TagCreationInputPanel inputPanel; - private final Button createTagFromTextBoxes, editCustomTagButtons; public TagCreationPanel(StringMessages stringMessages) { setWidth("100%"); - inputPanel = new TagCreationInputPanel(stringMessages); - standardButtonsPanel = new FlowPanel(); - standardButtonsPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); - customButtonsPanel = new FlowPanel(); - customButtonsPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); - add(inputPanel); - add(standardButtonsPanel); - add(customButtonsPanel); - createTagFromTextBoxes = new Button(stringMessages.tagAddTag()); - createTagFromTextBoxes.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); + TagInputPanel inputPanel = new TagInputPanel(stringMessages); + + Panel standardButtonsPanel = new FlowPanel(); + standardButtonsPanel.setStyleName(style.buttonsPanel()); + + Panel tagButtonsPanel = new FlowPanel(); + tagButtonsPanel.setStyleName(style.buttonsPanel()); + + Button createTagFromTextBoxes = new Button(stringMessages.tagAddTag()); + createTagFromTextBoxes.setStyleName(style.footerButton()); createTagFromTextBoxes.addStyleName("gwt-Button"); createTagFromTextBoxes.addClickHandler(new ClickHandler() { @Override @@ -391,97 +379,55 @@ public class TaggingPanel extends ComponentWithoutSettings }); standardButtonsPanel.add(createTagFromTextBoxes); - editCustomTagButtons = new Button(stringMessages.tagEditCustomTagButtons()); - editCustomTagButtons.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); + Button editCustomTagButtons = new Button(stringMessages.tagEditCustomTagButtons()); + editCustomTagButtons.setStyleName(style.footerButton()); editCustomTagButtons.addStyleName("gwt-Button"); editCustomTagButtons.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (isLoggedInAndRaceLogAvailable()) { - new EditCustomTagButtonsDialog(customButtonsPanel); - updateButtons(); + new TagButtonDialog(tagButtonsPanel); + updateButtons(tagButtonsPanel); } } }); standardButtonsPanel.add(editCustomTagButtons); + + add(inputPanel); + add(standardButtonsPanel); + add(tagButtonsPanel); } - private void updateButtons() { - customButtonsPanel.clear(); - customTagButtons.forEach(button -> { - customButtonsPanel.add(button); + private void updateButtons(Panel tagButtonsPanel) { + /* + * If the height of the customButtonsPanel has changed after deleting (delta not equals to 0 ), the + * footerWidget of the TaggingPanel has a different height, which in this case might cause the contentWidget + * to be to small. + */ + final int oldHeight = tagButtonsPanel.getOffsetHeight(); + tagButtonsPanel.clear(); + tagButtons.forEach(button -> { + tagButtonsPanel.add(button); }); + if ((tagButtonsPanel.getOffsetHeight() - oldHeight) != 0) { + panel.setContentWidget(contentPanel); + } } } - public class TagPreviewPanel extends FlowPanel { - private final CellList tagPreviewCellList; - private TagDTO previewTag; - private List listContainingPreviewTag; - private final TagCreationInputPanel inputField; - private final Label previewLabel; + /** + * Panel containing input fields for tag/tag button creation and modification. + */ + private class TagInputPanel extends FlowPanel { - public TagPreviewPanel(TagCreationInputPanel inputField) { - this.inputField = inputField; - tagPreviewCellList = new CellList(new TagCell(true), CellListResources.INSTANCE); - tagPreviewCellList.setVisibleRange(0, 1); - previewLabel = new Label(stringMessages.tagPreview()); - listContainingPreviewTag = new ArrayList(); + // default value for "Visible for public" checkbox + private static final boolean DEFAULT_VISIBLE_FOR_PUBLIC = true; - setStyleName(TagPanelResources.INSTANCE.style().tagPreviewPanel()); - add(previewLabel); - add(tagPreviewCellList); - - inputField.getTagTextBox().addValueChangeHandler(new ValueChangeHandler() { - @Override - public void onValueChange(ValueChangeEvent event) { - renderPreview(); - } - - }); - inputField.getImageURLTextBox().addValueChangeHandler(new ValueChangeHandler() { - @Override - public void onValueChange(ValueChangeEvent event) { - renderPreview(); - } - - }); - inputField.getCommentTextArea().addValueChangeHandler(new ValueChangeHandler() { - @Override - public void onValueChange(ValueChangeEvent event) { - renderPreview(); - } - - }); - inputField.getVisibleForPublicCheckBox().addValueChangeHandler(new ValueChangeHandler() { - @Override - public void onValueChange(ValueChangeEvent event) { - renderPreview(); - } - }); - renderPreview(); - } - - public void renderPreview() { - listContainingPreviewTag.removeAll(listContainingPreviewTag); - previewTag = new TagDTO(inputField.getTag(), inputField.getComment(), inputField.getImageURL(), "Author", - inputField.isVisibleForPublic(), new MillisecondsTimePoint(timer.getTime()), - new MillisecondsTimePoint(timer.getTime())); - listContainingPreviewTag.add(previewTag); - tagPreviewCellList.setRowData(listContainingPreviewTag); - - setVisible(!inputField.getTag().isEmpty()); - } - } - - public class TagCreationInputPanel extends FlowPanel { private final TextBox tagTextBox, imageURLTextBox; private final TextArea commentTextArea; private final CheckBox visibleForPublicCheckBox; - private final TagPanelStyle style; - public TagCreationInputPanel(StringMessages stringMessages) { - style = TagPanelResources.INSTANCE.style(); + public TagInputPanel(StringMessages stringMessages) { setWidth("100%"); tagTextBox = new TextBox(); @@ -505,7 +451,7 @@ public class TaggingPanel extends ComponentWithoutSettings visibleForPublicCheckBox = new CheckBox(stringMessages.tagVisibleForPublicCheckBox()); visibleForPublicCheckBox.setStyleName(style.inputPanelIsVisibleForPublic()); - visibleForPublicCheckBox.setValue(true); + visibleForPublicCheckBox.setValue(DEFAULT_VISIBLE_FOR_PUBLIC); add(visibleForPublicCheckBox); } @@ -553,303 +499,98 @@ public class TaggingPanel extends ComponentWithoutSettings imageURLTextBox.setValue(imageURL); } + public void setVisibleForPublic(boolean visibleForPublic) { + visibleForPublicCheckBox.setValue(visibleForPublic); + } + public void clearAllValues() { tagTextBox.setText(""); imageURLTextBox.setText(""); commentTextArea.setText(""); + setVisibleForPublic(DEFAULT_VISIBLE_FOR_PUBLIC); } } - private class EditCustomTagButtonsDialog extends DialogBox { + /** + * Panel used to preview a tag. + */ + private class TagPreviewPanel extends FlowPanel { - private final Button closeButton, saveChangesButton, cancelChangesButton; - private final FlowPanel mainPanel; - private final CellTable customTagButtonsTable; - private final TagCreationInputPanel inputPanel; - private final Button addCustomTagButton; - private final TagPreviewPanel tagPreviewPanel; - private final FlowPanel controlButttonPanel; - private TagButton selectedTagButton = null; + private final CellList tagPreviewCellList; + private List listContainingPreviewTag; - public EditCustomTagButtonsDialog(Panel customButtonsPanel) { - TagPanelStyle style = TagPanelResources.INSTANCE.style(); - setGlassEnabled(true); - setText(stringMessages.tagEditCustomTagButtons()); - setWidth("450px"); + public TagPreviewPanel(TagInputPanel inputPanel) { + tagPreviewCellList = new CellList(new TagCell(true), cellResources); + listContainingPreviewTag = new ArrayList(); - mainPanel = new FlowPanel(); - mainPanel.setWidth("100%"); + setStyleName(style.tagPreviewPanel()); + add(new Label(stringMessages.tagPreview())); + add(tagPreviewCellList); - // Table with tag buttons - customTagButtonsTable = new CellTable(); - customTagButtonsTable.setStyleName(style.tagButtonTable()); - TextColumn tagColumn = new TextColumn() { + inputPanel.getTagTextBox().addValueChangeHandler(new ValueChangeHandler() { @Override - public String getValue(TagButton button) { - return button.getTag(); + public void onValueChange(ValueChangeEvent event) { + renderPreview(inputPanel); } - }; - TextColumn imageURLColumn = new TextColumn() { + + }); + inputPanel.getImageURLTextBox().addValueChangeHandler(new ValueChangeHandler() { @Override - public String getValue(TagButton button) { - return button.getImageURL(); + public void onValueChange(ValueChangeEvent event) { + renderPreview(inputPanel); } - }; - TextColumn commentColumn = new TextColumn() { + + }); + inputPanel.getCommentTextArea().addValueChangeHandler(new ValueChangeHandler() { @Override - public String getValue(TagButton button) { - return button.getComment(); + public void onValueChange(ValueChangeEvent event) { + renderPreview(inputPanel); } - }; - Column isPrivateColumn = new Column( - new ImageResourceCell()) { + + }); + inputPanel.getVisibleForPublicCheckBox().addValueChangeHandler(new ValueChangeHandler() { @Override - public ImageResource getValue(TagButton tagButton) { - if (tagButton.isVisibleForPublic()) { - return TagPanelResources.INSTANCE.publicIcon(); - } else { - return TagPanelResources.INSTANCE.privateIcon(); - } - } - }; - - ImagesBarColumn actionsColumn = new ImagesBarColumn( - new EditTagButtonsImagesBarCell(stringMessages)); - actionsColumn.setFieldUpdater(new FieldUpdater() { - @Override - public void update(int index, TagButton button, String value) { - if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { - final int heightOfTagButtonPanel = customButtonsPanel.getOffsetHeight(); - new ConfirmationDialog(stringMessages.tagButtonConfirmDeletionHeading(), stringMessages.tagButtonConfirmDeletion(button.getTag()), (confirmed) -> { - if (confirmed) { - customTagButtons.remove(button); - customButtonsPanel.remove(button); - setRowData(customTagButtons); - - final int deltaHeight = customButtonsPanel.getOffsetHeight() - heightOfTagButtonPanel; - /* - * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), the - * footerWidget of the TaggingPanel has a different height, which in this case might cause the - * contentWidget to be to small. - */ - if (deltaHeight != 0) { - panel.setContentWidget(contentPanel); - } - } - }); - } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { - selectedTagButton = button; - - inputPanel.setTag(button.getTag()); - inputPanel.setImageURL(button.getImageURL()); - inputPanel.setComment(button.getComment()); - - tagPreviewPanel.renderPreview(); - - saveChangesButton.setVisible(true); - cancelChangesButton.setVisible(true); - closeButton.setVisible(false); - addCustomTagButton.setVisible(false); - customTagButtonsTable.setVisible(false); - } + public void onValueChange(ValueChangeEvent event) { + renderPreview(inputPanel); } }); - - customTagButtonsTable.addColumn(tagColumn, stringMessages.tagLabelTag()); - customTagButtonsTable.addColumn(imageURLColumn, stringMessages.tagLabelImageURL()); - customTagButtonsTable.addColumn(commentColumn, stringMessages.tagLabelComment()); - customTagButtonsTable.addColumn(isPrivateColumn, stringMessages.tagVisibility()); - customTagButtonsTable.addColumn(actionsColumn, stringMessages.tagLabelAction()); - setRowData(customTagButtons); - - // input panel - inputPanel = new TagCreationInputPanel(stringMessages); - - // contol buttons - controlButttonPanel = new FlowPanel(); - controlButttonPanel.setStyleName(TagPanelResources.INSTANCE.style().footerPanel()); - - addCustomTagButton = new Button(stringMessages.tagAddCustomTagButton()); - addCustomTagButton.setStyleName(style.footerButton()); - addCustomTagButton.addStyleName("gwt-Button"); - addCustomTagButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - if (inputPanel.getTag().length() > 0) { - final int heightOfTagButtonPanel = customButtonsPanel.getOffsetHeight(); - TagButton tagButton = new TagButton(inputPanel.getTag(), inputPanel.getTag(), - inputPanel.getImageURL(), inputPanel.getComment(), inputPanel.isVisibleForPublic()); - inputPanel.clearAllValues(); - tagPreviewPanel.renderPreview(); - - customTagButtons.add(tagButton); - customButtonsPanel.add(tagButton); - setRowData(customTagButtons); - - final int deltaHeight = customButtonsPanel.getOffsetHeight() - heightOfTagButtonPanel; - /* - * If the height of the customButtonsPanel has changed ( delta not equals to 0 ), the - * footerWidget of the TaggingPanel has a different height, which might cause the contentWidget - * to overlap the footerWidget. - */ - if (deltaHeight != 0) { - panel.setContentWidget(contentPanel); - } - } else { - Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); - } - } - }); - - saveChangesButton = new Button(stringMessages.save()); - saveChangesButton.setVisible(false); - saveChangesButton.setStyleName(style.footerButton()); - saveChangesButton.addStyleName("gwt-Button"); - saveChangesButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - if (inputPanel.getTag().length() > 0) { - selectedTagButton.setText(inputPanel.getTag()); - selectedTagButton.setTag(inputPanel.getTag()); - selectedTagButton.setComment(inputPanel.getComment()); - selectedTagButton.setImageURL(inputPanel.getImageURL()); - inputPanel.clearAllValues(); - tagPreviewPanel.renderPreview(); - customTagButtonsTable.redraw(); - - saveChangesButton.setVisible(false); - cancelChangesButton.setVisible(false); - closeButton.setVisible(true); - addCustomTagButton.setVisible(true); - selectedTagButton = null; - setRowData(customTagButtons); - } else { - Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); - } - } - }); - - cancelChangesButton = new Button(stringMessages.cancel()); - cancelChangesButton.setVisible(false); - cancelChangesButton.setStyleName(style.footerButton()); - cancelChangesButton.addStyleName("gwt-Button"); - cancelChangesButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - inputPanel.clearAllValues(); - tagPreviewPanel.renderPreview(); - saveChangesButton.setVisible(false); - cancelChangesButton.setVisible(false); - closeButton.setVisible(true); - addCustomTagButton.setVisible(true); - setRowData(customTagButtons); - } - }); - - closeButton = new Button(stringMessages.close()); - closeButton.setStyleName(TagPanelResources.INSTANCE.style().footerButton()); - closeButton.addStyleName("gwt-Button"); - closeButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - hide(); - } - }); - controlButttonPanel.add(closeButton); - controlButttonPanel.add(addCustomTagButton); - controlButttonPanel.add(cancelChangesButton); - controlButttonPanel.add(saveChangesButton); - - tagPreviewPanel = new TagPreviewPanel(inputPanel); - - mainPanel.add(customTagButtonsTable); - mainPanel.add(inputPanel); - mainPanel.add(controlButttonPanel); - mainPanel.add(tagPreviewPanel); - getElement().getStyle().setBackgroundColor("white"); - - setWidget(mainPanel); - center(); + renderPreview(inputPanel); } - private void setRowData(List buttons) { - customTagButtonsTable.setRowData(buttons); - customTagButtonsTable.setVisible(buttons.size() > 0); - } - } - - private class ConfirmationDialog extends DialogBox { - - private final FlowPanel panel; - private final TagPanelStyle style = TagPanelResources.INSTANCE.style(); - - public ConfirmationDialog(String title, String text, Consumer consumer) { - panel = new FlowPanel(); - setGlassEnabled(true); - - Label label = new Label(text); - label.getElement().getStyle().setMarginBottom(10, Unit.PX); - - Button confirm = new Button(stringMessages.confirm()); - confirm.setStyleName(style.footerButton()); - confirm.addStyleName("gwt-Button"); - confirm.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - consumer.accept(true); - hide(); - } - }); - - Button cancel = new Button(stringMessages.cancel()); - cancel.setStyleName(style.footerButton()); - cancel.addStyleName("gwt-Button"); - cancel.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - consumer.accept(false); - hide(); - } - }); - - panel.add(label); - panel.add(cancel); - panel.add(confirm); - - setText(title); - getElement().getStyle().setBackgroundColor("white"); - setWidget(panel); - center(); + public void renderPreview(TagInputPanel inputPanel) { + listContainingPreviewTag.removeAll(listContainingPreviewTag); + listContainingPreviewTag.add(new TagDTO(inputPanel.getTag(), inputPanel.getComment(), + inputPanel.getImageURL(), userService.getCurrentUser().getName(), inputPanel.isVisibleForPublic(), + new MillisecondsTimePoint(timer.getTime()), new MillisecondsTimePoint(timer.getTime()))); + tagPreviewCellList.setRowData(listContainingPreviewTag); + + setVisible(!inputPanel.getTag().isEmpty()); } } + /** + * Panel used to select and modify tag filter. + */ private class TagFilterPanel extends FlowPanel implements KeyUpHandler, FilterWithUI { + private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailingAnalytics.raceBoard.tagsFilterSets"; - private final TagPanelStyle css = TagPanelResources.INSTANCE.style(); - private final TextBox searchTextBox; - private final Button clearTextBoxButton; - private final Button filterSettingsButton; - private final TagsFilterSets tagFilterSets; - private final FlowPanel searchBoxPanel; - private final StringMessages stringMessages; - private final TagListProvider tagProvider; + private FilterSet> lastActiveTagFilterSet; + private final TagFilterSets tagFilterSets; + private TextBox searchTextBox; + private Button clearTextBoxButton, filterSettingsButton; private final AbstractListFilter filter; - private FilterSet> lastActiveTagFilterSet; + public TagFilterPanel() { + setStyleName(style.tagFilterContainer()); - public TagFilterPanel(StringMessages stringMessages, TagListProvider tagProvider) { - css.ensureInjected(); - this.stringMessages = stringMessages; - this.tagProvider = tagProvider; - this.setStyleName(css.tagFilterContainer()); + TagFilterSets loadedTagsFilterSets = loadTagFilterSets(); - TagsFilterSets loadedTagsFilterSets = loadTagsFilterSets(); if (loadedTagsFilterSets != null) { tagFilterSets = loadedTagsFilterSets; - tagProvider.setTagsFilterSet(tagFilterSets.getActiveFilterSetWithGeneralizedType()); + tagListProvider.setTagsFilterSet(tagFilterSets.getActiveFilterSetWithGeneralizedType()); } else { - tagFilterSets = createAndAddDefaultTagsFilter(); + tagFilterSets = new TagFilterSets(); storeTagsFilterSets(tagFilterSets); } @@ -861,23 +602,26 @@ public class TaggingPanel extends ComponentWithoutSettings return result; } }; + initializeUI(); + } + private void initializeUI() { Button submitButton = new Button(); - submitButton.setStyleName(css.tagFilterButton()); + submitButton.setStyleName(style.tagFilterButton()); submitButton.addStyleName("gwt-Button"); - submitButton.addStyleName(css.tagFilterSearchButton()); - submitButton.addStyleName(css.searchButtonBackgroundImage()); + submitButton.addStyleName(style.tagFilterSearchButton()); + submitButton.addStyleName(style.searchButtonBackgroundImage()); searchTextBox = new TextBox(); searchTextBox.getElement().setAttribute("placeholder", stringMessages.tagSearchTags()); searchTextBox.addKeyUpHandler(this); - searchTextBox.setStyleName(css.tagFilterSearchInput()); + searchTextBox.setStyleName(style.tagFilterSearchInput()); clearTextBoxButton = new Button(); - clearTextBoxButton.setStyleName(css.tagFilterButton()); - clearTextBoxButton.addStyleName(css.tagFilterClearButton()); - clearTextBoxButton.addStyleName(css.clearButtonBackgroundImage()); - clearTextBoxButton.addStyleName(css.tagFilterHiddenButton()); + clearTextBoxButton.setStyleName(style.tagFilterButton()); + clearTextBoxButton.addStyleName(style.tagFilterClearButton()); + clearTextBoxButton.addStyleName(style.clearButtonBackgroundImage()); + clearTextBoxButton.addStyleName(style.tagFilterHiddenButton()); clearTextBoxButton.addStyleName("gwt-Button"); clearTextBoxButton.addClickHandler(new ClickHandler() { @Override @@ -886,21 +630,21 @@ public class TaggingPanel extends ComponentWithoutSettings } }); - filterSettingsButton = new Button(""); - filterSettingsButton.setStyleName(css.tagFilterButton()); - filterSettingsButton.addStyleName(css.tagFilterFilterButton()); - filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); + filterSettingsButton = new Button(); + filterSettingsButton.setStyleName(style.tagFilterButton()); + filterSettingsButton.addStyleName(style.tagFilterFilterButton()); + filterSettingsButton.addStyleName(style.filterInactiveButtonBackgroundImage()); filterSettingsButton.addStyleName("gwt-Button"); filterSettingsButton.setTitle(stringMessages.tagsFilter()); filterSettingsButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - showEditTagsFiltersDialog(); + showFilterDialog(); } }); - searchBoxPanel = new FlowPanel(); - searchBoxPanel.setStyleName(css.tagFilterSearchBox()); + Panel searchBoxPanel = new FlowPanel(); + searchBoxPanel.setStyleName(style.tagFilterSearchBox()); searchBoxPanel.add(submitButton); searchBoxPanel.add(searchTextBox); searchBoxPanel.add(clearTextBoxButton); @@ -908,20 +652,21 @@ public class TaggingPanel extends ComponentWithoutSettings add(filterSettingsButton); } - private void showEditTagsFiltersDialog() { - TagsFilterSetsDialog tagsFilterSetsDialog = new TagsFilterSetsDialog(tagFilterSets, stringMessages, - new DialogCallback() { + private void showFilterDialog() { + TagFilterSetsDialog tagsFilterSetsDialog = new TagFilterSetsDialog(tagFilterSets, stringMessages, + new DialogCallback() { @Override - public void ok(final TagsFilterSets newTagsFilterSets) { + public void ok(final TagFilterSets newTagFilterSets) { tagFilterSets.getFilterSets().clear(); - tagFilterSets.getFilterSets().addAll(newTagsFilterSets.getFilterSets()); - tagFilterSets.setActiveFilterSet(newTagsFilterSets.getActiveFilterSet()); + tagFilterSets.getFilterSets().addAll(newTagFilterSets.getFilterSets()); + tagFilterSets.setActiveFilterSet(newTagFilterSets.getActiveFilterSet()); - tagProvider.setTagsFilterSet(newTagsFilterSets.getActiveFilterSetWithGeneralizedType()); - tagProvider.updateFilteredTags(); - tagProvider.refresh(); - updateTagsFilterControlState(newTagsFilterSets); - storeTagsFilterSets(newTagsFilterSets); + tagListProvider.setTagsFilterSet(newTagFilterSets.getActiveFilterSetWithGeneralizedType()); + tagListProvider.updateFilteredTags(); + tagListProvider.refresh(); + updateTagFilterControlState(newTagFilterSets); + storeTagsFilterSets(newTagFilterSets); + updateContent(); } @Override @@ -937,19 +682,19 @@ public class TaggingPanel extends ComponentWithoutSettings * Updates the tags filter checkbox state by setting its check mark and updating its label according to the * current filter selected */ - private void updateTagsFilterControlState(TagsFilterSets filterSets) { + private void updateTagFilterControlState(TagFilterSets filterSets) { String tagsFilterTitle = stringMessages.tagsFilter(); FilterSet> activeFilterSet = filterSets.getActiveFilterSet(); if (activeFilterSet != null) { if (lastActiveTagFilterSet == null) { - filterSettingsButton.removeStyleName(css.filterInactiveButtonBackgroundImage()); - filterSettingsButton.addStyleName(css.filterActiveButtonBackgroundImage()); + filterSettingsButton.removeStyleName(style.filterInactiveButtonBackgroundImage()); + filterSettingsButton.addStyleName(style.filterActiveButtonBackgroundImage()); } lastActiveTagFilterSet = activeFilterSet; } else { if (lastActiveTagFilterSet != null) { - filterSettingsButton.removeStyleName(css.filterActiveButtonBackgroundImage()); - filterSettingsButton.addStyleName(css.filterInactiveButtonBackgroundImage()); + filterSettingsButton.removeStyleName(style.filterActiveButtonBackgroundImage()); + filterSettingsButton.addStyleName(style.filterInactiveButtonBackgroundImage()); } lastActiveTagFilterSet = null; } @@ -960,8 +705,8 @@ public class TaggingPanel extends ComponentWithoutSettings } } - private TagsFilterSets loadTagsFilterSets() { - TagsFilterSets result = null; + private TagFilterSets loadTagFilterSets() { + TagFilterSets result = null; Storage localStorage = Storage.getLocalStorageIfSupported(); if (localStorage != null) { try { @@ -980,7 +725,7 @@ public class TaggingPanel extends ComponentWithoutSettings return result; } - private void storeTagsFilterSets(TagsFilterSets newTagsFilterSets) { + private void storeTagsFilterSets(TagFilterSets newTagsFilterSets) { Storage localStorage = Storage.getLocalStorageIfSupported(); if (localStorage != null) { // delete old value @@ -990,23 +735,45 @@ public class TaggingPanel extends ComponentWithoutSettings TagsFilterSetsJsonDeSerializer serializer = new TagsFilterSetsJsonDeSerializer(); JSONObject jsonObject = serializer.serialize(newTagsFilterSets); localStorage.setItem(LOCAL_STORAGE_TAGS_FILTER_SETS_KEY, jsonObject.toString()); + } else { + Notification.notify(stringMessages.tagFilterNotSavable(), NotificationType.WARNING); } } - private TagsFilterSets createAndAddDefaultTagsFilter() { - TagsFilterSets filterSets = new TagsFilterSets(); - - // TODO add standard filters here - - return filterSets; - } - private void clearSelection() { searchTextBox.setText(""); - clearTextBoxButton.addStyleName(css.tagFilterHiddenButton()); + clearTextBoxButton.addStyleName(style.tagFilterHiddenButton()); onKeyUp(null); } + private void ensureSetSearchFilter() { + if (tagListProvider.getTagFilterSet() == null + || !Util.contains(tagListProvider.getTagFilterSet().getFilters(), this)) { + FilterSet> newFilterSetWithThis = new FilterSet<>(getName()); + if (tagListProvider.getTagFilterSet() != null) { + for (Filter oldFilter : tagListProvider.getTagFilterSet().getFilters()) { + newFilterSetWithThis.addFilter(oldFilter); + } + } + newFilterSetWithThis.addFilter(this); + tagListProvider.setTagsFilterSet(newFilterSetWithThis); + } + } + + private void removeSearchFilter() { + if (tagListProvider.getTagFilterSet() != null + && Util.contains(tagListProvider.getTagFilterSet().getFilters(), this)) { + FilterSet> newFilterSetWithThis = new FilterSet<>( + tagListProvider.getTagFilterSet().getName()); + for (Filter oldFilter : tagListProvider.getTagFilterSet().getFilters()) { + if (oldFilter != this) { + newFilterSetWithThis.addFilter(oldFilter); + } + } + tagListProvider.setTagsFilterSet(newFilterSetWithThis); + } + } + @Override public boolean matches(TagDTO tag) { final Iterable lowercaseKeywords = Util @@ -1053,55 +820,312 @@ public class TaggingPanel extends ComponentWithoutSettings String newValue = searchTextBox.getValue(); if (newValue.trim().isEmpty()) { removeSearchFilter(); - clearTextBoxButton.addStyleName(css.tagFilterHiddenButton()); + clearTextBoxButton.addStyleName(style.tagFilterHiddenButton()); } else { if (newValue.length() >= 2) { - clearTextBoxButton.removeStyleName(css.tagFilterHiddenButton()); - ensureSearchFilterIsSet(); - tagProvider.setTagsFilterSet(tagProvider.getTagsFilterSet()); // + clearTextBoxButton.removeStyleName(style.tagFilterHiddenButton()); + ensureSetSearchFilter(); + tagListProvider.setTagsFilterSet(tagListProvider.getTagFilterSet()); // } } } - - private void ensureSearchFilterIsSet() { - if (tagProvider.getTagsFilterSet() == null - || !Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { - FilterSet> newFilterSetWithThis = new FilterSet<>(getName()); - if (tagProvider.getTagsFilterSet() != null) { - for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { - newFilterSetWithThis.addFilter(oldFilter); - } - } - newFilterSetWithThis.addFilter(this); - tagProvider.setTagsFilterSet(newFilterSetWithThis); - } - } - - private void removeSearchFilter() { - if (tagProvider.getTagsFilterSet() != null - && Util.contains(tagProvider.getTagsFilterSet().getFilters(), this)) { - FilterSet> newFilterSetWithThis = new FilterSet<>( - tagProvider.getTagsFilterSet().getName()); - for (Filter oldFilter : tagProvider.getTagsFilterSet().getFilters()) { - if (oldFilter != this) { - newFilterSetWithThis.addFilter(oldFilter); - } - } - tagProvider.setTagsFilterSet(newFilterSetWithThis); - } - } } - private final HeaderPanel panel; - private final TagCreationPanel tagCreationPanel; - private final Panel filterbarPanel; - private final Label currentFilterLabel; - private final ScrollPanel contentPanel; + /* Dialogs */ + /** + * Dialog for modifying tag buttons + */ + private class TagButtonDialog extends DialogBox { + + private class EditTagButtonsImagesBarCell extends ImagesBarCell { + public static final String ACTION_REMOVE = "ACTION_REMOVE"; + public static final String ACTION_EDIT = "ACTION_EDIT"; + private final StringMessages stringMessages; + + public EditTagButtonsImagesBarCell(StringMessages stringMessages) { + this.stringMessages = stringMessages; + } + + @Override + protected Iterable getImageSpecs() { + return Arrays.asList( + new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), + makeImagePrototype(resources.editIcon())), + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), + makeImagePrototype(IconResources.INSTANCE.removeIcon()))); + } + } + + private Button closeButton, saveButton, cancelButton, addTagButtonButton; + private TagButton selectedTagButton; + + public TagButtonDialog(Panel customButtonsPanel) { + setGlassEnabled(true); + setText(stringMessages.tagEditCustomTagButtons()); + setWidth("450px"); + + TagInputPanel inputPanel = new TagInputPanel(stringMessages); + TagPreviewPanel tagPreviewPanel = new TagPreviewPanel(inputPanel); + CellTable tagButtonsTable = createTable(inputPanel, tagPreviewPanel); + Panel controlButtonPanel = createButtonPanel(tagButtonsTable, inputPanel, tagPreviewPanel); + + Panel mainPanel = new FlowPanel(); + mainPanel.setWidth("100%"); + mainPanel.add(tagButtonsTable); + mainPanel.add(inputPanel); + mainPanel.add(controlButtonPanel); + mainPanel.add(tagPreviewPanel); + getElement().getStyle().setBackgroundColor("white"); + + setWidget(mainPanel); + center(); + } + + private CellTable createTable(TagInputPanel inputPanel, TagPreviewPanel tagPreviewPanel) { + CellTable tagButtonTable = new CellTable(); + tagButtonTable.setStyleName(style.tagButtonTable()); + TextColumn tagColumn = new TextColumn() { + @Override + public String getValue(TagButton button) { + return button.getTag(); + } + }; + TextColumn imageURLColumn = new TextColumn() { + @Override + public String getValue(TagButton button) { + return button.getImageURL(); + } + }; + TextColumn commentColumn = new TextColumn() { + @Override + public String getValue(TagButton button) { + return button.getComment(); + } + }; + Column visibleForPublicColumn = new Column( + new ImageResourceCell()) { + @Override + public ImageResource getValue(TagButton tagButton) { + if (tagButton.isVisibleForPublic()) { + return resources.publicIcon(); + } else { + return resources.privateIcon(); + } + } + }; + ImagesBarColumn actionsColumn = new ImagesBarColumn( + new EditTagButtonsImagesBarCell(stringMessages)); + actionsColumn.setFieldUpdater(new FieldUpdater() { + @Override + public void update(int index, TagButton button, String value) { + if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { + new ConfirmationDialog(stringMessages.tagButtonConfirmDeletionHeading(), + stringMessages.tagButtonConfirmDeletion(button.getTag()), (confirmed) -> { + if (confirmed) { + tagButtons.remove(button); + setRowData(tagButtonTable, tagButtons); + } + }); + } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { + selectedTagButton = button; + + inputPanel.setTag(button.getTag()); + inputPanel.setImageURL(button.getImageURL()); + inputPanel.setComment(button.getComment()); + inputPanel.setVisibleForPublic(button.isVisibleForPublic()); + + tagPreviewPanel.renderPreview(inputPanel); + + saveButton.setVisible(true); + cancelButton.setVisible(true); + closeButton.setVisible(false); + addTagButtonButton.setVisible(false); + + tagButtonTable.setVisible(false); + } + } + }); + + tagButtonTable.addColumn(tagColumn, stringMessages.tagLabelTag()); + tagButtonTable.addColumn(imageURLColumn, stringMessages.tagLabelImageURL()); + tagButtonTable.addColumn(commentColumn, stringMessages.tagLabelComment()); + tagButtonTable.addColumn(visibleForPublicColumn, stringMessages.tagVisibility()); + tagButtonTable.addColumn(actionsColumn, stringMessages.tagLabelAction()); + setRowData(tagButtonTable, tagButtons); + + return tagButtonTable; + } + + private Panel createButtonPanel(CellTable tagButtonTable, TagInputPanel inputPanel, + TagPreviewPanel tagPreviewPanel) { + addSaveButton(tagButtonTable, inputPanel, tagPreviewPanel); + addCancelButton(inputPanel, tagPreviewPanel); + addCloseButton(tagPreviewPanel); + addTagButtonButton(tagButtonTable, inputPanel, tagPreviewPanel); + + Panel controlButtonPanel = new FlowPanel(); + controlButtonPanel.setStyleName(style.buttonsPanel()); + controlButtonPanel.add(closeButton); + controlButtonPanel.add(addTagButtonButton); + controlButtonPanel.add(cancelButton); + controlButtonPanel.add(saveButton); + + return controlButtonPanel; + } + + private void addSaveButton(CellTable tagButtonTable, TagInputPanel inputPanel, + TagPreviewPanel tagPreviewPanel) { + saveButton = new Button(stringMessages.save()); + saveButton.setVisible(false); + saveButton.setStyleName(style.footerButton()); + saveButton.addStyleName("gwt-Button"); + saveButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + if (!inputPanel.getTag().isEmpty()) { + selectedTagButton.setText(inputPanel.getTag()); + selectedTagButton.setTag(inputPanel.getTag()); + selectedTagButton.setComment(inputPanel.getComment()); + selectedTagButton.setImageURL(inputPanel.getImageURL()); + inputPanel.clearAllValues(); + tagPreviewPanel.renderPreview(inputPanel); + tagButtonTable.redraw(); + + saveButton.setVisible(false); + cancelButton.setVisible(false); + closeButton.setVisible(true); + addTagButtonButton.setVisible(true); + selectedTagButton = null; + setRowData(tagButtonTable, tagButtons); + } else { + Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); + } + } + }); + } + + private void addCancelButton(TagInputPanel inputPanel, TagPreviewPanel tagPreviewPanel) { + cancelButton = new Button(stringMessages.cancel()); + cancelButton.setVisible(false); + cancelButton.setStyleName(style.footerButton()); + cancelButton.addStyleName("gwt-Button"); + cancelButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + inputPanel.clearAllValues(); + tagPreviewPanel.renderPreview(inputPanel); + saveButton.setVisible(false); + cancelButton.setVisible(false); + closeButton.setVisible(true); + addTagButtonButton.setVisible(true); + } + }); + } + + private void addCloseButton(TagPreviewPanel tagPreviewPanel) { + closeButton = new Button(stringMessages.close()); + closeButton.setStyleName(style.footerButton()); + closeButton.addStyleName("gwt-Button"); + closeButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + hide(); + } + }); + } + + private void addTagButtonButton(CellTable tagButtonTable, TagInputPanel inputPanel, + TagPreviewPanel tagPreviewPanel) { + addTagButtonButton = new Button(stringMessages.tagAddCustomTagButton()); + addTagButtonButton.setStyleName(style.footerButton()); + addTagButtonButton.addStyleName("gwt-Button"); + addTagButtonButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + if (!inputPanel.getTag().isEmpty()) { + TagButton tagButton = new TagButton(inputPanel.getTag(), inputPanel.getTag(), + inputPanel.getImageURL(), inputPanel.getComment(), inputPanel.isVisibleForPublic()); + inputPanel.clearAllValues(); + tagPreviewPanel.renderPreview(inputPanel); + tagButtons.add(tagButton); + setRowData(tagButtonTable, tagButtons); + } else { + Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); + } + } + }); + } + + private void setRowData(CellTable tagButtonTable, List buttons) { + tagButtonTable.setRowData(buttons); + tagButtonTable.setVisible(!buttons.isEmpty()); + } + } + + /** + * Used to show generic confirmation dialog to ask user for explicit confirmation of an action. + */ + private class ConfirmationDialog extends DialogBox { + + private final Panel mainPanel; + private final TagPanelStyle style = TagPanelResources.INSTANCE.style(); + + public ConfirmationDialog(String title, String text, Consumer consumer) { + mainPanel = new FlowPanel(); + setGlassEnabled(true); + + Label label = new Label(text); + label.getElement().getStyle().setMarginBottom(10, Unit.PX); + + Button confirm = new Button(stringMessages.confirm()); + confirm.setStyleName(style.footerButton()); + confirm.addStyleName("gwt-Button"); + confirm.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + consumer.accept(true); + hide(); + } + }); + + Button cancel = new Button(stringMessages.cancel()); + cancel.setStyleName(style.footerButton()); + cancel.addStyleName("gwt-Button"); + cancel.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + consumer.accept(false); + hide(); + } + }); + + mainPanel.add(label); + mainPanel.add(cancel); + mainPanel.add(confirm); + + setText(title); + getElement().getStyle().setBackgroundColor("white"); + setWidget(mainPanel); + center(); + } + } + + private final TagPanelResources resources; + private final TagPanelStyle style; + + private final TagCellListResources cellResources; + private final TagCellListStyle cellStyle; + private final CellList tagCellList; private final SingleSelectionModel tagSelectionModel; - private final TagListProvider tagListProvider; - private final List customTagButtons; + + private final List tagButtons; + + private final HeaderPanel panel; + private final Panel tagCreationPanel; + private final Panel filterbarPanel; + private final Panel contentPanel; private final StringMessages stringMessages; private final SailingServiceAsync sailingService; @@ -1118,44 +1142,40 @@ public class TaggingPanel extends ComponentWithoutSettings RaceTimesInfoProvider raceTimesInfoProvider) { super(parent, context); - TagPanelResources.INSTANCE.style().ensureInjected(); - CellListResources.INSTANCE.cellListStyle().ensureInjected(); - - // TODO Add this label to ui - currentFilterLabel = new Label(); - tagListProvider = new TagListProvider(currentFilterLabel); - customTagButtons = new ArrayList(); - - panel = new HeaderPanel(); - filterbarPanel = new TagFilterPanel(stringMessages, tagListProvider); - tagCellList = new CellList(new TagCell(false), CellListResources.INSTANCE); - tagSelectionModel = new SingleSelectionModel(); - - contentPanel = new ScrollPanel(); - tagCreationPanel = new TagCreationPanel(stringMessages); - this.stringMessages = stringMessages; this.sailingService = sailingService; this.userService = userService; - userService.addUserStatusEventHandler(this); this.timer = timer; this.raceTimesInfoProvider = raceTimesInfoProvider; + + resources = TagPanelResources.INSTANCE; + style = resources.style(); + style.ensureInjected(); + + cellResources = TagCellListResources.INSTANCE; + cellStyle = cellResources.cellListStyle(); + cellStyle.ensureInjected(); + + tagCellList = new CellList(new TagCell(false), cellResources); + tagSelectionModel = new SingleSelectionModel(); + tagListProvider = new TagListProvider(); + + tagButtons = new ArrayList(); + + panel = new HeaderPanel(); + tagCreationPanel = new TagCreationPanel(stringMessages); + filterbarPanel = new TagFilterPanel(); + contentPanel = new ScrollPanel(); + + userService.addUserStatusEventHandler(this); raceTimesInfoProvider.addRaceTimesInfoProviderListener(this); initializePanel(); } - public TaggingPanel(Component parent, ComponentContext context, StringMessages stringMessages, - SailingServiceAsync sailingService, UserService userService, Timer timer, - RaceTimesInfoProvider raceTimesInfoProvider, String leaderboardName, RaceColumnDTO raceColumn, - FleetDTO fleet) { - this(parent, context, stringMessages, sailingService, userService, timer, raceTimesInfoProvider); - updateRace(leaderboardName, raceColumn, fleet); - } - private void initializePanel() { // Panel - panel.setStyleName(TagPanelResources.INSTANCE.style().tagPanel()); + panel.setStyleName(style.tagPanel()); // Searchbar panel.setHeaderWidget(filterbarPanel); @@ -1174,7 +1194,6 @@ public class TaggingPanel extends ComponentWithoutSettings } }); - // contentPanel.add(currentFilterLabel); contentPanel.add(tagCellList); contentPanel.getElement().getStyle().setHeight(100, Unit.PCT); contentPanel.getElement().getStyle().setPaddingTop(10, Unit.PX); @@ -1197,7 +1216,7 @@ public class TaggingPanel extends ComponentWithoutSettings private void addTagToRaceLog(String tag, String comment, String imageURL, boolean isPublic) { if (isLoggedInAndRaceLogAvailable()) { - if (tag.length() > 0) { + if (!tag.isEmpty()) { sailingService.addTagToRaceLog(leaderboardName, raceColumn.getName(), fleet.getName(), tag, comment, imageURL, isPublic, new MillisecondsTimePoint(timer.getTime()), new AsyncCallback() { @@ -1221,7 +1240,6 @@ public class TaggingPanel extends ComponentWithoutSettings Notification.notify(stringMessages.tagNotSpecified(), NotificationType.WARNING); } } - } private void removeTagFromRaceLog(TagDTO tag) { @@ -1248,8 +1266,7 @@ public class TaggingPanel extends ComponentWithoutSettings } private boolean isLoggedInAndRaceLogAvailable() { - return !(userService.getCurrentUser() == null || leaderboardName == null || raceColumn == null - || fleet == null); + return userService.getCurrentUser() != null && leaderboardName != null && raceColumn != null && fleet != null; } private void updateContent() { @@ -1263,14 +1280,21 @@ public class TaggingPanel extends ComponentWithoutSettings public void raceTimesInfosReceived(Map raceTimesInfo, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) { raceTimesInfo.forEach((raceIdentifier, raceInfo) -> { + // Will be true if local list of tags get modified with new received tags, otherwise false. boolean modifiedTags = false; + // Will be true if latestReceivedTagTime needs to be updated in raceTimesInfoprovider, otherwise false. boolean updatedLatestTag = false; + // TODO: Is this if-clause still required? if (raceIdentifier.equals(raceInfo.getRaceIdentifier())) { + // local list of already received tags List currentTags = tagListProvider.getAllTags(); + // createdAt or revokedAt timepoint of latest received tag TimePoint latestReceivedTagTime = raceTimesInfoProvider.getLatestReceivedTagTime(raceIdentifier); + // get difference in tags since latestReceivedTagTime for (TagDTO tag : raceInfo.getTags()) { if (tag.getRevokedAt() != null) { - // tag got revoked + // received tag is revoked => latestReceivedTagTime will be revokedAt if revoke event occured + // before latestReceivedTagTime currentTags.remove(tag); modifiedTags = true; if (latestReceivedTagTime == null || (latestReceivedTagTime != null @@ -1279,7 +1303,8 @@ public class TaggingPanel extends ComponentWithoutSettings updatedLatestTag = true; } } else if (!currentTags.contains(tag)) { - // tag did not get revoked + // received tag is NOT revoked => latestReceivedTagTime will be createdAt if tag event occured + // before latestReceivedTagTime currentTags.add(tag); modifiedTags = true; if (latestReceivedTagTime == null || (latestReceivedTagTime != null @@ -1289,9 +1314,11 @@ public class TaggingPanel extends ComponentWithoutSettings } } } + // set new latestReceivedTagTime for next data request if (updatedLatestTag) { raceTimesInfoProvider.setLatestReceivedTagTime(raceIdentifier, latestReceivedTagTime); } + // refresh UI if tags did change if (modifiedTags) { updateContent(); } @@ -1301,6 +1328,7 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onUserStatusChange(UserDTO user, boolean preAuthenticated) { + // clear list of local tags to hide private tags of previous user tagListProvider.getAllTags().clear(); raceTimesInfoProvider.getRaceIdentifiers().forEach((raceIdentifier) -> { raceTimesInfoProvider.setLatestReceivedTagTime(raceIdentifier, null); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css index 1e90ab81272..bb6db9e499a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging-panel.css @@ -78,7 +78,7 @@ b { float: right; } -.footerPanel { +.buttonsPanel { float: right; width: 100%; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java index f8e64d0ec25..30bbfd5c775 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/TagDTO.java @@ -5,18 +5,12 @@ import com.sap.sse.common.TimePoint; public class TagDTO implements IsSerializable { - private String tag; - private String comment; - private String imageURL; - private String username; + private String tag, comment, imageURL, username; private boolean visibleForPublic; - private TimePoint raceTimepoint; - private TimePoint createdAt; - private TimePoint revokedAt; + private TimePoint raceTimepoint, createdAt, revokedAt; // for GWT - public TagDTO() { - } + public TagDTO() {} public TagDTO(String tag, String comment, String imageURL, String username, boolean visibleForPublic, TimePoint raceTimepoint, TimePoint createdAt) { this(tag, comment, imageURL, username, visibleForPublic, raceTimepoint, createdAt, null); @@ -115,7 +109,7 @@ public class TagDTO implements IsSerializable { + ", username=" + username + ", raceTimepoint=" + raceTimepoint + ", createdAt=" + createdAt - + ", isPublic" + visibleForPublic + + ", isPublic=" + visibleForPublic + ", revokedAt=" + revokedAt + "]"; } } \ No newline at end of file From a19338ab3abc98f137820460cd765379482cb19d Mon Sep 17 00:00:00 2001 From: D067890 Date: Mon, 20 Aug 2018 08:53:02 +0200 Subject: [PATCH 154/292] bug4104: refactoring part 2 --- .../abstractlog/race/RaceLogTagEvent.java | 12 +- .../race/impl/RaceLogTagEventImpl.java | 11 +- .../AbstractTagNumberFilterUIFactory.java | 37 ----- .../AbstractTagTextFilterUIFactory.java | 6 +- .../filter/AbstractTagsFilterSetDialog.java | 74 ++++----- .../client/shared/filter/TagFilterSets.java | 19 +-- .../shared/filter/TagFilterSetsDialog.java | 151 +++++++++--------- .../shared/filter/TagFilterWithUIFactory.java | 7 +- .../ui/client/shared/filter/TagTagFilter.java | 37 ++--- .../shared/filter/TagTagFilterUIFactory.java | 17 +- .../shared/filter/TagUsernameFilter.java | 40 ++--- .../filter/TagUsernameFilterUIFactory.java | 12 +- .../TagsFilterSetsJsonDeSerializer.java | 24 +-- 13 files changed, 209 insertions(+), 238 deletions(-) delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagNumberFilterUIFactory.java diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java index 637b5bf7735..069af85e9c9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogTagEvent.java @@ -6,16 +6,16 @@ import com.sap.sse.common.TimePoint; public interface RaceLogTagEvent extends RaceLogEvent, Revokable { String getTag(); - + String getUsername(); - + String getComment(); - - String getImageURL(); - + + String getImageURL(); + boolean isVisibleForPublic(); void markAsRevoked(TimePoint revokedAt); - + TimePoint getRevokedAt(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java index a74a4a6be38..89620d2d035 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogTagEventImpl.java @@ -57,8 +57,13 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE return username; } + @Override + public boolean isVisibleForPublic() { + return visibleForPublic; + } + /** - * Only sets revokedAt if tag is not already revoked and given timepoint is not null. + * Only sets revokedAt if tag is not already revoked and given TimePoint is not null. */ @Override public void markAsRevoked(TimePoint revokedAt) { @@ -83,10 +88,6 @@ public class RaceLogTagEventImpl extends RaceLogEventImpl implements RaceLogTagE } @Override - public boolean isVisibleForPublic() { - return visibleForPublic; - } - public boolean equals(Object obj) { if (this == obj) return true; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagNumberFilterUIFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagNumberFilterUIFactory.java deleted file mode 100644 index 39172102a72..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagNumberFilterUIFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.sap.sailing.gwt.ui.client.shared.filter; - -import java.util.ArrayList; -import java.util.List; - -import com.google.gwt.user.client.ui.ListBox; -import com.sap.sailing.gwt.ui.shared.TagDTO; -import com.sap.sse.common.filter.BinaryOperator; -import com.sap.sse.common.filter.NumberFilter; -import com.sap.sse.gwt.client.dialog.DataEntryDialog; - -public abstract class AbstractTagNumberFilterUIFactory implements FilterUIFactory { - protected List supportedOperators; - protected BinaryOperator.Operators defaultOperator; - protected NumberFilter tagNumberFilter; - - public AbstractTagNumberFilterUIFactory(NumberFilter tagNumberFilter, BinaryOperator.Operators defaultOperator) { - this.tagNumberFilter = tagNumberFilter; - this.defaultOperator = defaultOperator; - supportedOperators = new ArrayList(); - } - - protected ListBox createOperatorSelectionListBox(DataEntryDialog dataEntryDialog) { - ListBox operatorsListBox = dataEntryDialog.createListBox(false); - int i = 0; - for (BinaryOperator.Operators op : supportedOperators) { - operatorsListBox.addItem(FilterOperatorsFormatter.format(op), op.name()); - if (tagNumberFilter.getOperator() != null && tagNumberFilter.getOperator().getName().equals(op.name())) { - operatorsListBox.setSelectedIndex(i); - } else if (defaultOperator != null && defaultOperator.equals(op)) { - operatorsListBox.setSelectedIndex(i); - } - i++; - } - return operatorsListBox; - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagTextFilterUIFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagTextFilterUIFactory.java index b9196987eb3..f0a7e90a441 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagTextFilterUIFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagTextFilterUIFactory.java @@ -10,7 +10,7 @@ import com.sap.sse.common.filter.TextOperator; import com.sap.sse.gwt.client.dialog.DataEntryDialog; public abstract class AbstractTagTextFilterUIFactory implements FilterUIFactory { - + protected List supportedOperators; protected TextOperator.Operators defaultOperator; protected TextFilter tagTextFilter; @@ -24,9 +24,9 @@ public abstract class AbstractTagTextFilterUIFactory implements FilterUIFactory< protected ListBox createOperatorSelectionListBox(DataEntryDialog dataEntryDialog) { ListBox operatorsListBox = dataEntryDialog.createListBox(false); int i = 0; - for(TextOperator.Operators op: supportedOperators) { + for (TextOperator.Operators op : supportedOperators) { operatorsListBox.addItem(FilterOperatorsFormatter.format(op), op.name()); - if(tagTextFilter.getOperator() != null && tagTextFilter.getOperator().getName().equals(op.name())) { + if (tagTextFilter.getOperator() != null && tagTextFilter.getOperator().getName().equals(op.name())) { operatorsListBox.setSelectedIndex(i); } else if (defaultOperator != null && defaultOperator.equals(op)) { operatorsListBox.setSelectedIndex(i); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagsFilterSetDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagsFilterSetDialog.java index 24f26d8b7dc..7cec10548bc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagsFilterSetDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/filter/AbstractTagsFilterSetDialog.java @@ -36,18 +36,18 @@ public abstract class AbstractTagsFilterSetDialog extends DataEntryDialog filterEditWidgets; private final List> filterUIFactories; private final List