configuration/httpd/conf.d/000-macros.conf
... ...
@@ -1,6 +1,20 @@
1 1
# ARCHIVE, based on i3.2xlarge, 64GB RAM and 1.9TB swap
2
-Define ARCHIVE_IP 172.31.40.242
3
-Define ARCHIVE_FAILOVER_IP 172.31.40.242
2
+Define ARCHIVE_IP 172.31.46.178
3
+Define ARCHIVE_FAILOVER_IP 172.31.15.201
4
+#Define ARCHIVE_FAILOVER_IP 172.31.15.54
5
+#Define ARCHIVE_FAILOVER_IP 172.31.15.128
6
+#Define ARCHIVE_FAILOVER_IP 172.31.5.109
7
+#Define ARCHIVE_FAILOVER_IP 172.31.41.46
8
+#Define ARCHIVE_FAILOVER_IP 172.31.5.186
9
+#Define ARCHIVE_FAILOVER_IP 172.31.41.46
10
+#Define ARCHIVE_FAILOVER_IP 172.31.8.46
11
+#Define ARCHIVE_FAILOVER_IP 172.31.12.171
12
+#Define ARCHIVE_FAILOVER_IP 172.31.15.227
13
+#Define ARCHIVE_FAILOVER_IP 172.31.12.220
14
+#Define ARCHIVE_FAILOVER_IP 172.31.11.126
15
+#Define ARCHIVE_FAILOVER_IP 172.31.2.103
16
+#Define ARCHIVE_FAILOVER_IP 172.31.40.242
17
+#Define ARCHIVE_FAILOVER_IP 172.31.46.203
4 18
Define PRODUCTION_ARCHIVE ${ARCHIVE_IP}
5 19
6 20
<Macro ArchiveRewrite>
... ...
@@ -34,115 +48,6 @@ Define PRODUCTION_ARCHIVE ${ARCHIVE_IP}
34 48
AllowEncodedSlashes NoDecode
35 49
</Macro>
36 50
37
-<Macro Headers-Tennis>
38
- AllowEncodedSlashes On
39
-
40
- SetEnvIf Request_Method POST REQUEST_IS_POST=1
41
- SetEnvIf Request_URI ^/?$ REQUEST_IS_POST=1
42
-
43
- Header set Expires "Sun, 19 Nov 1978 05:00:00 GMT" env=REQUEST_IS_POST
44
- Header set Cache-Control no-cache,no-store,must-revalidate,post-check=0,pre-check=0 env=REQUEST_IS_POST
45
-
46
- <IfModule mod_mime.c>
47
- AddType text/css .css
48
- AddType application/x-javascript .js
49
- AddType text/x-component .htc
50
- AddType text/html .html .htm
51
- AddType text/richtext .rtf .rtx
52
- AddType image/svg+xml .svg .svgz
53
- AddType text/plain .txt
54
- AddType text/xsd .xsd
55
- AddType text/xsl .xsl
56
- AddType text/xml .xml
57
- AddType video/asf .asf .asx .wax .wmv .wmx
58
- AddType video/avi .avi
59
- AddType image/bmp .bmp
60
- AddType application/java .class
61
- AddType video/divx .divx
62
- AddType application/msword .doc .docx
63
- AddType application/vnd.ms-fontobject .eot
64
- AddType application/x-msdownload .exe
65
- AddType image/gif .gif
66
- AddType application/x-gzip .gz .gzip
67
- AddType image/x-icon .ico
68
- AddType image/jpeg .jpg .jpeg .jpe
69
- AddType application/vnd.ms-access .mdb
70
- AddType audio/midi .mid .midi
71
- AddType video/quicktime .mov .qt
72
- AddType audio/mpeg .mp3 .m4a
73
- AddType video/mp4 .mp4 .m4v
74
- AddType video/mpeg .mpeg .mpg .mpe
75
- AddType application/vnd.ms-project .mpp
76
- AddType application/x-font-otf .otf
77
- AddType application/vnd.oasis.opendocument.database .odb
78
- AddType application/vnd.oasis.opendocument.chart .odc
79
- AddType application/vnd.oasis.opendocument.formula .odf
80
- AddType application/vnd.oasis.opendocument.graphics .odg
81
- AddType application/vnd.oasis.opendocument.presentation .odp
82
- AddType application/vnd.oasis.opendocument.spreadsheet .ods
83
- AddType application/vnd.oasis.opendocument.text .odt
84
- AddType audio/ogg .ogg
85
- AddType application/pdf .pdf
86
- AddType image/png .png
87
- AddType application/vnd.ms-powerpoint .pot .pps .ppt .pptx
88
- AddType audio/x-realaudio .ra .ram
89
- AddType application/x-shockwave-flash .swf
90
- AddType application/x-tar .tar
91
- AddType image/tiff .tif .tiff
92
- AddType application/x-font-ttf .ttf .ttc
93
- AddType audio/wav .wav
94
- AddType audio/wma .wma
95
- AddType application/vnd.ms-write .wri
96
- AddType application/vnd.ms-excel .xla .xls .xlsx .xlt .xlw
97
- AddType application/zip .zip
98
- </IfModule>
99
-
100
- <IfModule mod_deflate.c>
101
- # Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/
102
- <IfModule mod_setenvif.c>
103
- <IfModule mod_headers.c>
104
- SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
105
- RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
106
- </IfModule>
107
- </IfModule>
108
-
109
- <IfModule filter_module>
110
- # HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
111
- FilterDeclare COMPRESS
112
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/html'"
113
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/css'"
114
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/plain'"
115
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/xml'"
116
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/x-component'"
117
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/javascript'"
118
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/json'"
119
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/xml'"
120
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/xhtml+xml'"
121
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/rss+xml'"
122
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/atom+xml'"
123
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/vnd.ms-fontobject'"
124
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/svg+xml'"
125
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/x-icon'"
126
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/gif'"
127
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/jpeg'"
128
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/png'"
129
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/x-font-ttf'"
130
- FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$font/opentype'"
131
- FilterChain COMPRESS
132
- FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
133
- </IfModule>
134
-
135
- <IfModule !mod_filter.c>
136
- # Legacy versions of Apache
137
- AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
138
- AddOutputFilterByType DEFLATE application/javascript
139
- AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
140
- AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
141
- AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype
142
- </IfModule>
143
- </IfModule>
144
-</Macro>
145
-
146 51
<Macro Rewrite $IP $PORT>
147 52
ProxyPass "/" "http://$IP:$PORT/" nocanon
148 53
# This is what it was before, requiring AllowEncodedSlashes On instead of NoDecode:
configuration/httpd/conf.d/000-main.conf
... ...
@@ -62,23 +62,6 @@ Use Home-ARCHIVE www.sapsailing.com
62 62
</Directory>
63 63
</VirtualHost>
64 64
65
-# Git Viewer -->
66
-<VirtualHost *:80>
67
- ServerName gitlist.sapsailing.com
68
- CustomLog logs/services_log combined env=!original_client_ip
69
- CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
70
- DocumentRoot /var/www/gitlist
71
- AddHandler php5-script .php
72
- AddType text/html .php
73
- DirectoryIndex index.php
74
- <Directory /var/www/gitlist>
75
- Options Indexes FollowSymLinks MultiViews
76
- AllowOverride All
77
- Order allow,deny
78
- allow from all
79
- </Directory>
80
-</VirtualHost>
81
-
82 65
<VirtualHost *:80>
83 66
ServerName bugzilla.sapsailing.com
84 67
RewriteEngine On
configuration/httpd/conf.d/001-events.conf
... ...
@@ -21,8 +21,8 @@ Use Status 172.31.42.171 internal-server-status
21 21
Use Status 127.0.0.1 internal-server-status
22 22
23 23
# Uncomment the following and update the internal IP to what your Archive server candidate is
24
-Use Plain archive-failover.sapsailing.com 172.31.40.12 8888
25
-Use Plain archive-candidate.sapsailing.com 172.31.46.203 8888
24
+Use Plain archive-failover.sapsailing.com ${ARCHIVE_FAILOVER_IP} 8888
25
+Use Plain archive-candidate.sapsailing.com 172.31.46.178 8888
26 26
27 27
Use Plain my-master.sapsailing.com 172.31.24.34 8888
28 28
configuration/httpd/conf.d/007-sail-insight.conf
... ...
@@ -2,20 +2,6 @@
2 2
<VirtualHost *:80>
3 3
ServerName sail-insight.com
4 4
ServerAlias www.sail-insight.com
5
- RedirectPermanent / https://sail-insight.com/
6
-</VirtualHost>
7
-
8
-<Macro SSL-sail-insight>
9
- SSLEngine On
10
- SSLCertificateFile /etc/letsencrypt/live/sail-insight.com/cert.pem
11
- SSLCertificateKeyFile /etc/letsencrypt/live/sail-insight.com/privkey.pem
12
- SSLCertificateChainFile /etc/letsencrypt/live/sail-insight.com/fullchain.pem
13
-</Macro>
14
-
15
-<VirtualHost *:443>
16
- ServerName sail-insight.com
17
- ServerAlias www.sail-insight.com
18
- Use SSL-sail-insight
19 5
CustomLog logs/services_log combined env=!original_client_ip
20 6
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
21 7
Alias / /home/trac/sail-insight-website/
configuration/httpd/conf.d/austrianleague2023.sapsailing.com.conf
... ...
@@ -0,0 +1 @@
1
+Use Home-ARCHIVE austrianleague2023.sapsailing.com
configuration/httpd/conf.d/hongkongraceweek2024.sapsailing.com.conf
... ...
@@ -0,0 +1 @@
1
+Use Event-ARCHIVE hongkongraceweek2024.sapsailing.com c2d54400-6144-4507-9e9f-1f6d26bc6e59
configuration/httpd/conf.d/polishleague2023.sapsailing.com.conf
... ...
@@ -0,0 +1 @@
1
+Use Series-ARCHIVE polishleague2023.sapsailing.com 87023ec6-d372-4222-a217-3c7edb3bcfdf
configuration/httpd/conf.d/rs21polish2023.sapsailing.com.conf
... ...
@@ -0,0 +1 @@
1
+Use Series-ARCHIVE rs21polish2023.sapsailing.com "5593a4e3-7122-43fb-bef5-e133c649e108"
configuration/httpd/conf.d/wlz2023.sapsailing.com.conf
... ...
@@ -0,0 +1 @@
1
+Use Series-ARCHIVE wlz2023.sapsailing.com fe076ac2-6fca-4457-ad2d-761a3d8ad812
configuration/httpd/conf/httpd.conf
... ...
@@ -925,3 +925,4 @@ BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
925 925
# CustomLog logs/dummy-host.example.com-access_log common
926 926
#</VirtualHost>
927 927
928
+
java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/coursetemplate/test/TestLapConfiguration.java
... ...
@@ -26,9 +26,9 @@ import com.sap.sailing.domain.coursetemplate.impl.CourseTemplateImpl;
26 26
import com.sap.sailing.domain.coursetemplate.impl.MarkRoleImpl;
27 27
import com.sap.sailing.domain.coursetemplate.impl.MarkRolePairImpl;
28 28
import com.sap.sailing.domain.coursetemplate.impl.MarkTemplateImpl;
29
-import com.sap.sailing.domain.coursetemplate.impl.RepeatablePartImpl;
30 29
import com.sap.sailing.domain.coursetemplate.impl.WaypointTemplateImpl;
31 30
import com.sap.sse.common.Util;
31
+import com.sap.sse.common.impl.RepeatablePartImpl;
32 32
33 33
public class TestLapConfiguration {
34 34
private CourseTemplate courseTemplate;
java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/coursetemplate/CourseConfiguration.java
... ...
@@ -6,12 +6,14 @@ import java.util.Map;
6 6
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
7 7
import com.sap.sailing.domain.base.Mark;
8 8
import com.sap.sse.common.Named;
9
+import com.sap.sse.common.WithOptionalRepeatablePart;
9 10
10 11
/**
11 12
* A course that does not necessarily consist of {@link Mark}s existing in a regatta but instead is defined by
12 13
* {@link MarkConfiguration}s. This means changes to the model are easily possible without requiring to pollute the
13 14
* {@link RegattaLog}. The effective Marks will then be created upon Course creation based on the
14
- * {@link MarkConfiguration}s.
15
+ * {@link MarkConfiguration}s. See, e.g.,
16
+ * {@link CourseAndMarkConfigurationFactory#createCourseFromConfigurationAndDefineMarksAsNeeded}.
15 17
* <p>
16 18
*
17 19
* This is the model represented in a course editor which deals with editing the waypoint sequence as well as changing
... ...
@@ -25,8 +27,9 @@ import com.sap.sse.common.Named;
25 27
* that the number of laps requested is reflected in the waypoint sequence consistently.
26 28
* <p>
27 29
*
28
- * When used in a request to create a course template, the {@link #getRepeatablePart()} will be used as the
29
- * new course template's {@link CourseTemplate#getRepeatablePart() repeatable part}.<p>
30
+ * When used in a request to create a course template, the {@link #getRepeatablePart()} will be used as the new course
31
+ * template's {@link CourseTemplate#getRepeatablePart() repeatable part}.
32
+ * <p>
30 33
*
31 34
* In particular, the base {@link #getWaypoints() waypoints sequence}, when returned by a request, has at least one
32 35
* occurrence of a repeatable part, should the configuration specify a course template, be consistent with it, and
java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/coursetemplate/CourseTemplate.java
... ...
@@ -10,6 +10,7 @@ import com.sap.sailing.domain.base.Mark;
10 10
import com.sap.sailing.domain.common.security.SecuredDomainType;
11 11
import com.sap.sse.common.NamedWithUUID;
12 12
import com.sap.sse.common.Util;
13
+import com.sap.sse.common.WithOptionalRepeatablePart;
13 14
import com.sap.sse.security.shared.HasPermissions;
14 15
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
15 16
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/coursetemplate/CourseTemplateCompatibilityChecker.java
... ...
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.coursetemplate;
3 3
import java.util.Iterator;
4 4
5 5
import com.sap.sailing.domain.base.CourseBase;
6
+import com.sap.sse.common.RepeatablePart;
6 7
import com.sap.sse.common.Util;
7 8
8 9
/**
java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/coursetemplate/MarkConfigurationResponseAnnotation.java
... ...
@@ -15,5 +15,11 @@ import com.sap.sse.common.Util.Triple;
15 15
*/
16 16
public interface MarkConfigurationResponseAnnotation {
17 17
GPSFix getLastKnownPosition();
18
+
19
+ /**
20
+ * @return a non-{@code null} but possibly empty sequence of device mappings; the triple holds the
21
+ * device identifier, the time range during which the device was assigned, and optionally the last
22
+ * known GPS fix if one has been received.
23
+ */
18 24
Iterable<Triple<DeviceIdentifier, TimeRange, GPSFix>> getDeviceMappings();
19 25
}
java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/coursetemplate/MarkRole.java
... ...
@@ -4,7 +4,6 @@ import java.util.Collections;
4 4
import java.util.UUID;
5 5
6 6
import com.sap.sailing.domain.common.security.SecuredDomainType;
7
-import com.sap.sse.common.Named;
8 7
import com.sap.sse.common.NamedWithUUID;
9 8
import com.sap.sse.security.shared.HasPermissions;
10 9
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
... ...
@@ -33,7 +32,7 @@ import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
33 32
* be solved.
34 33
35 34
*/
36
-public interface MarkRole extends Named, NamedWithUUID, WithQualifiedObjectIdentifier, ControlPointTemplate {
35
+public interface MarkRole extends NamedWithUUID, WithQualifiedObjectIdentifier, ControlPointTemplate {
37 36
public static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(UUID markPropertiesUUID) {
38 37
return new TypeRelativeObjectIdentifier(markPropertiesUUID.toString());
39 38
}
java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/coursetemplate/RepeatablePart.java
... ...
@@ -1,89 +0,0 @@
1
-package com.sap.sailing.domain.coursetemplate;
2
-
3
-import java.io.Serializable;
4
-import java.util.ArrayList;
5
-import java.util.List;
6
-
7
-import com.sap.sse.common.Util;
8
-
9
-/**
10
- * Reusable implementation of the semantics for the repeatable part of a course sequence. The sequence is defined by the
11
- * start and end of the zero-based repeatable part of the complete sequence. The following requirements need to be
12
- * fulfilled:
13
- * <ul>
14
- * <li>The {@link #getZeroBasedIndexOfRepeatablePartStart()} and {@link #getZeroBasedIndexOfRepeatablePartEnd()} are
15
- * required to be >=0</li>
16
- * <li>{@link #getZeroBasedIndexOfRepeatablePartStart()} is truly less than {@link #getZeroBasedIndexOfRepeatablePartEnd()}</li>
17
- * </ul>
18
- */
19
-public interface RepeatablePart extends Serializable {
20
- /**
21
- * The index into {@link #waypoints} of the first waypoint that is to be cloned for repetitive laps.
22
- */
23
- int getZeroBasedIndexOfRepeatablePartStart();
24
-
25
- /**
26
- * The index into {@link #waypoints} of the first waypoint that comes after the sub-sequence to be cloned for
27
- * repetitive laps.
28
- */
29
- int getZeroBasedIndexOfRepeatablePartEnd();
30
-
31
- default int length() {
32
- return getZeroBasedIndexOfRepeatablePartEnd()-getZeroBasedIndexOfRepeatablePartStart();
33
- }
34
-
35
- /**
36
- * Returns a sequence of waypoints (T) that can be use to construct a course. If this course template
37
- * defines a repeatable waypoint sub-sequence, the {@code numberOfLaps} parameter is used to decide how many times
38
- * to repeat this sub-sequence. Typically, the repeatable sub-sequence will be repeated one times fewer than the
39
- * {@code numberOfLaps}. For example, in a typical windward-leeward "L" course we would have
40
- * {@code Start/Finish, [1, 4p/4s], 1, Start/Finish}. For an "L1" course with only one lap, we'd like to have
41
- * {@code Start/Finish, 1, Start/Finish}, so the repeatable sub-sequence, enclosed by the brackets in the example
42
- * above, will occur zero times. For an "L2" the repeatable sub-sequence will occur once, and so on.
43
- *
44
- * @throws IllegalArgumentException
45
- * in case the given {@code sequenceWithRepeatablePart} contains less or equal elements to
46
- * {@link #getZeroBasedIndexOfRepeatablePartEnd()}.
47
- */
48
- default <T> Iterable<T> createSequence(int laps, Iterable<T> sequenceWithRepeatablePart) {
49
- validateRepeatablePartForSequence(sequenceWithRepeatablePart);
50
- final int zeroBasedIndexOfRepeatablePartStart = getZeroBasedIndexOfRepeatablePartStart();
51
- final int zeroBasedIndexOfRepeatablePartEnd = getZeroBasedIndexOfRepeatablePartEnd();
52
- final List<T> sequenceWithRepeatablePartAsList = new ArrayList<>();
53
- Util.addAll(sequenceWithRepeatablePart, sequenceWithRepeatablePartAsList);
54
- final int sequenceLength = sequenceWithRepeatablePartAsList.size();
55
- final List<T> result = new ArrayList<>();
56
- // Non-repeatable start of the sequence
57
- for (int i = 0; i < zeroBasedIndexOfRepeatablePartStart; i++) {
58
- result.add(sequenceWithRepeatablePartAsList.get(i));
59
- }
60
- // Repeatable part of the sequence
61
- for (int lap = 1; lap < laps; lap++) {
62
- for (int i = zeroBasedIndexOfRepeatablePartStart; i < zeroBasedIndexOfRepeatablePartEnd; i++) {
63
- result.add(sequenceWithRepeatablePartAsList.get(i));
64
- }
65
- }
66
- // Non-repeatable end of the sequence
67
- for (int i = zeroBasedIndexOfRepeatablePartEnd; i < sequenceLength; i++) {
68
- result.add(sequenceWithRepeatablePartAsList.get(i));
69
- }
70
- return result;
71
- }
72
-
73
- /**
74
- * Validates that this repeatable part is compatible with the given {@code sequenceWithRepeatablePart} and causes an
75
- * exception in case it isn't.
76
- *
77
- * @throws IllegalArgumentException
78
- * in case the given {@code sequenceWithRepeatablePart} contains less or equal elements to
79
- * {@link #getZeroBasedIndexOfRepeatablePartEnd()}.
80
- */
81
- default <T> void validateRepeatablePartForSequence(Iterable<T> sequenceWithRepeatablePart) {
82
- final int zeroBasedIndexOfRepeatablePartEnd = getZeroBasedIndexOfRepeatablePartEnd();
83
- final int sequenceLength = Util.size(sequenceWithRepeatablePart);
84
- if (sequenceLength < zeroBasedIndexOfRepeatablePartEnd) {
85
- throw new IllegalArgumentException("Repeatable part (" + getZeroBasedIndexOfRepeatablePartStart() + ", "
86
- + zeroBasedIndexOfRepeatablePartEnd + ") is out of range for sequence of length " + sequenceLength);
87
- }
88
- }
89
-}
java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/coursetemplate/WithOptionalRepeatablePart.java
... ...
@@ -1,9 +0,0 @@
1
-package com.sap.sailing.domain.coursetemplate;
2
-
3
-public interface WithOptionalRepeatablePart {
4
- default boolean hasRepeatablePart() {
5
- return getRepeatablePart() != null;
6
- }
7
-
8
- RepeatablePart getRepeatablePart();
9
-}
java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/coursetemplate/impl/CourseConfigurationImpl.java
... ...
@@ -11,8 +11,8 @@ import com.sap.sailing.domain.coursetemplate.CourseTemplate;
11 11
import com.sap.sailing.domain.coursetemplate.CourseTemplateCompatibilityChecker;
12 12
import com.sap.sailing.domain.coursetemplate.MarkConfiguration;
13 13
import com.sap.sailing.domain.coursetemplate.MarkRole;
14
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
15 14
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
15
+import com.sap.sse.common.RepeatablePart;
16 16
17 17
public class CourseConfigurationImpl<P> implements CourseConfiguration<P> {
18 18
private static final long serialVersionUID = -9189989170055144298L;
java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/coursetemplate/impl/CourseTemplateImpl.java
... ...
@@ -12,8 +12,8 @@ import java.util.UUID;
12 12
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
13 13
import com.sap.sailing.domain.coursetemplate.MarkRole;
14 14
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
15
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
16 15
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
16
+import com.sap.sse.common.RepeatablePart;
17 17
import com.sap.sse.common.Util;
18 18
import com.sap.sse.common.impl.NamedWithUUIDImpl;
19 19
java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/coursetemplate/impl/RepeatablePartImpl.java
... ...
@@ -1,39 +0,0 @@
1
-package com.sap.sailing.domain.coursetemplate.impl;
2
-
3
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
4
-
5
-public class RepeatablePartImpl implements RepeatablePart {
6
- private static final long serialVersionUID = -7432656529810302123L;
7
-
8
- private final int zeroBasedIndexOfRepeatablePartStart;
9
-
10
- private final int zeroBasedIndexOfRepeatablePartEnd;
11
-
12
- public RepeatablePartImpl(int zeroBasedIndexOfRepeatablePartStart, int zeroBasedIndexOfRepeatablePartEnd) {
13
- super();
14
- if (zeroBasedIndexOfRepeatablePartStart < 0 || zeroBasedIndexOfRepeatablePartEnd < 0) {
15
- throw new IllegalArgumentException("No negative indices are possible for the repeatable part.");
16
- }
17
- if (zeroBasedIndexOfRepeatablePartStart >= zeroBasedIndexOfRepeatablePartEnd) {
18
- throw new IllegalArgumentException(
19
- "The start of the repeatable part needs to be less than the end such that the repeatable part has at least one element.");
20
- }
21
- this.zeroBasedIndexOfRepeatablePartStart = zeroBasedIndexOfRepeatablePartStart;
22
- this.zeroBasedIndexOfRepeatablePartEnd = zeroBasedIndexOfRepeatablePartEnd;
23
- }
24
-
25
- @Override
26
- public int getZeroBasedIndexOfRepeatablePartStart() {
27
- return zeroBasedIndexOfRepeatablePartStart;
28
- }
29
-
30
- @Override
31
- public int getZeroBasedIndexOfRepeatablePartEnd() {
32
- return zeroBasedIndexOfRepeatablePartEnd;
33
- }
34
-
35
- @Override
36
- public String toString() {
37
- return "["+getZeroBasedIndexOfRepeatablePartStart()+".."+getZeroBasedIndexOfRepeatablePartEnd()+"]";
38
- }
39
-}
java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/common/impl/RepeatablePartImpl_CustomFieldSerializer.java
... ...
@@ -0,0 +1,49 @@
1
+package com.google.gwt.user.client.rpc.core.com.sap.sse.common.impl;
2
+
3
+import com.google.gwt.user.client.rpc.CustomFieldSerializer;
4
+import com.google.gwt.user.client.rpc.SerializationException;
5
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
6
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
7
+import com.sap.sse.common.impl.RepeatablePartImpl;
8
+
9
+public class RepeatablePartImpl_CustomFieldSerializer extends CustomFieldSerializer<RepeatablePartImpl> {
10
+
11
+ @Override
12
+ public void serializeInstance(SerializationStreamWriter streamWriter, RepeatablePartImpl instance)
13
+ throws SerializationException {
14
+ serialize(streamWriter, instance);
15
+ }
16
+
17
+ public static void serialize(SerializationStreamWriter streamWriter, RepeatablePartImpl instance)
18
+ throws SerializationException {
19
+ streamWriter.writeInt(instance.getZeroBasedIndexOfRepeatablePartStart());
20
+ streamWriter.writeInt(instance.getZeroBasedIndexOfRepeatablePartEnd());
21
+ }
22
+
23
+ @Override
24
+ public boolean hasCustomInstantiateInstance() {
25
+ return true;
26
+ }
27
+
28
+ @Override
29
+ public RepeatablePartImpl instantiateInstance(SerializationStreamReader streamReader)
30
+ throws SerializationException {
31
+ return instantiate(streamReader);
32
+ }
33
+
34
+ public static RepeatablePartImpl instantiate(SerializationStreamReader streamReader)
35
+ throws SerializationException {
36
+ return new RepeatablePartImpl(streamReader.readInt(), streamReader.readInt());
37
+ }
38
+
39
+ @Override
40
+ public void deserializeInstance(SerializationStreamReader streamReader, RepeatablePartImpl instance)
41
+ throws SerializationException {
42
+ deserialize(streamReader, instance);
43
+ }
44
+
45
+ public static void deserialize(SerializationStreamReader streamReader, RepeatablePartImpl instance) {
46
+ // Done by instantiateInstance
47
+ }
48
+
49
+}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventListComposite.java
... ...
@@ -229,7 +229,7 @@ public class EventListComposite extends Composite {
229 229
public int hashCode(EventDTO t) {
230 230
return t.id.hashCode();
231 231
}
232
- },filterTextbox.getAllListDataProvider(),table);
232
+ }, filterTextbox.getAllListDataProvider(),table);
233 233
AnchorCell anchorCell = new AnchorCell();
234 234
ListHandler<EventDTO> listHandler = new ListHandler<EventDTO>(eventListDataProvider.getList());
235 235
final TextColumn<EventDTO> eventUUidColumn = new AbstractSortableTextColumn<EventDTO>(
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogAddDeviceMappingDialog.java
... ...
@@ -96,7 +96,7 @@ public class RegattaLogAddDeviceMappingDialog extends DataEntryDialogWithDateTim
96 96
from.setValue(null);
97 97
to = createDateTimeBox(new Date(), Accuracy.SECONDS);
98 98
to.setValue(null);
99
-
99
+ // device ID list box:
100 100
deviceType = createListBox(false);
101 101
sailingServiceWrite.getDeserializableDeviceIdentifierTypes(new AsyncCallback<List<String>>() {
102 102
@Override
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogTrackingDeviceMappingsDialog.java
... ...
@@ -305,7 +305,6 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog<Void
305 305
306 306
private void showAddMappingDialog(DeviceMappingDTO mapping) {
307 307
sailingServiceWrite.getMailType(new AsyncCallback<MailInvitationType>() {
308
-
309 308
@Override
310 309
public void onFailure(Throwable caught) {
311 310
errorReporter.reportError(caught.getMessage());
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/CourseConfigurationEditDialog.java
... ...
@@ -0,0 +1,87 @@
1
+package com.sap.sailing.gwt.ui.adminconsole.coursecreation;
2
+
3
+import java.util.List;
4
+
5
+import com.google.gwt.user.client.ui.Grid;
6
+import com.google.gwt.user.client.ui.Widget;
7
+import com.sap.sailing.domain.common.Position;
8
+import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
9
+import com.sap.sailing.gwt.ui.client.StringMessages;
10
+import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO;
11
+import com.sap.sailing.gwt.ui.shared.courseCreation.CourseConfigurationDTO;
12
+import com.sap.sailing.gwt.ui.shared.courseCreation.CourseTemplateDTO;
13
+import com.sap.sailing.gwt.ui.shared.courseCreation.MarkRoleDTO;
14
+import com.sap.sailing.gwt.ui.shared.courseCreation.MarkTemplateDTO;
15
+import com.sap.sse.gwt.client.dialog.DataEntryDialog;
16
+
17
+/**
18
+ * A dialog that lets the user edit a {@link CourseConfigurationDTO}. It may be initialized from a server-side
19
+ * {@code CourseConfiguration} which may in turn have been initialized from a {@code Regatta}'s course, or from a
20
+ * {@code CourseTemplate}. At any time the user can select a course template from the library and set up a course with
21
+ * the {@code MarkProperties} from the library, or generate new {@code Mark}s from the {@code MarkTemplate}s coming with
22
+ * the {@code CourseTemplate}. All marks placed in the course configuration may be selected for storing in the
23
+ * "inventory" as {@code MarkProperties} objects for future use.
24
+ * <p>
25
+ *
26
+ * If the user edits the course configuration in a way incompatible with a previously selected course template,
27
+ * the course template selection is reset so that the user can know that the course is no longer governed by the
28
+ * template.<p>
29
+ *
30
+ * As long as the course configuration is "in sync" with a selected course template, the mark roles of which the
31
+ * course consists will be displayed for each mark configuration. When the course configuration runs "out of sync"
32
+ * with the course template, the mark role labels disappear.<p>
33
+ *
34
+ * Existing and new regatta marks can be assigned to the mark roles and to additional (spare) mark templates. Missing
35
+ * marks for mark roles will be initialized from the mark templates assigned to the respective mark role and will lead
36
+ * to the respective regatta marks to be created. Optionally, the user may select the spare mark templates from which
37
+ * regatta marks shall be created or to which existing regatta marks shall be associated.<p>
38
+ *
39
+ * When offering the user the possible assignments to a mark role, the marks linked to the mark templates which in turn
40
+ * act as spares for the mark role to be assigned will be shown at the top of the list.<p>
41
+ *
42
+ * Warnings may be emitted in case a mark configuration is used in multiple places where the course template does not
43
+ * use the same mark template for those. This suggests the user accidentally used the same mark at incorrect places.<p>
44
+ *
45
+ * Positioning information for marks may be provided, either as one or more {@link DeviceMappingDTO} objects (TODO show
46
+ * a QR code that allows a user to bind a device; the binding would, once complete, have to be read from the server to
47
+ * be shown in the UI again) and/or a fixed {@link Position} (TODO let the user pick on a map) indicating the last known
48
+ * position or the position to set for, e.g., a fixed land mark. Other request/response attributes may also be
49
+ * visualized and edited, such as whether a mark configuration shall be stored as {@code MarkProperties} in the user's
50
+ * "inventory" or a {@code MarkRole} with name and short name shall be created in a new {@code CourseTemplate} for the
51
+ * mark defined in the course.
52
+ * <p>
53
+ *
54
+ * @author Axel Uhl (d043530)
55
+ *
56
+ */
57
+public class CourseConfigurationEditDialog extends DataEntryDialog<CourseConfigurationDTO> {
58
+ private static class Validator implements DataEntryDialog.Validator<CourseConfigurationDTO> {
59
+ @Override
60
+ public String getErrorMessage(CourseConfigurationDTO valueToValidate) {
61
+ // TODO Auto-generated method stub
62
+ return null;
63
+ }
64
+ }
65
+
66
+ public CourseConfigurationEditDialog(final SailingServiceAsync sailingService, final StringMessages stringMessages,
67
+ CourseConfigurationDTO courseConfigurationToEdit, List<CourseTemplateDTO> allCourseTemplates,
68
+ List<MarkRoleDTO> allMarkRoles, List<MarkTemplateDTO> allMarkTemplates,
69
+ DialogCallback<CourseConfigurationDTO> callback) {
70
+ super(stringMessages.configureCourse(), stringMessages.configureCourse(), stringMessages.ok(), stringMessages.cancel(),
71
+ new Validator(), callback);
72
+ }
73
+
74
+ @Override
75
+ protected Widget getAdditionalWidget() {
76
+ final Grid grid = new Grid(1, 2);
77
+
78
+ // TODO Auto-generated method stub
79
+ return grid;
80
+ }
81
+
82
+ @Override
83
+ protected CourseConfigurationDTO getResult() {
84
+ // TODO Auto-generated method stub
85
+ return null;
86
+ }
87
+}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/CourseTemplateEditDialog.java
... ...
@@ -48,7 +48,6 @@ import com.sap.sse.gwt.client.celltable.ImagesBarColumn;
48 48
import com.sap.sse.gwt.client.controls.IntegerBox;
49 49
import com.sap.sse.gwt.client.controls.listedit.StringListEditorComposite;
50 50
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
51
-import com.sap.sse.security.ui.client.UserService;
52 51
import com.sap.sse.security.ui.client.component.DefaultActionsImagesBarCell;
53 52
54 53
public class CourseTemplateEditDialog extends DataEntryDialog<CourseTemplateDTO> {
... ...
@@ -92,10 +91,10 @@ public class CourseTemplateEditDialog extends DataEntryDialog<CourseTemplateDTO>
92 91
private static final RegExp urlRegExp = RegExp
93 92
.compile("^((ftp|http|https)://[\\w@.\\-\\_]+(:\\d{1,5})?(/[\\w#!:.?+=&%@!\\_\\-/]+)*){1}$");
94 93
95
- public CourseTemplateEditDialog(final SailingServiceAsync sailingService, final UserService userService,
96
- final StringMessages stringMessages, CourseTemplateDTO courseTemplateToEdit,
97
- List<MarkRoleDTO> allMarkRoles, List<MarkTemplateDTO> allMarkTemplates,
98
- DialogCallback<CourseTemplateDTO> callback, final boolean isNew) {
94
+ public CourseTemplateEditDialog(final SailingServiceAsync sailingService, final StringMessages stringMessages,
95
+ CourseTemplateDTO courseTemplateToEdit, List<MarkRoleDTO> allMarkRoles,
96
+ List<MarkTemplateDTO> allMarkTemplates, DialogCallback<CourseTemplateDTO> callback,
97
+ final boolean isNew) {
99 98
super(stringMessages.edit() + " " + stringMessages.courseTemplates(), null, stringMessages.ok(),
100 99
stringMessages.cancel(), new Validator<CourseTemplateDTO>() {
101 100
@Override
... ...
@@ -173,7 +172,7 @@ public class CourseTemplateEditDialog extends DataEntryDialog<CourseTemplateDTO>
173 172
this.allMarkRolesSelectionListPlusEmptyString = new LinkedList<>(allMarkRoles.stream().map(MarkRoleDTO::getName).collect(Collectors.toList()));
174 173
allMarkRolesSelectionListPlusEmptyString.add(0, ""); // prepend the empty selection
175 174
this.markTemplatesForMarkRoles = new ArrayList<>();
176
- markTemplatesForMarkRolesTable = createMarkTemplateAndMarkRoleTable(/* readOnly */ !isNew, markTemplatesForMarkRoles, userService);
175
+ markTemplatesForMarkRolesTable = createMarkTemplateAndMarkRoleTable(/* readOnly */ !isNew, markTemplatesForMarkRoles);
177 176
buttonAddMarkRoleToMarkTemplateMapping = new Button(stringMessages.add());
178 177
buttonAddMarkRoleToMarkTemplateMapping.addClickHandler(c -> {
179 178
markTemplatesForMarkRoles.add(new MarkTemplateDTOAndMarkRoleDTO(allMarkTemplates.stream().findFirst().orElse(null),
... ...
@@ -182,7 +181,7 @@ public class CourseTemplateEditDialog extends DataEntryDialog<CourseTemplateDTO>
182 181
validateAndUpdate();
183 182
});
184 183
this.spareMarkTemplatesAndTheirDefaultMarkRoles = new ArrayList<>();
185
- spareMarkTemplatesAndTheirDefaultMarkRolesTable = createMarkTemplateAndMarkRoleTable(/* readOnly */ !isNew, spareMarkTemplatesAndTheirDefaultMarkRoles, userService);
184
+ spareMarkTemplatesAndTheirDefaultMarkRolesTable = createMarkTemplateAndMarkRoleTable(/* readOnly */ !isNew, spareMarkTemplatesAndTheirDefaultMarkRoles);
186 185
buttonAddMarkRoleToMarkTemplateMapping.setEnabled(isNew);
187 186
buttonAddSpareMarkTemplate = new Button(stringMessages.add());
188 187
buttonAddSpareMarkTemplate.addClickHandler(c -> {
... ...
@@ -226,7 +225,7 @@ public class CourseTemplateEditDialog extends DataEntryDialog<CourseTemplateDTO>
226 225
}
227 226
228 227
private CellTable<MarkTemplateDTOAndMarkRoleDTO> createMarkTemplateAndMarkRoleTable(final boolean readOnly,
229
- final List<MarkTemplateDTOAndMarkRoleDTO> markTemplatesAndMarkRoles, final UserService userService) {
228
+ final List<MarkTemplateDTOAndMarkRoleDTO> markTemplatesAndMarkRoles) {
230 229
final CellTable<MarkTemplateDTOAndMarkRoleDTO> table = new BaseCelltable<>(1000, tableResources);
231 230
table.setWidth("100%");
232 231
final SelectionCell markTemplateSelectionCell = new SelectionCell(allMarkTemplatesSelectionListPlusEmptyString);
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/CourseTemplatePanel.java
... ...
@@ -18,21 +18,15 @@ import java.util.stream.Collectors;
18 18
19 19
import com.google.gwt.cell.client.TextCell;
20 20
import com.google.gwt.core.client.GWT;
21
-import com.google.gwt.dom.client.BrowserEvents;
22
-import com.google.gwt.dom.client.NativeEvent;
23 21
import com.google.gwt.dom.client.Style.Unit;
24 22
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
25 23
import com.google.gwt.user.cellview.client.AbstractCellTable;
26
-import com.google.gwt.user.cellview.client.CellTable;
27 24
import com.google.gwt.user.cellview.client.Column;
28 25
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
29 26
import com.google.gwt.user.client.Window;
30 27
import com.google.gwt.user.client.rpc.AsyncCallback;
31 28
import com.google.gwt.user.client.ui.FlowPanel;
32 29
import com.google.gwt.user.client.ui.Label;
33
-import com.google.gwt.view.client.CellPreviewEvent;
34
-import com.google.gwt.view.client.DefaultSelectionEventManager;
35
-import com.google.gwt.view.client.DefaultSelectionEventManager.SelectAction;
36 30
import com.google.gwt.view.client.ListDataProvider;
37 31
import com.sap.sailing.domain.common.security.SecuredDomainType;
38 32
import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync;
... ...
@@ -43,10 +37,10 @@ import com.sap.sailing.gwt.ui.shared.courseCreation.MarkTemplateDTO;
43 37
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
44 38
import com.sap.sse.gwt.adminconsole.FilterablePanelProvider;
45 39
import com.sap.sse.gwt.client.ErrorReporter;
46
-import com.sap.sse.gwt.client.celltable.BaseCelltable;
47 40
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
41
+import com.sap.sse.gwt.client.celltable.FlushableCellTable;
48 42
import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel;
49
-import com.sap.sse.gwt.client.controls.BetterCheckboxCell;
43
+import com.sap.sse.gwt.client.celltable.SelectionCheckboxColumn;
50 44
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
51 45
import com.sap.sse.gwt.client.panels.AbstractFilterablePanel;
52 46
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
... ...
@@ -68,7 +62,7 @@ public class CourseTemplatePanel extends FlowPanel implements FilterablePanelPro
68 62
private List<CourseTemplateDTO> allCourseTemplates;
69 63
private final ErrorReporter errorReporter;
70 64
private final StringMessages stringMessages;
71
- private CellTable<CourseTemplateDTO> courseTemplateTable;
65
+ private FlushableCellTable<CourseTemplateDTO> courseTemplateTable;
72 66
private ListDataProvider<CourseTemplateDTO> courseTemplateListDataProvider = new ListDataProvider<>();
73 67
private RefreshableMultiSelectionModel<CourseTemplateDTO> refreshableSelectionModel;
74 68
private List<MarkRoleDTO> allMarkRoles;
... ...
@@ -179,64 +173,14 @@ public class CourseTemplatePanel extends FlowPanel implements FilterablePanelPro
179 173
}
180 174
181 175
private void createCourseTemplateTable(final UserService userService) {
182
- // Create a CellTable.
183
-
184
- // Set a key provider that provides a unique key for each contact. If key is
185
- // used to identify contacts when fields (such as the name and address)
186
- // change.
187
- courseTemplateTable = new BaseCelltable<>(1000, tableResources);
176
+ courseTemplateTable = new FlushableCellTable<>(1000, tableResources);
188 177
courseTemplateTable.setWidth("100%");
189 178
190 179
// Attach a column sort handler to the ListDataProvider to sort the list.
191 180
ListHandler<CourseTemplateDTO> sortHandler = new ListHandler<>(courseTemplateListDataProvider.getList());
192 181
courseTemplateTable.addColumnSortHandler(sortHandler);
193
-
194
- // Add a selection model so we can select cells.
195
- refreshableSelectionModel = new RefreshableMultiSelectionModel<>(
196
- new EntityIdentityComparator<CourseTemplateDTO>() {
197
- @Override
198
- public boolean representSameEntity(CourseTemplateDTO dto1, CourseTemplateDTO dto2) {
199
- return dto1.getUuid().equals(dto2.getUuid());
200
- }
201
-
202
- @Override
203
- public int hashCode(CourseTemplateDTO t) {
204
- return t.getUuid().hashCode();
205
- }
206
- }, filterableCourseTemplatePanel.getAllListDataProvider());
207
- courseTemplateTable.setSelectionModel(refreshableSelectionModel, DefaultSelectionEventManager
208
- .createCustomManager(new DefaultSelectionEventManager.CheckboxEventTranslator<CourseTemplateDTO>() {
209
- @Override
210
- public boolean clearCurrentSelection(CellPreviewEvent<CourseTemplateDTO> event) {
211
- return !isCheckboxColumn(event.getColumn());
212
- }
213
-
214
- @Override
215
- public SelectAction translateSelectionEvent(CellPreviewEvent<CourseTemplateDTO> event) {
216
- NativeEvent nativeEvent = event.getNativeEvent();
217
- if (BrowserEvents.CLICK.equals(nativeEvent.getType())) {
218
- if (nativeEvent.getCtrlKey()) {
219
- CourseTemplateDTO value = event.getValue();
220
- refreshableSelectionModel.setSelected(value,
221
- !refreshableSelectionModel.isSelected(value));
222
- return SelectAction.IGNORE;
223
- }
224
- if (!refreshableSelectionModel.getSelectedSet().isEmpty()
225
- && !isCheckboxColumn(event.getColumn())) {
226
- return SelectAction.DEFAULT;
227
- }
228
- }
229
- return SelectAction.TOGGLE;
230
- }
231
-
232
- private boolean isCheckboxColumn(int columnIndex) {
233
- return columnIndex == 0;
234
- }
235
- }));
236
-
237 182
// Initialize the columns.
238 183
initTableColumns(sortHandler, userService);
239
-
240 184
courseTemplateListDataProvider.addDataDisplay(courseTemplateTable);
241 185
add(courseTemplateTable);
242 186
allCourseTemplates.clear();
... ...
@@ -247,18 +191,22 @@ public class CourseTemplatePanel extends FlowPanel implements FilterablePanelPro
247 191
* Add the columns to the table.
248 192
*/
249 193
private void initTableColumns(final ListHandler<CourseTemplateDTO> sortHandler, final UserService userService) {
250
- Column<CourseTemplateDTO, Boolean> checkColumn = new Column<CourseTemplateDTO, Boolean>(
251
- new BetterCheckboxCell(tableResources.cellTableStyle().cellTableCheckboxSelected(),
252
- tableResources.cellTableStyle().cellTableCheckboxDeselected())) {
253
- @Override
254
- public Boolean getValue(CourseTemplateDTO object) {
255
- // Get the value from the selection model.
256
- return refreshableSelectionModel.isSelected(object);
257
- }
258
- };
194
+ final SelectionCheckboxColumn<CourseTemplateDTO> checkColumn = new SelectionCheckboxColumn<CourseTemplateDTO>(
195
+ tableResources.cellTableStyle().cellTableCheckboxSelected(),
196
+ tableResources.cellTableStyle().cellTableCheckboxDeselected(),
197
+ tableResources.cellTableStyle().cellTableCheckboxColumnCell(), new EntityIdentityComparator<CourseTemplateDTO>() {
198
+ @Override
199
+ public boolean representSameEntity(CourseTemplateDTO dto1, CourseTemplateDTO dto2) {
200
+ return dto1.getUuid().equals(dto2.getUuid());
201
+ }
202
+ @Override
203
+ public int hashCode(CourseTemplateDTO t) {
204
+ return t.getUuid().hashCode();
205
+ }
206
+ }, filterableCourseTemplatePanel.getAllListDataProvider(), courseTemplateTable);
207
+
259 208
courseTemplateTable.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>"));
260 209
courseTemplateTable.setColumnWidth(checkColumn, 40, Unit.PX);
261
-
262 210
// id
263 211
Column<CourseTemplateDTO, String> idColumn = new Column<CourseTemplateDTO, String>(new TextCell()) {
264 212
@Override
... ...
@@ -336,6 +284,8 @@ public class CourseTemplatePanel extends FlowPanel implements FilterablePanelPro
336 284
courseTemplate -> configACL.openDialog(courseTemplate));
337 285
courseTemplateTable.addColumn(idColumn, stringMessages.id());
338 286
courseTemplateTable.addColumn(actionsColumn, stringMessages.actions());
287
+ refreshableSelectionModel = checkColumn.getSelectionModel();
288
+ courseTemplateTable.setSelectionModel(refreshableSelectionModel, checkColumn.getSelectionManager());
339 289
}
340 290
341 291
public void refreshCourseTemplates() {
... ...
@@ -346,9 +296,8 @@ public class CourseTemplatePanel extends FlowPanel implements FilterablePanelPro
346 296
347 297
void openEditCourseTemplateDialog(final CourseTemplateDTO originalCourseTemplate, final UserService userService,
348 298
final boolean isNew) {
349
- final CourseTemplateEditDialog dialog = new CourseTemplateEditDialog(sailingService, userService,
350
- stringMessages, originalCourseTemplate, allMarkRoles, allMarkTemplates,
351
- new DialogCallback<CourseTemplateDTO>() {
299
+ final CourseTemplateEditDialog dialog = new CourseTemplateEditDialog(sailingService, stringMessages,
300
+ originalCourseTemplate, allMarkRoles, allMarkTemplates, new DialogCallback<CourseTemplateDTO>() {
352 301
@Override
353 302
public void ok(CourseTemplateDTO courseTemplate) {
354 303
sailingService.createOrUpdateCourseTemplate(courseTemplate,
... ...
@@ -383,7 +332,8 @@ public class CourseTemplatePanel extends FlowPanel implements FilterablePanelPro
383 332
@Override
384 333
public void cancel() {
385 334
}
386
- }, isNew);
335
+ },
336
+ isNew);
387 337
dialog.ensureDebugId("CourseTemplateEditDialog");
388 338
dialog.show();
389 339
}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkPropertiesPanel.java
... ...
@@ -20,13 +20,10 @@ import java.util.stream.Collectors;
20 20
import com.google.gwt.cell.client.AbstractCell;
21 21
import com.google.gwt.cell.client.TextCell;
22 22
import com.google.gwt.core.client.GWT;
23
-import com.google.gwt.dom.client.BrowserEvents;
24
-import com.google.gwt.dom.client.NativeEvent;
25 23
import com.google.gwt.dom.client.Style.Unit;
26 24
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
27 25
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
28 26
import com.google.gwt.user.cellview.client.AbstractCellTable;
29
-import com.google.gwt.user.cellview.client.CellTable;
30 27
import com.google.gwt.user.cellview.client.Column;
31 28
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
32 29
import com.google.gwt.user.client.Window;
... ...
@@ -34,9 +31,6 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
34 31
import com.google.gwt.user.client.ui.AbstractImagePrototype;
35 32
import com.google.gwt.user.client.ui.FlowPanel;
36 33
import com.google.gwt.user.client.ui.Label;
37
-import com.google.gwt.view.client.CellPreviewEvent;
38
-import com.google.gwt.view.client.DefaultSelectionEventManager;
39
-import com.google.gwt.view.client.DefaultSelectionEventManager.SelectAction;
40 34
import com.google.gwt.view.client.ListDataProvider;
41 35
import com.sap.sailing.domain.common.Position;
42 36
import com.sap.sailing.domain.common.security.SecuredDomainType;
... ...
@@ -49,10 +43,10 @@ import com.sap.sse.common.Util;
49 43
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
50 44
import com.sap.sse.gwt.adminconsole.FilterablePanelProvider;
51 45
import com.sap.sse.gwt.client.ErrorReporter;
52
-import com.sap.sse.gwt.client.celltable.BaseCelltable;
53 46
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
47
+import com.sap.sse.gwt.client.celltable.FlushableCellTable;
54 48
import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel;
55
-import com.sap.sse.gwt.client.controls.BetterCheckboxCell;
49
+import com.sap.sse.gwt.client.celltable.SelectionCheckboxColumn;
56 50
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
57 51
import com.sap.sse.gwt.client.panels.AbstractFilterablePanel;
58 52
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
... ...
@@ -79,7 +73,7 @@ public class MarkPropertiesPanel extends FlowPanel implements FilterablePanelPro
79 73
private List<MarkPropertiesDTO> allMarkProperties;
80 74
private final ErrorReporter errorReporter;
81 75
private final StringMessages stringMessages;
82
- private CellTable<MarkPropertiesDTO> markPropertiesTable;
76
+ private FlushableCellTable<MarkPropertiesDTO> markPropertiesTable;
83 77
private ListDataProvider<MarkPropertiesDTO> markPropertiesListDataProvider = new ListDataProvider<>();
84 78
private RefreshableMultiSelectionModel<MarkPropertiesDTO> refreshableSelectionModel;
85 79
... ...
@@ -160,58 +154,11 @@ public class MarkPropertiesPanel extends FlowPanel implements FilterablePanelPro
160 154
}
161 155
162 156
private void createMarkPropertiesTable(final UserService userService) {
163
- // Create a CellTable.
164
- // Set a key provider that provides a unique key for each contact. If key is
165
- // used to identify contacts when fields (such as the name and address)
166
- // change.
167
- markPropertiesTable = new BaseCelltable<>(1000, tableResources);
157
+ markPropertiesTable = new FlushableCellTable<>(1000, tableResources);
168 158
markPropertiesTable.setWidth("100%");
169 159
// Attach a column sort handler to the ListDataProvider to sort the list.
170 160
ListHandler<MarkPropertiesDTO> sortHandler = new ListHandler<>(markPropertiesListDataProvider.getList());
171 161
markPropertiesTable.addColumnSortHandler(sortHandler);
172
- // Add a selection model so we can select cells.
173
- refreshableSelectionModel = new RefreshableMultiSelectionModel<>(
174
- new EntityIdentityComparator<MarkPropertiesDTO>() {
175
- @Override
176
- public boolean representSameEntity(MarkPropertiesDTO dto1, MarkPropertiesDTO dto2) {
177
- return dto1.getUuid().equals(dto2.getUuid());
178
- }
179
-
180
- @Override
181
- public int hashCode(MarkPropertiesDTO t) {
182
- return t.getUuid().hashCode();
183
- }
184
- }, filterableMarkProperties.getAllListDataProvider());
185
- markPropertiesTable.setSelectionModel(refreshableSelectionModel, DefaultSelectionEventManager
186
- .createCustomManager(new DefaultSelectionEventManager.CheckboxEventTranslator<MarkPropertiesDTO>() {
187
- @Override
188
- public boolean clearCurrentSelection(CellPreviewEvent<MarkPropertiesDTO> event) {
189
- return !isCheckboxColumn(event.getColumn());
190
- }
191
-
192
- @Override
193
- public SelectAction translateSelectionEvent(CellPreviewEvent<MarkPropertiesDTO> event) {
194
- NativeEvent nativeEvent = event.getNativeEvent();
195
- if (BrowserEvents.CLICK.equals(nativeEvent.getType())) {
196
- if (nativeEvent.getCtrlKey()) {
197
- MarkPropertiesDTO value = event.getValue();
198
- refreshableSelectionModel.setSelected(value,
199
- !refreshableSelectionModel.isSelected(value));
200
- return SelectAction.IGNORE;
201
- }
202
- if (!refreshableSelectionModel.getSelectedSet().isEmpty()
203
- && !isCheckboxColumn(event.getColumn())) {
204
- return SelectAction.DEFAULT;
205
- }
206
- }
207
- return SelectAction.TOGGLE;
208
- }
209
-
210
- private boolean isCheckboxColumn(int columnIndex) {
211
- return columnIndex == 0;
212
- }
213
- }));
214
-
215 162
// Initialize the columns.
216 163
initTableColumns(sortHandler, userService);
217 164
markPropertiesListDataProvider.addDataDisplay(markPropertiesTable);
... ...
@@ -224,18 +171,21 @@ public class MarkPropertiesPanel extends FlowPanel implements FilterablePanelPro
224 171
* Add the columns to the table.
225 172
*/
226 173
private void initTableColumns(final ListHandler<MarkPropertiesDTO> sortHandler, final UserService userService) {
227
- Column<MarkPropertiesDTO, Boolean> checkColumn = new Column<MarkPropertiesDTO, Boolean>(
228
- new BetterCheckboxCell(tableResources.cellTableStyle().cellTableCheckboxSelected(),
229
- tableResources.cellTableStyle().cellTableCheckboxDeselected())) {
230
- @Override
231
- public Boolean getValue(MarkPropertiesDTO object) {
232
- // Get the value from the selection model.
233
- return refreshableSelectionModel.isSelected(object);
234
- }
235
- };
174
+ final SelectionCheckboxColumn<MarkPropertiesDTO> checkColumn = new SelectionCheckboxColumn<MarkPropertiesDTO>(
175
+ tableResources.cellTableStyle().cellTableCheckboxSelected(),
176
+ tableResources.cellTableStyle().cellTableCheckboxDeselected(),
177
+ tableResources.cellTableStyle().cellTableCheckboxColumnCell(), new EntityIdentityComparator<MarkPropertiesDTO>() {
178
+ @Override
179
+ public boolean representSameEntity(MarkPropertiesDTO dto1, MarkPropertiesDTO dto2) {
180
+ return dto1.getUuid().equals(dto2.getUuid());
181
+ }
182
+ @Override
183
+ public int hashCode(MarkPropertiesDTO t) {
184
+ return t.getUuid().hashCode();
185
+ }
186
+ }, filterableMarkProperties.getAllListDataProvider(), markPropertiesTable);
236 187
markPropertiesTable.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>"));
237 188
markPropertiesTable.setColumnWidth(checkColumn, 40, Unit.PX);
238
-
239 189
// id
240 190
Column<MarkPropertiesDTO, String> idColumn = new Column<MarkPropertiesDTO, String>(new TextCell()) {
241 191
@Override
... ...
@@ -298,7 +248,6 @@ public class MarkPropertiesPanel extends FlowPanel implements FilterablePanelPro
298 248
};
299 249
Column<MarkPropertiesDTO, AbstractImagePrototype> positioningColumn = new Column<MarkPropertiesDTO, AbstractImagePrototype>(
300 250
new AbstractCell<AbstractImagePrototype>() {
301
-
302 251
@Override
303 252
public void render(Context context, AbstractImagePrototype image, SafeHtmlBuilder sb) {
304 253
if (image != null) sb.append(image.getSafeHtml());
... ...
@@ -356,17 +305,19 @@ public class MarkPropertiesPanel extends FlowPanel implements FilterablePanelPro
356 305
}
357 306
});
358 307
actionsColumn.addAction(ACTION_UPDATE, UPDATE, this::openEditMarkPropertiesDialog);
359
- actionsColumn.addAction(MarkPropertiesImagesbarCell.ACTION_SET_DEVICE_IDENTIFIER,
308
+ actionsColumn.addAction(MarkPropertiesImagesbarCell.ACTION_SET_DEVICE_IDENTIFIER, UPDATE,
360 309
this::openEditMarkPropertiesDeviceIdentifierDialog);
361
- actionsColumn.addAction(MarkPropertiesImagesbarCell.ACTION_SET_POSITION,
310
+ actionsColumn.addAction(MarkPropertiesImagesbarCell.ACTION_SET_POSITION, UPDATE,
362 311
this::openEditMarkPropertiesPositionDialog);
363
- actionsColumn.addAction(MarkPropertiesImagesbarCell.ACTION_UNSET_POSITION,
312
+ actionsColumn.addAction(MarkPropertiesImagesbarCell.ACTION_UNSET_POSITION, UPDATE,
364 313
this::unsetPosition);
365 314
actionsColumn.addAction(ACTION_CHANGE_OWNERSHIP, CHANGE_OWNERSHIP, configOwnership::openOwnershipDialog);
366 315
actionsColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_ACL, DefaultActions.CHANGE_ACL,
367 316
markProperties -> configACL.openDialog(markProperties));
368 317
markPropertiesTable.addColumn(idColumn, stringMessages.id());
369 318
markPropertiesTable.addColumn(actionsColumn, stringMessages.actions());
319
+ refreshableSelectionModel = checkColumn.getSelectionModel();
320
+ markPropertiesTable.setSelectionModel(checkColumn.getSelectionModel(), checkColumn.getSelectionManager());
370 321
}
371 322
372 323
public void refreshMarkProperties() {
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkRolePanel.java
... ...
@@ -15,7 +15,6 @@ import com.google.gwt.dom.client.NativeEvent;
15 15
import com.google.gwt.dom.client.Style.Unit;
16 16
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
17 17
import com.google.gwt.user.cellview.client.AbstractCellTable;
18
-import com.google.gwt.user.cellview.client.CellTable;
19 18
import com.google.gwt.user.cellview.client.Column;
20 19
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
21 20
import com.google.gwt.user.client.Command;
... ...
@@ -34,10 +33,10 @@ import com.sap.sse.common.Util;
34 33
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
35 34
import com.sap.sse.gwt.adminconsole.FilterablePanelProvider;
36 35
import com.sap.sse.gwt.client.ErrorReporter;
37
-import com.sap.sse.gwt.client.celltable.BaseCelltable;
38 36
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
37
+import com.sap.sse.gwt.client.celltable.FlushableCellTable;
39 38
import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel;
40
-import com.sap.sse.gwt.client.controls.BetterCheckboxCell;
39
+import com.sap.sse.gwt.client.celltable.SelectionCheckboxColumn;
41 40
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
42 41
import com.sap.sse.gwt.client.panels.AbstractFilterablePanel;
43 42
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
... ...
@@ -59,7 +58,7 @@ public class MarkRolePanel extends FlowPanel implements FilterablePanelProvider<
59 58
private final ListDataProvider<MarkRoleDTO> markRoleListDataProvider = new ListDataProvider<>();
60 59
private final LabeledAbstractFilterablePanel<MarkRoleDTO> filterableMarkRoles;
61 60
private List<MarkRoleDTO> allMarkRoles;
62
- private CellTable<MarkRoleDTO> markRolesTable;
61
+ private FlushableCellTable<MarkRoleDTO> markRolesTable;
63 62
private RefreshableMultiSelectionModel<MarkRoleDTO> refreshableSelectionModel;
64 63
65 64
public MarkRolePanel(SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, StringMessages stringMessages,
... ...
@@ -134,23 +133,10 @@ public class MarkRolePanel extends FlowPanel implements FilterablePanelProvider<
134 133
}
135 134
136 135
private void createMarkRoleTable(final UserService userService) {
137
- markRolesTable = new BaseCelltable<>(1000, tableResources);
138
-
136
+ markRolesTable = new FlushableCellTable<>(1000, tableResources);
139 137
markRolesTable.setWidth("100%");
140 138
ListHandler<MarkRoleDTO> sortHandler = new ListHandler<>(markRoleListDataProvider.getList());
141 139
markRolesTable.addColumnSortHandler(sortHandler);
142
-
143
- refreshableSelectionModel = new RefreshableMultiSelectionModel<>(new EntityIdentityComparator<MarkRoleDTO>() {
144
- @Override
145
- public boolean representSameEntity(MarkRoleDTO dto1, MarkRoleDTO dto2) {
146
- return dto1.getUuid().equals(dto2.getUuid());
147
- }
148
-
149
- @Override
150
- public int hashCode(MarkRoleDTO t) {
151
- return t.getUuid().hashCode();
152
- }
153
- }, filterableMarkRoles.getAllListDataProvider());
154 140
markRolesTable.setSelectionModel(refreshableSelectionModel, DefaultSelectionEventManager
155 141
.createCustomManager(new DefaultSelectionEventManager.CheckboxEventTranslator<MarkRoleDTO>() {
156 142
@Override
... ...
@@ -182,7 +168,6 @@ public class MarkRolePanel extends FlowPanel implements FilterablePanelProvider<
182 168
}));
183 169
184 170
initTableColumns(sortHandler, userService);
185
-
186 171
markRoleListDataProvider.addDataDisplay(markRolesTable);
187 172
add(markRolesTable);
188 173
allMarkRoles.clear();
... ...
@@ -190,15 +175,19 @@ public class MarkRolePanel extends FlowPanel implements FilterablePanelProvider<
190 175
}
191 176
192 177
private void initTableColumns(final ListHandler<MarkRoleDTO> sortHandler, final UserService userService) {
193
- Column<MarkRoleDTO, Boolean> checkColumn = new Column<MarkRoleDTO, Boolean>(
194
- new BetterCheckboxCell(tableResources.cellTableStyle().cellTableCheckboxSelected(),
195
- tableResources.cellTableStyle().cellTableCheckboxDeselected())) {
196
- @Override
197
- public Boolean getValue(MarkRoleDTO object) {
198
- // Get the value from the selection model.
199
- return refreshableSelectionModel.isSelected(object);
200
- }
201
- };
178
+ final SelectionCheckboxColumn<MarkRoleDTO> checkColumn = new SelectionCheckboxColumn<MarkRoleDTO>(
179
+ tableResources.cellTableStyle().cellTableCheckboxSelected(),
180
+ tableResources.cellTableStyle().cellTableCheckboxDeselected(),
181
+ tableResources.cellTableStyle().cellTableCheckboxColumnCell(), new EntityIdentityComparator<MarkRoleDTO>() {
182
+ @Override
183
+ public boolean representSameEntity(MarkRoleDTO dto1, MarkRoleDTO dto2) {
184
+ return dto1.getUuid().equals(dto2.getUuid());
185
+ }
186
+ @Override
187
+ public int hashCode(MarkRoleDTO t) {
188
+ return t.getUuid().hashCode();
189
+ }
190
+ }, filterableMarkRoles.getAllListDataProvider(), markRolesTable);
202 191
markRolesTable.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>"));
203 192
markRolesTable.setColumnWidth(checkColumn, 40, Unit.PX);
204 193
// id
... ...
@@ -249,6 +238,8 @@ public class MarkRolePanel extends FlowPanel implements FilterablePanelProvider<
249 238
markRole -> configACL.openDialog(markRole));
250 239
markRolesTable.addColumn(idColumn, stringMessages.id());
251 240
markRolesTable.addColumn(actionsColumn, stringMessages.actions());
241
+ refreshableSelectionModel = checkColumn.getSelectionModel();
242
+ markRolesTable.setSelectionModel(refreshableSelectionModel, checkColumn.getSelectionManager());
252 243
}
253 244
254 245
private void openEditMarkRoleDialog(final MarkRoleDTO originalMarkRole) {
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkTemplatePanel.java
... ...
@@ -10,21 +10,15 @@ import java.util.List;
10 10
11 11
import com.google.gwt.cell.client.TextCell;
12 12
import com.google.gwt.core.client.GWT;
13
-import com.google.gwt.dom.client.BrowserEvents;
14
-import com.google.gwt.dom.client.NativeEvent;
15 13
import com.google.gwt.dom.client.Style.Unit;
16 14
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
17 15
import com.google.gwt.user.cellview.client.AbstractCellTable;
18
-import com.google.gwt.user.cellview.client.CellTable;
19 16
import com.google.gwt.user.cellview.client.Column;
20 17
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
21 18
import com.google.gwt.user.client.Command;
22 19
import com.google.gwt.user.client.rpc.AsyncCallback;
23 20
import com.google.gwt.user.client.ui.FlowPanel;
24 21
import com.google.gwt.user.client.ui.Label;
25
-import com.google.gwt.view.client.CellPreviewEvent;
26
-import com.google.gwt.view.client.DefaultSelectionEventManager;
27
-import com.google.gwt.view.client.DefaultSelectionEventManager.SelectAction;
28 22
import com.google.gwt.view.client.ListDataProvider;
29 23
import com.sap.sailing.domain.common.security.SecuredDomainType;
30 24
import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync;
... ...
@@ -34,10 +28,10 @@ import com.sap.sse.common.Util;
34 28
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
35 29
import com.sap.sse.gwt.adminconsole.FilterablePanelProvider;
36 30
import com.sap.sse.gwt.client.ErrorReporter;
37
-import com.sap.sse.gwt.client.celltable.BaseCelltable;
38 31
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
32
+import com.sap.sse.gwt.client.celltable.FlushableCellTable;
39 33
import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel;
40
-import com.sap.sse.gwt.client.controls.BetterCheckboxCell;
34
+import com.sap.sse.gwt.client.celltable.SelectionCheckboxColumn;
41 35
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
42 36
import com.sap.sse.gwt.client.panels.AbstractFilterablePanel;
43 37
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
... ...
@@ -59,7 +53,7 @@ public class MarkTemplatePanel extends FlowPanel implements FilterablePanelProvi
59 53
private List<MarkTemplateDTO> allMarkTemplates;
60 54
private final ErrorReporter errorReporter;
61 55
private final StringMessages stringMessages;
62
- private CellTable<MarkTemplateDTO> markTemplateTable;
56
+ private FlushableCellTable<MarkTemplateDTO> markTemplateTable;
63 57
private ListDataProvider<MarkTemplateDTO> markTemplateListDataProvider = new ListDataProvider<>();
64 58
private RefreshableMultiSelectionModel<MarkTemplateDTO> refreshableSelectionModel;
65 59
... ...
@@ -129,58 +123,11 @@ public class MarkTemplatePanel extends FlowPanel implements FilterablePanelProvi
129 123
}
130 124
131 125
private void createMarkTemplatesTable(final UserService userService) {
132
- // Create a CellTable.
133
- // Set a key provider that provides a unique key for each contact. If key is
134
- // used to identify contacts when fields (such as the name and address)
135
- // change.
136
- markTemplateTable = new BaseCelltable<>(1000, tableResources);
126
+ markTemplateTable = new FlushableCellTable<>(1000, tableResources);
137 127
markTemplateTable.setWidth("100%");
138 128
// Attach a column sort handler to the ListDataProvider to sort the list.
139 129
ListHandler<MarkTemplateDTO> sortHandler = new ListHandler<>(markTemplateListDataProvider.getList());
140 130
markTemplateTable.addColumnSortHandler(sortHandler);
141
- // Add a selection model so we can select cells.
142
- refreshableSelectionModel = new RefreshableMultiSelectionModel<>(
143
- new EntityIdentityComparator<MarkTemplateDTO>() {
144
- @Override
145
- public boolean representSameEntity(MarkTemplateDTO dto1, MarkTemplateDTO dto2) {
146
- return dto1.getUuid().equals(dto2.getUuid());
147
- }
148
-
149
- @Override
150
- public int hashCode(MarkTemplateDTO t) {
151
- return t.getUuid().hashCode();
152
- }
153
- }, filterableMarkTemplates.getAllListDataProvider());
154
- markTemplateTable.setSelectionModel(refreshableSelectionModel, DefaultSelectionEventManager
155
- .createCustomManager(new DefaultSelectionEventManager.CheckboxEventTranslator<MarkTemplateDTO>() {
156
- @Override
157
- public boolean clearCurrentSelection(CellPreviewEvent<MarkTemplateDTO> event) {
158
- return !isCheckboxColumn(event.getColumn());
159
- }
160
-
161
- @Override
162
- public SelectAction translateSelectionEvent(CellPreviewEvent<MarkTemplateDTO> event) {
163
- NativeEvent nativeEvent = event.getNativeEvent();
164
- if (BrowserEvents.CLICK.equals(nativeEvent.getType())) {
165
- if (nativeEvent.getCtrlKey()) {
166
- MarkTemplateDTO value = event.getValue();
167
- refreshableSelectionModel.setSelected(value,
168
- !refreshableSelectionModel.isSelected(value));
169
- return SelectAction.IGNORE;
170
- }
171
- if (!refreshableSelectionModel.getSelectedSet().isEmpty()
172
- && !isCheckboxColumn(event.getColumn())) {
173
- return SelectAction.DEFAULT;
174
- }
175
- }
176
- return SelectAction.TOGGLE;
177
- }
178
-
179
- private boolean isCheckboxColumn(int columnIndex) {
180
- return columnIndex == 0;
181
- }
182
- }));
183
-
184 131
// Initialize the columns.
185 132
initTableColumns(sortHandler, userService);
186 133
markTemplateListDataProvider.addDataDisplay(markTemplateTable);
... ...
@@ -193,15 +140,19 @@ public class MarkTemplatePanel extends FlowPanel implements FilterablePanelProvi
193 140
* Add the columns to the table.
194 141
*/
195 142
private void initTableColumns(final ListHandler<MarkTemplateDTO> sortHandler, final UserService userService) {
196
- Column<MarkTemplateDTO, Boolean> checkColumn = new Column<MarkTemplateDTO, Boolean>(
197
- new BetterCheckboxCell(tableResources.cellTableStyle().cellTableCheckboxSelected(),
198
- tableResources.cellTableStyle().cellTableCheckboxDeselected())) {
199
- @Override
200
- public Boolean getValue(MarkTemplateDTO object) {
201
- // Get the value from the selection model.
202
- return refreshableSelectionModel.isSelected(object);
203
- }
204
- };
143
+ final SelectionCheckboxColumn<MarkTemplateDTO> checkColumn = new SelectionCheckboxColumn<MarkTemplateDTO>(
144
+ tableResources.cellTableStyle().cellTableCheckboxSelected(),
145
+ tableResources.cellTableStyle().cellTableCheckboxDeselected(),
146
+ tableResources.cellTableStyle().cellTableCheckboxColumnCell(), new EntityIdentityComparator<MarkTemplateDTO>() {
147
+ @Override
148
+ public boolean representSameEntity(MarkTemplateDTO dto1, MarkTemplateDTO dto2) {
149
+ return dto1.getUuid().equals(dto2.getUuid());
150
+ }
151
+ @Override
152
+ public int hashCode(MarkTemplateDTO t) {
153
+ return t.getUuid().hashCode();
154
+ }
155
+ }, filterableMarkTemplates.getAllListDataProvider(), markTemplateTable);
205 156
markTemplateTable.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>"));
206 157
markTemplateTable.setColumnWidth(checkColumn, 40, Unit.PX);
207 158
// id
... ...
@@ -283,6 +234,8 @@ public class MarkTemplatePanel extends FlowPanel implements FilterablePanelProvi
283 234
markTemplate -> configACL.openDialog(markTemplate));
284 235
markTemplateTable.addColumn(idColumn, stringMessages.id());
285 236
markTemplateTable.addColumn(actionsColumn, stringMessages.actions());
237
+ refreshableSelectionModel = checkColumn.getSelectionModel();
238
+ markTemplateTable.setSelectionModel(refreshableSelectionModel, checkColumn.getSelectionManager());
286 239
}
287 240
288 241
public void refreshMarkTemplates() {
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkTemplateSuggestOracle.java
... ...
@@ -29,7 +29,7 @@ public class MarkTemplateSuggestOracle extends AbstractListSuggestOracle<MarkTem
29 29
refresh();
30 30
}
31 31
32
- public void refresh() {
32
+ private void refresh() {
33 33
sailingServiceAsync.getMarkTemplates(new AsyncCallback<List<MarkTemplateDTO>>() {
34 34
@Override
35 35
public void onFailure(Throwable caught) {
... ...
@@ -64,7 +64,6 @@ public class MarkTemplateSuggestOracle extends AbstractListSuggestOracle<MarkTem
64 64
if (this.getSelectableValues() == null) {
65 65
throw new NullPointerException("Mark Templates are not loaded yet or could not be loaded.");
66 66
}
67
-
68 67
for (MarkTemplateDTO template : this.getSelectableValues()) {
69 68
if (template.getName().equals(templateName)) {
70 69
return template;
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWrite.java
... ...
@@ -453,7 +453,7 @@ public interface SailingServiceWrite extends FileStorageManagementGwtService, Sa
453 453
String yellowBrickPassword);
454 454
455 455
MarkPropertiesDTO updateMarkPropertiesPositioning(UUID markPropertiesId, DeviceIdentifierDTO deviceIdentifier,
456
- Position fixedPosition);
456
+ Position fixedPosition) throws Exception;
457 457
458 458
CourseTemplateDTO createOrUpdateCourseTemplate(CourseTemplateDTO courseTemplate);
459 459
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java
... ...
@@ -2456,4 +2456,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
2456 2456
String eitherNoneOrBothStartAndEndOfRepeatablePartMustBeSpecified();
2457 2457
String endOfRepeatablePartMustBeAtOfAfterStart();
2458 2458
String endOfRepeatablePartIsGreaterThanNumberOfWaypoints();
2459
+ String configureCourse();
2459 2460
}
... ...
\ No newline at end of file
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties
... ...
@@ -2492,4 +2492,5 @@ zeroBasedNumberOfWaypointForRepeatablePartEnd=Repeatable sequence end waypoint i
2492 2492
defaultNumberOfLapsMustNotBeNegative=Default number of laps must not be negative.
2493 2493
eitherNoneOrBothStartAndEndOfRepeatablePartMustBeSpecified=Either none or both, start and end, of the repeatable part of the waypoint sequence must be specified.
2494 2494
endOfRepeatablePartMustBeAtOfAfterStart=End of repeatable part must be at or after start of repeatable part.
2495
-endOfRepeatablePartIsGreaterThanNumberOfWaypoints=End of repeatable part is greater than number of waypoints.
... ...
\ No newline at end of file
0
+endOfRepeatablePartIsGreaterThanNumberOfWaypoints=End of repeatable part is greater than number of waypoints.econfigureCourse
1
+configureCourse=Configure Course
... ...
\ No newline at end of file
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
... ...
@@ -2488,4 +2488,5 @@ zeroBasedNumberOfWaypointForRepeatablePartEnd=0-basierter Wegpunktindex für End
2488 2488
defaultNumberOfLapsMustNotBeNegative=Standard-Rundenzahl darf nicht negativ sein.
2489 2489
eitherNoneOrBothStartAndEndOfRepeatablePartMustBeSpecified=Anfang und Ende der wiederholbaren Wegpunkte-Sequenz müssen entweder beide gesetzt oder beide leer sein.
2490 2490
endOfRepeatablePartMustBeAtOfAfterStart=Ende der wiederholbaren Wegpunkte-Sequenz muss auf oder nach dem Anfang liegen.
2491
-endOfRepeatablePartIsGreaterThanNumberOfWaypoints=Ende der wiederholbaren Wegpunkte-Sequenz liegt hinter dem Ende der Wegpunkt-Liste.
... ...
\ No newline at end of file
0
+endOfRepeatablePartIsGreaterThanNumberOfWaypoints=Ende der wiederholbaren Wegpunkte-Sequenz liegt hinter dem Ende der Wegpunkt-Liste.
1
+configureCourse=Kurs konfigurieren
... ...
\ No newline at end of file
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java
... ...
@@ -222,6 +222,7 @@ import com.sap.sailing.domain.common.racelog.Flags;
222 222
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
223 223
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
224 224
import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException;
225
+import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice;
225 226
import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState;
226 227
import com.sap.sailing.domain.common.security.SecuredDomainType;
227 228
import com.sap.sailing.domain.common.security.SecuredDomainType.TrackedRaceActions;
... ...
@@ -233,18 +234,27 @@ import com.sap.sailing.domain.common.tracking.impl.PreciseCompactGPSFixMovingImp
233 234
import com.sap.sailing.domain.common.windfinder.SpotDTO;
234 235
import com.sap.sailing.domain.coursetemplate.CommonMarkProperties;
235 236
import com.sap.sailing.domain.coursetemplate.ControlPointTemplate;
237
+import com.sap.sailing.domain.coursetemplate.ControlPointWithMarkConfiguration;
238
+import com.sap.sailing.domain.coursetemplate.CourseConfiguration;
236 239
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
237 240
import com.sap.sailing.domain.coursetemplate.FixedPositioning;
241
+import com.sap.sailing.domain.coursetemplate.FreestyleMarkConfiguration;
242
+import com.sap.sailing.domain.coursetemplate.MarkConfiguration;
243
+import com.sap.sailing.domain.coursetemplate.MarkConfigurationRequestAnnotation;
244
+import com.sap.sailing.domain.coursetemplate.MarkConfigurationResponseAnnotation;
245
+import com.sap.sailing.domain.coursetemplate.MarkConfigurationVisitor;
238 246
import com.sap.sailing.domain.coursetemplate.MarkProperties;
247
+import com.sap.sailing.domain.coursetemplate.MarkPropertiesBasedMarkConfiguration;
239 248
import com.sap.sailing.domain.coursetemplate.MarkRole;
240 249
import com.sap.sailing.domain.coursetemplate.MarkRolePair.MarkRolePairFactory;
241 250
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
251
+import com.sap.sailing.domain.coursetemplate.MarkTemplateBasedMarkConfiguration;
242 252
import com.sap.sailing.domain.coursetemplate.PositioningVisitor;
243
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
253
+import com.sap.sailing.domain.coursetemplate.RegattaMarkConfiguration;
244 254
import com.sap.sailing.domain.coursetemplate.TrackingDeviceBasedPositioning;
245 255
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
256
+import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
246 257
import com.sap.sailing.domain.coursetemplate.impl.CommonMarkPropertiesImpl;
247
-import com.sap.sailing.domain.coursetemplate.impl.RepeatablePartImpl;
248 258
import com.sap.sailing.domain.coursetemplate.impl.WaypointTemplateImpl;
249 259
import com.sap.sailing.domain.igtimiadapter.Account;
250 260
import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory;
... ...
@@ -275,7 +285,6 @@ import com.sap.sailing.domain.racelogtracking.DeviceMapping;
275 285
import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapter;
276 286
import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapterFactory;
277 287
import com.sap.sailing.domain.racelogtracking.impl.DeviceMappingImpl;
278
-import com.sap.sailing.domain.racelogtracking.impl.SmartphoneUUIDIdentifierImpl;
279 288
import com.sap.sailing.domain.ranking.RankingMetric;
280 289
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
281 290
import com.sap.sailing.domain.regattalike.HasRegattaLike;
... ...
@@ -407,12 +416,21 @@ import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO;
407 416
import com.sap.sailing.gwt.ui.shared.YellowBrickConfigurationWithSecurityDTO;
408 417
import com.sap.sailing.gwt.ui.shared.YellowBrickRaceRecordDTO;
409 418
import com.sap.sailing.gwt.ui.shared.courseCreation.CommonMarkPropertiesDTO;
419
+import com.sap.sailing.gwt.ui.shared.courseCreation.ControlPointWithMarkConfigurationDTO;
420
+import com.sap.sailing.gwt.ui.shared.courseCreation.CourseConfigurationDTO;
410 421
import com.sap.sailing.gwt.ui.shared.courseCreation.CourseTemplateDTO;
422
+import com.sap.sailing.gwt.ui.shared.courseCreation.FreestyleMarkConfigurationDTO;
423
+import com.sap.sailing.gwt.ui.shared.courseCreation.MarkConfigurationDTO;
424
+import com.sap.sailing.gwt.ui.shared.courseCreation.MarkPairWithConfigurationDTO;
425
+import com.sap.sailing.gwt.ui.shared.courseCreation.MarkPropertiesBasedMarkConfigurationDTO;
411 426
import com.sap.sailing.gwt.ui.shared.courseCreation.MarkPropertiesDTO;
412 427
import com.sap.sailing.gwt.ui.shared.courseCreation.MarkRoleDTO;
428
+import com.sap.sailing.gwt.ui.shared.courseCreation.MarkTemplateBasedMarkConfigurationDTO;
413 429
import com.sap.sailing.gwt.ui.shared.courseCreation.MarkTemplateDTO;
430
+import com.sap.sailing.gwt.ui.shared.courseCreation.RegattaMarkConfigurationDTO;
414 431
import com.sap.sailing.gwt.ui.shared.courseCreation.RepeatablePartDTO;
415 432
import com.sap.sailing.gwt.ui.shared.courseCreation.WaypointTemplateDTO;
433
+import com.sap.sailing.gwt.ui.shared.courseCreation.WaypointWithMarkConfigurationDTO;
416 434
import com.sap.sailing.manage2sail.EventResultDescriptor;
417 435
import com.sap.sailing.manage2sail.Manage2SailEventResultsParserImpl;
418 436
import com.sap.sailing.manage2sail.RaceResultDescriptor;
... ...
@@ -441,9 +459,11 @@ import com.sap.sse.common.Distance;
441 459
import com.sap.sse.common.Duration;
442 460
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
443 461
import com.sap.sse.common.PairingListCreationException;
462
+import com.sap.sse.common.RepeatablePart;
444 463
import com.sap.sse.common.Speed;
445 464
import com.sap.sse.common.TimePoint;
446 465
import com.sap.sse.common.TimeRange;
466
+import com.sap.sse.common.Timed;
447 467
import com.sap.sse.common.TransformationException;
448 468
import com.sap.sse.common.TypeBasedServiceFinder;
449 469
import com.sap.sse.common.TypeBasedServiceFinderFactory;
... ...
@@ -452,6 +472,7 @@ import com.sap.sse.common.Util.Pair;
452 472
import com.sap.sse.common.Util.Triple;
453 473
import com.sap.sse.common.WithID;
454 474
import com.sap.sse.common.impl.MillisecondsTimePoint;
475
+import com.sap.sse.common.impl.RepeatablePartImpl;
455 476
import com.sap.sse.common.impl.SecondsDurationImpl;
456 477
import com.sap.sse.common.impl.TimeRangeImpl;
457 478
import com.sap.sse.common.media.MediaTagConstants;
... ...
@@ -4830,8 +4851,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
4830 4851
}
4831 4852
return finder;
4832 4853
}
4833
-
4834
- private DeviceIdentifier deserializeDeviceIdentifier(String type, String deviceId) throws NoCorrespondingServiceRegisteredException,
4854
+
4855
+ protected DeviceIdentifier deserializeDeviceIdentifier(String type, String deviceId) throws NoCorrespondingServiceRegisteredException,
4835 4856
TransformationException {
4836 4857
DeviceIdentifierStringSerializationHandler handler =
4837 4858
getDeviceIdentifierStringSerializerHandlerFinder(false).findService(type);
... ...
@@ -4871,13 +4892,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
4871 4892
4872 4893
protected DeviceMapping<?> convertToDeviceMapping(DeviceMappingDTO dto)
4873 4894
throws NoCorrespondingServiceRegisteredException, TransformationException {
4874
- DeviceIdentifier device = deserializeDeviceIdentifier(dto.deviceIdentifier.deviceType, dto.deviceIdentifier.deviceId);
4895
+ DeviceIdentifier device = convertDtoToDeviceIdentifier(dto.deviceIdentifier);
4875 4896
TimePoint from = dto.from == null ? null : new MillisecondsTimePoint(dto.from);
4876 4897
TimePoint to = dto.to == null ? null : new MillisecondsTimePoint(dto.to);
4877 4898
TimeRange timeRange = new TimeRangeImpl(from, to);
4878 4899
if (dto.mappedTo instanceof MarkDTO) {
4879 4900
Mark mark = convertToMark(((MarkDTO) dto.mappedTo), true);
4880
- //expect UUIDs
4901
+ // expect UUIDs
4881 4902
return new DeviceMappingImpl<Mark>(mark, device, timeRange, dto.originalRaceLogEventIds, RegattaLogDeviceMarkMappingEventImpl.class);
4882 4903
} else if (dto.mappedTo instanceof CompetitorDTO) {
4883 4904
Competitor competitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(
... ...
@@ -6070,9 +6091,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
6070 6091
markProperties.getType());
6071 6092
}
6072 6093
6073
- protected DeviceIdentifier convertDtoToDeviceIdentifier(DeviceIdentifierDTO deviceIdentifier) {
6074
- return deviceIdentifier != null ? new SmartphoneUUIDIdentifierImpl(UUID.fromString(deviceIdentifier.deviceId))
6075
- : null;
6094
+ protected DeviceIdentifier convertDtoToDeviceIdentifier(DeviceIdentifierDTO deviceIdentifier) throws NoCorrespondingServiceRegisteredException, TransformationException {
6095
+ return deserializeDeviceIdentifier(deviceIdentifier.deviceType, deviceIdentifier.deviceId);
6076 6096
}
6077 6097
6078 6098
@Override
... ...
@@ -6174,6 +6194,172 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
6174 6194
SecurityDTOUtil.addSecurityInformation(getSecurityService(), markRoleDTO);
6175 6195
return markRoleDTO;
6176 6196
}
6197
+
6198
+ protected DeviceMappingDTO convertToDeviceMappingDTO(DeviceMapping<?> mapping) throws TransformationException {
6199
+ final Map<DeviceIdentifier, Timed> lastFixes = getService().getSensorFixStore().getFixLastReceived(Collections.singleton(mapping.getDevice()));
6200
+ final Timed lastFix;
6201
+ if (lastFixes != null && lastFixes.containsKey(mapping.getDevice())) {
6202
+ lastFix = lastFixes.get(mapping.getDevice());
6203
+ } else {
6204
+ lastFix = null;
6205
+ }
6206
+ final Date from = mapping.getTimeRange().from() == null || mapping.getTimeRange().from().equals(TimePoint.BeginningOfTime) ?
6207
+ null : mapping.getTimeRange().from().asDate();
6208
+ final Date to = mapping.getTimeRange().to() == null || mapping.getTimeRange().to().equals(TimePoint.EndOfTime) ?
6209
+ null : mapping.getTimeRange().to().asDate();
6210
+ final MappableToDevice item;
6211
+ final WithID mappedTo = mapping.getMappedTo();
6212
+ if (mappedTo == null) {
6213
+ throw new RuntimeException("Device mapping not mapped to any object");
6214
+ } else if (mappedTo instanceof Competitor) {
6215
+ item = baseDomainFactory.convertToCompetitorDTO((Competitor) mapping.getMappedTo());
6216
+ } else if (mappedTo instanceof Mark) {
6217
+ item = convertToMarkDTO((Mark) mapping.getMappedTo(), null);
6218
+ } else if (mappedTo instanceof Boat) {
6219
+ item = baseDomainFactory.convertToBoatDTO((Boat) mappedTo);
6220
+ } else {
6221
+ throw new RuntimeException("Can only handle Competitor, Boat or Mark as mapped item type, but not "
6222
+ + mappedTo.getClass().getName());
6223
+ }
6224
+ // Only deal with UUIDs - otherwise we would have to pass Serializable to browser context - which
6225
+ // has a large performance impact for GWT.
6226
+ // As any Serializable subclass is converted to String by the BaseRaceLogEventSerializer, and only UUIDs are
6227
+ // recovered by the BaseRaceLogEventDeserializer, only UUIDs are safe to use anyway.
6228
+ final List<UUID> originalRaceLogEventUUIDs = new ArrayList<UUID>();
6229
+ for (final Serializable id : mapping.getOriginalRaceLogEventIds()) {
6230
+ if (! (id instanceof UUID)) {
6231
+ logger.log(Level.WARNING, "Got RaceLogEvent with id that was not UUID, but " + id.getClass().getName());
6232
+ throw new TransformationException("Could not send device mapping to browser: can only deal with UUIDs");
6233
+ }
6234
+ originalRaceLogEventUUIDs.add((UUID) id);
6235
+ }
6236
+ return new DeviceMappingDTO(convertDeviceIdentifierToDTO(mapping.getDevice()), from, to, item, originalRaceLogEventUUIDs, lastFix==null?null:lastFix.getTimePoint());
6237
+ }
6238
+
6239
+ private <P> void addMarkConfigurationAnnotationsToDTO(MarkConfiguration<P> markConfig, MarkConfigurationDTO addTo) {
6240
+ if (markConfig.getAnnotationInfo() instanceof MarkConfigurationRequestAnnotation) {
6241
+ final MarkConfigurationRequestAnnotation requestAnnotation = (MarkConfigurationRequestAnnotation) markConfig.getAnnotationInfo();
6242
+ addTo.setAddToMarkPropertiesInventoryRequest(requestAnnotation.isStoreToInventory());
6243
+ addTo.setCreateMarkRoleRequest(requestAnnotation.getOptionalMarkRoleCreationRequest() != null);
6244
+ if (requestAnnotation.getOptionalPositioning() != null) {
6245
+ requestAnnotation.getOptionalPositioning().accept(new PositioningVisitor<Void>() {
6246
+ @Override
6247
+ public Void visit(FixedPositioning fixedPositioning) {
6248
+ addTo.setFixedPositionRequest(fixedPositioning.getFixedPosition());
6249
+ return null;
6250
+ }
6251
+
6252
+ @Override
6253
+ public Void visit(TrackingDeviceBasedPositioning trackingDeviceBasedPositioning) {
6254
+ try {
6255
+ addTo.setDeviceMappingRequest(convertDeviceIdentifierToDTO(trackingDeviceBasedPositioning.getDeviceIdentifier()));
6256
+ } catch (TransformationException e) {
6257
+ throw new RuntimeException(e);
6258
+ }
6259
+ return null;
6260
+ }
6261
+ });
6262
+ }
6263
+ } else if (markConfig.getAnnotationInfo() instanceof MarkConfigurationResponseAnnotation) {
6264
+ final MarkConfigurationResponseAnnotation responseAnnotation = (MarkConfigurationResponseAnnotation) markConfig.getAnnotationInfo();
6265
+ if (responseAnnotation.getLastKnownPosition() != null) {
6266
+ addTo.setLastKnownPosition(new GPSFixDTO(responseAnnotation.getLastKnownPosition().getTimePoint().asDate(), responseAnnotation.getLastKnownPosition().getPosition()));
6267
+ addTo.setExistingDeviceMappings(Util.mapToArrayList(responseAnnotation.getDeviceMappings(), deviceIdAndTimeRangeAndLastGPSFix->{
6268
+ try {
6269
+ return new Triple<>(convertDeviceIdentifierToDTO(deviceIdAndTimeRangeAndLastGPSFix.getA()),
6270
+ deviceIdAndTimeRangeAndLastGPSFix.getB(),
6271
+ new GPSFixDTO(deviceIdAndTimeRangeAndLastGPSFix.getC().getTimePoint().asDate(), deviceIdAndTimeRangeAndLastGPSFix.getC().getPosition()));
6272
+ } catch (TransformationException e) {
6273
+ throw new RuntimeException();
6274
+ }
6275
+ }));
6276
+ }
6277
+ }
6278
+ }
6279
+
6280
+ protected DeviceIdentifierDTO convertDeviceIdentifierToDTO(final DeviceIdentifier deviceIdentifier)
6281
+ throws TransformationException {
6282
+ return new DeviceIdentifierDTO(deviceIdentifier.getIdentifierType(),
6283
+ serializeDeviceIdentifier(deviceIdentifier));
6284
+ }
6285
+
6286
+ protected <P> MarkConfigurationDTO convertToMarkConfigurationDTO(MarkConfiguration<P> markConfig) {
6287
+ final MarkConfigurationDTO result = markConfig.accept(new MarkConfigurationVisitor<MarkConfigurationDTO, P>() {
6288
+ @Override
6289
+ public MarkConfigurationDTO visit(FreestyleMarkConfiguration<P> markConfiguration) {
6290
+ final FreestyleMarkConfigurationDTO result = new FreestyleMarkConfigurationDTO();
6291
+ result.setOptionalMarkProperties(markConfiguration.getOptionalMarkProperties()==null?null:convertToMarkPropertiesDTO(markConfiguration.getOptionalMarkProperties()));
6292
+ result.setOptionalMarkTemplate(markConfiguration.getOptionalMarkTemplate()==null?null:convertToMarkTemplateDTO(markConfiguration.getOptionalMarkTemplate()));
6293
+ return result;
6294
+ }
6295
+
6296
+ @Override
6297
+ public MarkConfigurationDTO visit(MarkPropertiesBasedMarkConfiguration<P> markConfiguration) {
6298
+ final MarkPropertiesBasedMarkConfigurationDTO result = new MarkPropertiesBasedMarkConfigurationDTO();
6299
+ result.setMarkProperties(markConfiguration.getOptionalMarkProperties()==null?null:convertToMarkPropertiesDTO(markConfiguration.getOptionalMarkProperties()));
6300
+ result.setOptionalMarkTemplate(markConfiguration.getOptionalMarkTemplate()==null?null:convertToMarkTemplateDTO(markConfiguration.getOptionalMarkTemplate()));
6301
+ return result;
6302
+ }
6303
+
6304
+ @Override
6305
+ public MarkConfigurationDTO visit(MarkTemplateBasedMarkConfiguration<P> markConfiguration) {
6306
+ final MarkTemplateBasedMarkConfigurationDTO result = new MarkTemplateBasedMarkConfigurationDTO();
6307
+ result.setOptionalMarkTemplate(markConfiguration.getOptionalMarkTemplate()==null?null:convertToMarkTemplateDTO(markConfiguration.getOptionalMarkTemplate()));
6308
+ return result;
6309
+ }
6310
+
6311
+ @Override
6312
+ public MarkConfigurationDTO visit(RegattaMarkConfiguration<P> markConfiguration) {
6313
+ final RegattaMarkConfigurationDTO result = new RegattaMarkConfigurationDTO();
6314
+ result.setMark(convertToMarkDTO(markConfiguration.getMark(), /* position */ null));
6315
+ result.setOptionalMarkProperties(markConfiguration.getOptionalMarkProperties()==null?null:convertToMarkPropertiesDTO(markConfiguration.getOptionalMarkProperties()));
6316
+ result.setOptionalMarkTemplate(markConfiguration.getOptionalMarkTemplate()==null?null:convertToMarkTemplateDTO(markConfiguration.getOptionalMarkTemplate()));
6317
+ return result;
6318
+ }
6319
+ });
6320
+ addMarkConfigurationAnnotationsToDTO(markConfig, result);
6321
+ return result;
6322
+ }
6323
+
6324
+ private <P> ControlPointWithMarkConfigurationDTO convertToControlPointWithMarkConfigurationDTO(ControlPointWithMarkConfiguration<P> controlPoint) {
6325
+ final Iterable<MarkConfigurationDTO> markConfigurations = Util.map(controlPoint.getMarkConfigurations(), this::convertToMarkConfigurationDTO);
6326
+ final ControlPointWithMarkConfigurationDTO result;
6327
+ if (Util.size(markConfigurations) == 1) {
6328
+ result = markConfigurations.iterator().next();
6329
+ } else {
6330
+ final MarkPairWithConfigurationDTO preResult = new MarkPairWithConfigurationDTO();
6331
+ preResult.setName(controlPoint.getName());
6332
+ preResult.setShortName(controlPoint.getShortName());
6333
+ final Iterator<MarkConfigurationDTO> markConfigs = markConfigurations.iterator();
6334
+ preResult.setLeft(markConfigs.next());
6335
+ preResult.setRight(markConfigs.next());
6336
+ result = preResult;
6337
+ }
6338
+ return result;
6339
+ }
6340
+
6341
+ protected <P> WaypointWithMarkConfigurationDTO convertToWaypointWithMarkConfigurationDTO(final WaypointWithMarkConfiguration<P> waypointWithMarkConfiguration) {
6342
+ final WaypointWithMarkConfigurationDTO result = new WaypointWithMarkConfigurationDTO();
6343
+ result.setControlPoint(convertToControlPointWithMarkConfigurationDTO(waypointWithMarkConfiguration.getControlPoint()));
6344
+ result.setPassingInstruction(waypointWithMarkConfiguration.getPassingInstruction());
6345
+ return result;
6346
+ }
6347
+
6348
+ protected <P> CourseConfigurationDTO convertToCourseConfigurationDTO(CourseConfiguration<P> courseConfiguration) {
6349
+ final CourseConfigurationDTO result = new CourseConfigurationDTO();
6350
+ result.setAssociatedRoles(new HashMap<>(courseConfiguration.getAssociatedRoles().entrySet().stream().collect(Collectors.toMap(
6351
+ e->convertToMarkConfigurationDTO(e.getKey()), e->convertToMarkRoleDTO(e.getValue())))));
6352
+ result.setAllMarks(Util.mapToArrayList(courseConfiguration.getAllMarks(), this::convertToMarkConfigurationDTO));
6353
+ result.setName(courseConfiguration.getName());
6354
+ result.setShortName(courseConfiguration.getShortName());
6355
+ result.setNumberOfLaps(courseConfiguration.getNumberOfLaps());
6356
+ result.setOptionalCourseTemplate(courseConfiguration.getOptionalCourseTemplate()==null?null:convertToCourseTemplateDTO(courseConfiguration.getOptionalCourseTemplate()));
6357
+ result.setOptionalImageURL(courseConfiguration.getOptionalImageURL());
6358
+ result.setOptionalRepeatablePart(courseConfiguration.getRepeatablePart());
6359
+ result.setShortName(courseConfiguration.getShortName());
6360
+ result.setWaypoints(new ArrayList<>(Util.asList(Util.map(courseConfiguration.getWaypoints(), wpWithMarkConfig->convertToWaypointWithMarkConfigurationDTO(wpWithMarkConfig)))));
6361
+ return result;
6362
+ }
6177 6363
6178 6364
@Override
6179 6365
public List<MarkRoleDTO> getMarkRoles() {
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceWriteImpl.java
... ...
@@ -160,7 +160,6 @@ import com.sap.sailing.domain.common.CompetitorDescriptor;
160 160
import com.sap.sailing.domain.common.CompetitorRegistrationType;
161 161
import com.sap.sailing.domain.common.CourseDesignerMode;
162 162
import com.sap.sailing.domain.common.DataImportProgress;
163
-import com.sap.sailing.domain.common.DeviceIdentifier;
164 163
import com.sap.sailing.domain.common.LeaderboardNameConstants;
165 164
import com.sap.sailing.domain.common.MailInvitationType;
166 165
import com.sap.sailing.domain.common.MaxPointsReason;
... ...
@@ -207,7 +206,6 @@ import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl;
207 206
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
208 207
import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException;
209 208
import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException;
210
-import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice;
211 209
import com.sap.sailing.domain.common.racelog.tracking.MarkAlreadyUsedInRaceException;
212 210
import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException;
213 211
import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException;
... ...
@@ -223,7 +221,6 @@ import com.sap.sailing.domain.coursetemplate.MarkProperties;
223 221
import com.sap.sailing.domain.coursetemplate.MarkRole;
224 222
import com.sap.sailing.domain.coursetemplate.MarkRolePair.MarkRolePairFactory;
225 223
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
226
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
227 224
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
228 225
import com.sap.sailing.domain.igtimiadapter.Account;
229 226
import com.sap.sailing.domain.igtimiadapter.IgtimiConnection;
... ...
@@ -359,10 +356,10 @@ import com.sap.sailing.xrr.schema.RegattaResults;
359 356
import com.sap.sse.common.Distance;
360 357
import com.sap.sse.common.Duration;
361 358
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
359
+import com.sap.sse.common.RepeatablePart;
362 360
import com.sap.sse.common.Speed;
363 361
import com.sap.sse.common.TimePoint;
364 362
import com.sap.sse.common.TimeRange;
365
-import com.sap.sse.common.Timed;
366 363
import com.sap.sse.common.TransformationException;
367 364
import com.sap.sse.common.Util;
368 365
import com.sap.sse.common.Util.Pair;
... ...
@@ -514,7 +511,7 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili
514 511
515 512
@Override
516 513
public MarkPropertiesDTO updateMarkPropertiesPositioning(UUID markPropertiesId, DeviceIdentifierDTO deviceIdentifier,
517
- Position fixedPosition) {
514
+ Position fixedPosition) throws NoCorrespondingServiceRegisteredException, TransformationException {
518 515
MarkProperties markProperties = getSharedSailingData().getMarkPropertiesById(markPropertiesId);
519 516
if (deviceIdentifier != null) {
520 517
getSharedSailingData().setTrackingDeviceIdentifierForMarkProperties(markProperties, convertDtoToDeviceIdentifier(deviceIdentifier));
... ...
@@ -3882,49 +3879,6 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili
3882 3879
return null;
3883 3880
}
3884 3881
3885
- private DeviceMappingDTO convertToDeviceMappingDTO(DeviceMapping<?> mapping) throws TransformationException {
3886
- final Map<DeviceIdentifier, Timed> lastFixes = getService().getSensorFixStore().getFixLastReceived(Collections.singleton(mapping.getDevice()));
3887
- final Timed lastFix;
3888
- if (lastFixes != null && lastFixes.containsKey(mapping.getDevice())) {
3889
- lastFix = lastFixes.get(mapping.getDevice());
3890
- } else {
3891
- lastFix = null;
3892
- }
3893
- String deviceId = serializeDeviceIdentifier(mapping.getDevice());
3894
- Date from = mapping.getTimeRange().from() == null || mapping.getTimeRange().from().equals(TimePoint.BeginningOfTime) ?
3895
- null : mapping.getTimeRange().from().asDate();
3896
- Date to = mapping.getTimeRange().to() == null || mapping.getTimeRange().to().equals(TimePoint.EndOfTime) ?
3897
- null : mapping.getTimeRange().to().asDate();
3898
- MappableToDevice item = null;
3899
- final WithID mappedTo = mapping.getMappedTo();
3900
- if (mappedTo == null) {
3901
- throw new RuntimeException("Device mapping not mapped to any object");
3902
- } else if (mappedTo instanceof Competitor) {
3903
- item = baseDomainFactory.convertToCompetitorDTO((Competitor) mapping.getMappedTo());
3904
- } else if (mappedTo instanceof Mark) {
3905
- item = convertToMarkDTO((Mark) mapping.getMappedTo(), null);
3906
- } else if (mappedTo instanceof Boat) {
3907
- item = baseDomainFactory.convertToBoatDTO((Boat) mappedTo);
3908
- } else {
3909
- throw new RuntimeException("Can only handle Competitor, Boat or Mark as mapped item type, but not "
3910
- + mappedTo.getClass().getName());
3911
- }
3912
- //Only deal with UUIDs - otherwise we would have to pass Serializable to browser context - which
3913
- //has a large performance implact for GWT.
3914
- //As any Serializable subclass is converted to String by the BaseRaceLogEventSerializer, and only UUIDs are
3915
- //recovered by the BaseRaceLogEventDeserializer, only UUIDs are safe to use anyway.
3916
- List<UUID> originalRaceLogEventUUIDs = new ArrayList<UUID>();
3917
- for (Serializable id : mapping.getOriginalRaceLogEventIds()) {
3918
- if (! (id instanceof UUID)) {
3919
- logger.log(Level.WARNING, "Got RaceLogEvent with id that was not UUID, but " + id.getClass().getName());
3920
- throw new TransformationException("Could not send device mapping to browser: can only deal with UUIDs");
3921
- }
3922
- originalRaceLogEventUUIDs.add((UUID) id);
3923
- }
3924
- return new DeviceMappingDTO(new DeviceIdentifierDTO(mapping.getDevice().getIdentifierType(),
3925
- deviceId), from, to, item, originalRaceLogEventUUIDs, lastFix==null?null:lastFix.getTimePoint());
3926
- }
3927
-
3928 3882
private List<DeviceMappingDTO> getDeviceMappings(RegattaLog regattaLog) throws TransformationException {
3929 3883
List<DeviceMappingDTO> result = new ArrayList<DeviceMappingDTO>();
3930 3884
for (List<? extends DeviceMapping<WithID>> list : new RegattaLogDeviceMappingFinder<>(
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/courseCreation/ControlPointWithMarkConfigurationDTO.java
... ...
@@ -0,0 +1,11 @@
1
+package com.sap.sailing.gwt.ui.shared.courseCreation;
2
+
3
+import com.sap.sse.common.Named;
4
+
5
+public abstract class ControlPointWithMarkConfigurationDTO implements Named {
6
+ private static final long serialVersionUID = -5408248989419043559L;
7
+
8
+ public abstract Iterable<MarkConfigurationDTO> getMarkConfigurations();
9
+
10
+ public abstract String getShortName();
11
+}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/courseCreation/CourseConfigurationDTO.java
... ...
@@ -0,0 +1,127 @@
1
+package com.sap.sailing.gwt.ui.shared.courseCreation;
2
+
3
+import java.net.URL;
4
+import java.util.ArrayList;
5
+import java.util.HashMap;
6
+
7
+import com.google.gwt.user.client.rpc.IsSerializable;
8
+import com.sap.sailing.domain.coursetemplate.CourseTemplate;
9
+import com.sap.sse.common.RepeatablePart;
10
+
11
+public class CourseConfigurationDTO implements IsSerializable {
12
+ private String shortName;
13
+ private CourseTemplateDTO optionalCourseTemplate;
14
+ // TODO decide if we should combine markConfigurations and roleMapping to one field
15
+ private ArrayList<MarkConfigurationDTO> markConfigurations;
16
+ private HashMap<MarkConfigurationDTO, MarkRoleDTO> associatedRoles;
17
+
18
+ /**
19
+ * The waypoints sequence, with at least a single occurrence of any {@link #getRepeatablePart() repeatable part}, in
20
+ * order to obtain a sequence for more than only one lap (meaning zero occurrences of the repeatable part). There
21
+ * may be more occurrences of the repeatable part than only one, in particular to allow subsequent repetitions to
22
+ * use different mark configurations in their lap. See also {@link #getWaypoints()} and {@link #getWaypoints(int)}.
23
+ * So, if {@link #numberOfLaps} is less than or equal to {@code 1}, an occurrence of the repeatable part will be in
24
+ * this sequence although it isn't used in the current configuration. This is, however, required in order to
25
+ * interpret the index-based repeatable part in case one or more occurrences of the repeatable part will be
26
+ * requested.
27
+ * <p>
28
+ *
29
+ * This sequence may contain more occurrences of the repeatable part than requested through {@link #numberOfLaps}
30
+ * even if one or more occurrences of the repeatable part are requested this way. These extra occurrences will then
31
+ * be used if {@link #getWaypoints(int)} is called with more laps than {@link #numberOfLaps}. This way, a course
32
+ * configuration can prepare for more laps being sailed and prepare a configuration for extra laps that differ from
33
+ * the configurations used for the laps currently selected.
34
+ */
35
+ private ArrayList<WaypointWithMarkConfigurationDTO> waypoints;
36
+
37
+ /**
38
+ * Refers to a repeatable part in {@link #waypoints}. Other than in a {@link CourseTemplate} that always has exactly
39
+ * one occurrence of a repeatable part in its waypoint template sequence, here the {@link #waypoints} sequence must
40
+ * have at least one but may have multiple occurrences of the repeatable part. The special handling that happens in
41
+ * this class is that when more than one occurrence already exists in {@link #waypoints}, upon adding more
42
+ * repetitions the <em>last</em> occurrence will be repeated. See also {@link #getWaypoints(int)}.
43
+ */
44
+ private RepeatablePart optionalRepeatablePart;
45
+
46
+ /**
47
+ * The number of laps this course configuration has, in case there is a {@link #getRepeatablePart() repeatable part}
48
+ * defined for a valid {@link #optionalCourseTemplate}. In this case, {@link #getWaypoints()} will consider this
49
+ * number of laps and will return
50
+ */
51
+ private Integer numberOfLaps;
52
+
53
+ private String name;
54
+ private URL optionalImageURL;
55
+
56
+ public String getShortName() {
57
+ return shortName;
58
+ }
59
+
60
+ public void setShortName(String shortName) {
61
+ this.shortName = shortName;
62
+ }
63
+
64
+ public CourseTemplateDTO getOptionalCourseTemplate() {
65
+ return optionalCourseTemplate;
66
+ }
67
+
68
+ public void setOptionalCourseTemplate(CourseTemplateDTO optionalCourseTemplate) {
69
+ this.optionalCourseTemplate = optionalCourseTemplate;
70
+ }
71
+
72
+ public ArrayList<MarkConfigurationDTO> getAllMarks() {
73
+ return markConfigurations;
74
+ }
75
+
76
+ public void setAllMarks(ArrayList<MarkConfigurationDTO> markConfigurations) {
77
+ this.markConfigurations = markConfigurations;
78
+ }
79
+
80
+ public HashMap<MarkConfigurationDTO, MarkRoleDTO> getAssociatedRoles() {
81
+ return associatedRoles;
82
+ }
83
+
84
+ public void setAssociatedRoles(HashMap<MarkConfigurationDTO, MarkRoleDTO> associatedRoles) {
85
+ this.associatedRoles = associatedRoles;
86
+ }
87
+
88
+ public ArrayList<WaypointWithMarkConfigurationDTO> getWaypoints() {
89
+ return waypoints;
90
+ }
91
+
92
+ public void setWaypoints(ArrayList<WaypointWithMarkConfigurationDTO> waypoints) {
93
+ this.waypoints = waypoints;
94
+ }
95
+
96
+ public RepeatablePart getOptionalRepeatablePart() {
97
+ return optionalRepeatablePart;
98
+ }
99
+
100
+ public void setOptionalRepeatablePart(RepeatablePart optionalRepeatablePart) {
101
+ this.optionalRepeatablePart = optionalRepeatablePart;
102
+ }
103
+
104
+ public Integer getNumberOfLaps() {
105
+ return numberOfLaps;
106
+ }
107
+
108
+ public void setNumberOfLaps(Integer numberOfLaps) {
109
+ this.numberOfLaps = numberOfLaps;
110
+ }
111
+
112
+ public String getName() {
113
+ return name;
114
+ }
115
+
116
+ public void setName(String name) {
117
+ this.name = name;
118
+ }
119
+
120
+ public URL getOptionalImageURL() {
121
+ return optionalImageURL;
122
+ }
123
+
124
+ public void setOptionalImageURL(URL optionalImageURL) {
125
+ this.optionalImageURL = optionalImageURL;
126
+ }
127
+}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/courseCreation/FreestyleMarkConfigurationDTO.java
... ...
@@ -0,0 +1,30 @@
1
+package com.sap.sailing.gwt.ui.shared.courseCreation;
2
+
3
+public class FreestyleMarkConfigurationDTO extends MarkConfigurationDTO {
4
+ private static final long serialVersionUID = -752631017462284881L;
5
+ private CommonMarkPropertiesDTO freestyleProperties;
6
+ private MarkPropertiesDTO optionalMarkProperties;
7
+
8
+ @Override
9
+ public CommonMarkPropertiesDTO getEffectiveProperties() {
10
+ return freestyleProperties;
11
+ }
12
+
13
+ @Override
14
+ public String getName() {
15
+ return freestyleProperties.getName();
16
+ }
17
+
18
+ @Override
19
+ public String getShortName() {
20
+ return freestyleProperties.getShortName();
21
+ }
22
+
23
+ public MarkPropertiesDTO getOptionalMarkProperties() {
24
+ return optionalMarkProperties;
25
+ }
26
+
27
+ public void setOptionalMarkProperties(MarkPropertiesDTO optionalMarkProperties) {
28
+ this.optionalMarkProperties = optionalMarkProperties;
29
+ }
30
+}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/courseCreation/MarkConfigurationDTO.java
... ...
@@ -0,0 +1,86 @@
1
+package com.sap.sailing.gwt.ui.shared.courseCreation;
2
+
3
+import java.util.ArrayList;
4
+import java.util.Arrays;
5
+
6
+import com.sap.sailing.domain.common.Position;
7
+import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO;
8
+import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
9
+import com.sap.sse.common.TimeRange;
10
+import com.sap.sse.common.Util.Triple;
11
+
12
+public abstract class MarkConfigurationDTO extends ControlPointWithMarkConfigurationDTO {
13
+ private static final long serialVersionUID = -6944495722826431655L;
14
+ private MarkTemplateDTO optionalMarkTemplate;
15
+ private boolean addToMarkPropertiesInventoryRequest;
16
+ private boolean createMarkRoleRequest;
17
+ private Position fixedPositionRequest;
18
+ private DeviceIdentifierDTO deviceMappingRequest;
19
+ private GPSFixDTO lastKnownPosition;
20
+ private ArrayList<Triple<DeviceIdentifierDTO, TimeRange, GPSFixDTO>> existingDeviceMappings;
21
+
22
+ public MarkTemplateDTO getOptionalMarkTemplate() {
23
+ return optionalMarkTemplate;
24
+ }
25
+
26
+ public void setOptionalMarkTemplate(MarkTemplateDTO optionalMarkTemplate) {
27
+ this.optionalMarkTemplate = optionalMarkTemplate;
28
+ }
29
+
30
+ public abstract MarkPropertiesDTO getOptionalMarkProperties();
31
+
32
+ public abstract CommonMarkPropertiesDTO getEffectiveProperties();
33
+
34
+ @Override
35
+ public Iterable<MarkConfigurationDTO> getMarkConfigurations() {
36
+ return Arrays.asList(this);
37
+ }
38
+
39
+ public boolean isAddToMarkPropertiesInventoryRequest() {
40
+ return addToMarkPropertiesInventoryRequest;
41
+ }
42
+
43
+ public void setAddToMarkPropertiesInventoryRequest(boolean addToMarkPropertiesInventoryRequest) {
44
+ this.addToMarkPropertiesInventoryRequest = addToMarkPropertiesInventoryRequest;
45
+ }
46
+
47
+ public boolean isCreateMarkRoleRequest() {
48
+ return createMarkRoleRequest;
49
+ }
50
+
51
+ public void setCreateMarkRoleRequest(boolean createMarkRoleRequest) {
52
+ this.createMarkRoleRequest = createMarkRoleRequest;
53
+ }
54
+
55
+ public Position getFixedPositionRequest() {
56
+ return fixedPositionRequest;
57
+ }
58
+
59
+ public void setFixedPositionRequest(Position fixedPositionRequest) {
60
+ this.fixedPositionRequest = fixedPositionRequest;
61
+ }
62
+
63
+ public DeviceIdentifierDTO getDeviceMappingRequest() {
64
+ return deviceMappingRequest;
65
+ }
66
+
67
+ public void setDeviceMappingRequest(DeviceIdentifierDTO deviceMappingRequest) {
68
+ this.deviceMappingRequest = deviceMappingRequest;
69
+ }
70
+
71
+ public GPSFixDTO getLastKnownPosition() {
72
+ return lastKnownPosition;
73
+ }
74
+
75
+ public void setLastKnownPosition(GPSFixDTO lastKnownPosition) {
76
+ this.lastKnownPosition = lastKnownPosition;
77
+ }
78
+
79
+ public ArrayList<Triple<DeviceIdentifierDTO, TimeRange, GPSFixDTO>> getExistingDeviceMappings() {
80
+ return existingDeviceMappings;
81
+ }
82
+
83
+ public void setExistingDeviceMappings(ArrayList<Triple<DeviceIdentifierDTO, TimeRange, GPSFixDTO>> existingDeviceMappings) {
84
+ this.existingDeviceMappings = existingDeviceMappings;
85
+ }
86
+}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/courseCreation/MarkPairWithConfigurationDTO.java
... ...
@@ -0,0 +1,50 @@
1
+package com.sap.sailing.gwt.ui.shared.courseCreation;
2
+
3
+import java.util.Arrays;
4
+
5
+public class MarkPairWithConfigurationDTO extends ControlPointWithMarkConfigurationDTO {
6
+ private static final long serialVersionUID = -6712123101182399453L;
7
+ private MarkConfigurationDTO left;
8
+ private MarkConfigurationDTO right;
9
+ private String shortName;
10
+ private String name;
11
+
12
+ @Override
13
+ public Iterable<MarkConfigurationDTO> getMarkConfigurations() {
14
+ return Arrays.asList(left, right);
15
+ }
16
+
17
+ public MarkConfigurationDTO getLeft() {
18
+ return left;
19
+ }
20
+
21
+ public void setLeft(MarkConfigurationDTO left) {
22
+ this.left = left;
23
+ }
24
+
25
+ public MarkConfigurationDTO getRight() {
26
+ return right;
27
+ }
28
+
29
+ public void setRight(MarkConfigurationDTO right) {
30
+ this.right = right;
31
+ }
32
+
33
+ @Override
34
+ public String getShortName() {
35
+ return shortName;
36
+ }
37
+
38
+ public void setShortName(String shortName) {
39
+ this.shortName = shortName;
40
+ }
41
+
42
+ @Override
43
+ public String getName() {
44
+ return name;
45
+ }
46
+
47
+ public void setName(String name) {
48
+ this.name = name;
49
+ }
50
+}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/courseCreation/MarkPropertiesBasedMarkConfigurationDTO.java
... ...
@@ -0,0 +1,39 @@
1
+package com.sap.sailing.gwt.ui.shared.courseCreation;
2
+
3
+import java.util.Arrays;
4
+
5
+public class MarkPropertiesBasedMarkConfigurationDTO extends MarkConfigurationDTO {
6
+
7
+ private static final long serialVersionUID = 2204116830344315567L;
8
+ private MarkPropertiesDTO markProperties;
9
+
10
+ public void setMarkProperties(MarkPropertiesDTO markProperties) {
11
+ this.markProperties = markProperties;
12
+ }
13
+
14
+ @Override
15
+ public MarkPropertiesDTO getOptionalMarkProperties() {
16
+ return markProperties;
17
+ }
18
+
19
+ @Override
20
+ public CommonMarkPropertiesDTO getEffectiveProperties() {
21
+ return markProperties.getCommonMarkProperties();
22
+ }
23
+
24
+ @Override
25
+ public Iterable<MarkConfigurationDTO> getMarkConfigurations() {
26
+ return Arrays.asList(this);
27
+ }
28
+
29
+ @Override
30
+ public String getName() {
31
+ return markProperties.getName();
32
+ }
33
+
34
+ @Override
35
+ public String getShortName() {
36
+ return markProperties.getCommonMarkProperties().getShortName();
37
+ }
38
+
39
+}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/courseCreation/MarkTemplateBasedMarkConfigurationDTO.java
... ...
@@ -0,0 +1,27 @@
1
+package com.sap.sailing.gwt.ui.shared.courseCreation;
2
+
3
+public class MarkTemplateBasedMarkConfigurationDTO extends MarkConfigurationDTO {
4
+
5
+ private static final long serialVersionUID = 4766727754528156938L;
6
+
7
+ @Override
8
+ public String getName() {
9
+ return getOptionalMarkTemplate().getName();
10
+ }
11
+
12
+ @Override
13
+ public MarkPropertiesDTO getOptionalMarkProperties() {
14
+ return null;
15
+ }
16
+
17
+ @Override
18
+ public CommonMarkPropertiesDTO getEffectiveProperties() {
19
+ return getOptionalMarkTemplate().getCommonMarkProperties();
20
+ }
21
+
22
+ @Override
23
+ public String getShortName() {
24
+ // TODO Auto-generated method stub
25
+ return getOptionalMarkTemplate().getCommonMarkProperties().getShortName();
26
+ }
27
+}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/courseCreation/RegattaMarkConfigurationDTO.java
... ...
@@ -0,0 +1,47 @@
1
+package com.sap.sailing.gwt.ui.shared.courseCreation;
2
+
3
+import com.sap.sailing.gwt.ui.shared.MarkDTO;
4
+
5
+public class RegattaMarkConfigurationDTO extends MarkConfigurationDTO {
6
+
7
+ private static final long serialVersionUID = -9209811588621240132L;
8
+ private MarkDTO mark;
9
+ private MarkPropertiesDTO optionalMarkProperties;
10
+
11
+ @Override
12
+ public String getName() {
13
+ return mark.getName();
14
+ }
15
+
16
+ public void setOptionalMarkProperties(MarkPropertiesDTO optionalMarkProperties) {
17
+ this.optionalMarkProperties = optionalMarkProperties;
18
+ }
19
+
20
+ @Override
21
+ public MarkPropertiesDTO getOptionalMarkProperties() {
22
+ return optionalMarkProperties;
23
+ }
24
+
25
+ @Override
26
+ public void setOptionalMarkTemplate(MarkTemplateDTO optionalMarkTemplate) {
27
+ super.setOptionalMarkTemplate(optionalMarkTemplate);
28
+ }
29
+
30
+ @Override
31
+ public CommonMarkPropertiesDTO getEffectiveProperties() {
32
+ return new CommonMarkPropertiesDTO(mark.getName(), mark.getShortName(), mark.color, mark.shape, mark.pattern, mark.type);
33
+ }
34
+
35
+ @Override
36
+ public String getShortName() {
37
+ return mark.getShortName();
38
+ }
39
+
40
+ public MarkDTO getMark() {
41
+ return mark;
42
+ }
43
+
44
+ public void setMark(MarkDTO mark) {
45
+ this.mark = mark;
46
+ }
47
+}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/courseCreation/WaypointWithMarkConfigurationDTO.java
... ...
@@ -0,0 +1,25 @@
1
+package com.sap.sailing.gwt.ui.shared.courseCreation;
2
+
3
+import com.google.gwt.user.client.rpc.IsSerializable;
4
+import com.sap.sailing.domain.common.PassingInstruction;
5
+
6
+public class WaypointWithMarkConfigurationDTO implements IsSerializable {
7
+ private ControlPointWithMarkConfigurationDTO controlPoint;
8
+ private PassingInstruction passingInstruction;
9
+
10
+ public ControlPointWithMarkConfigurationDTO getControlPoint() {
11
+ return controlPoint;
12
+ }
13
+
14
+ public void setControlPoint(ControlPointWithMarkConfigurationDTO controlPoint) {
15
+ this.controlPoint = controlPoint;
16
+ }
17
+
18
+ public PassingInstruction getPassingInstruction() {
19
+ return passingInstruction;
20
+ }
21
+
22
+ public void setPassingInstruction(PassingInstruction passingInstruction) {
23
+ this.passingInstruction = passingInstruction;
24
+ }
25
+}
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CourseConfigurationBuilder.java
... ...
@@ -39,7 +39,6 @@ import com.sap.sailing.domain.coursetemplate.MarkTemplateBasedMarkConfiguration;
39 39
import com.sap.sailing.domain.coursetemplate.Positioning;
40 40
import com.sap.sailing.domain.coursetemplate.PositioningVisitor;
41 41
import com.sap.sailing.domain.coursetemplate.RegattaMarkConfiguration;
42
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
43 42
import com.sap.sailing.domain.coursetemplate.TrackingDeviceBasedPositioning;
44 43
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
45 44
import com.sap.sailing.domain.coursetemplate.impl.CourseConfigurationImpl;
... ...
@@ -55,6 +54,7 @@ import com.sap.sailing.domain.racelogtracking.DeviceMappingWithRegattaLogEvent;
55 54
import com.sap.sailing.domain.tracking.GPSFixTrack;
56 55
import com.sap.sailing.domain.tracking.TrackedRace;
57 56
import com.sap.sailing.shared.server.SharedSailingData;
57
+import com.sap.sse.common.RepeatablePart;
58 58
import com.sap.sse.common.TimeRange;
59 59
import com.sap.sse.common.Util.Triple;
60 60
import com.sap.sse.common.WithID;
... ...
@@ -386,6 +386,9 @@ public class CourseConfigurationBuilder {
386 386
return bestMatchingDeviceMapping;
387 387
}
388 388
389
+ /**
390
+ * @return a non-{@code null} iterable
391
+ */
389 392
private static Iterable<Triple<DeviceIdentifier, TimeRange, GPSFix>> findAllDevicesAndMappedRangesForMark(
390 393
final Regatta regatta, Mark mark, Function<DeviceIdentifier, GPSFix> positionResolver) {
391 394
final Map<WithID, List<DeviceMappingWithRegattaLogEvent<WithID>>> deviceMappings = new RegattaLogDeviceMappingFinder<>(
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CourseConfigurationJsonDeserializer.java
... ...
@@ -20,10 +20,10 @@ import com.sap.sailing.domain.coursetemplate.MarkConfiguration;
20 20
import com.sap.sailing.domain.coursetemplate.MarkConfigurationRequestAnnotation;
21 21
import com.sap.sailing.domain.coursetemplate.MarkConfigurationRequestAnnotation.MarkRoleCreationRequest;
22 22
import com.sap.sailing.domain.coursetemplate.Positioning;
23
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
24 23
import com.sap.sailing.domain.coursetemplate.impl.MarkConfigurationRequestAnnotationImpl.MarkRoleCreationRequestImpl;
25 24
import com.sap.sailing.server.gateway.serialization.impl.CourseConfigurationJsonSerializer;
26 25
import com.sap.sailing.shared.server.SharedSailingData;
26
+import com.sap.sse.common.RepeatablePart;
27 27
import com.sap.sse.shared.json.JsonDeserializationException;
28 28
import com.sap.sse.shared.json.JsonDeserializer;
29 29
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CourseTemplateJsonDeserializer.java
... ...
@@ -18,13 +18,13 @@ import com.sap.sailing.domain.coursetemplate.CourseTemplate;
18 18
import com.sap.sailing.domain.coursetemplate.MarkRole;
19 19
import com.sap.sailing.domain.coursetemplate.MarkRolePair.MarkRolePairFactory;
20 20
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
21
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
22 21
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
23 22
import com.sap.sailing.domain.coursetemplate.impl.CourseTemplateImpl;
24 23
import com.sap.sailing.domain.coursetemplate.impl.WaypointTemplateImpl;
25 24
import com.sap.sailing.server.gateway.serialization.impl.CourseTemplateJsonSerializer;
26 25
import com.sap.sailing.server.gateway.serialization.impl.MarkRoleJsonSerializer;
27 26
import com.sap.sailing.server.gateway.serialization.impl.MarkTemplateJsonSerializer;
27
+import com.sap.sse.common.RepeatablePart;
28 28
import com.sap.sse.shared.json.JsonDeserializationException;
29 29
import com.sap.sse.shared.json.JsonDeserializer;
30 30
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/RepeatablePartJsonDeserializer.java
... ...
@@ -2,9 +2,9 @@ package com.sap.sailing.server.gateway.deserialization.impl;
2 2
3 3
import org.json.simple.JSONObject;
4 4
5
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
6
-import com.sap.sailing.domain.coursetemplate.impl.RepeatablePartImpl;
7 5
import com.sap.sailing.server.gateway.serialization.impl.RepeatablePartJsonSerializer;
6
+import com.sap.sse.common.RepeatablePart;
7
+import com.sap.sse.common.impl.RepeatablePartImpl;
8 8
import com.sap.sse.shared.json.JsonDeserializationException;
9 9
import com.sap.sse.shared.json.JsonDeserializer;
10 10
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CourseConfigurationJsonSerializer.java
... ...
@@ -22,8 +22,8 @@ import com.sap.sailing.domain.coursetemplate.MarkPropertiesBasedMarkConfiguratio
22 22
import com.sap.sailing.domain.coursetemplate.MarkRole;
23 23
import com.sap.sailing.domain.coursetemplate.MarkTemplateBasedMarkConfiguration;
24 24
import com.sap.sailing.domain.coursetemplate.RegattaMarkConfiguration;
25
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
26 25
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
26
+import com.sap.sse.common.RepeatablePart;
27 27
import com.sap.sse.common.TimeRange;
28 28
import com.sap.sse.common.Util.Triple;
29 29
import com.sap.sse.shared.json.JsonSerializer;
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CourseTemplateJsonSerializer.java
... ...
@@ -5,7 +5,7 @@ import org.json.simple.JSONObject;
5 5
6 6
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
7 7
import com.sap.sailing.domain.coursetemplate.MarkRole;
8
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
8
+import com.sap.sse.common.RepeatablePart;
9 9
import com.sap.sse.shared.json.JsonSerializer;
10 10
11 11
public class CourseTemplateJsonSerializer implements JsonSerializer<CourseTemplate> {
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RepeatablePartJsonSerializer.java
... ...
@@ -2,7 +2,7 @@ package com.sap.sailing.server.gateway.serialization.impl;
2 2
3 3
import org.json.simple.JSONObject;
4 4
5
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
5
+import com.sap.sse.common.RepeatablePart;
6 6
import com.sap.sse.shared.json.JsonSerializer;
7 7
8 8
public class RepeatablePartJsonSerializer implements JsonSerializer<RepeatablePart> {
java/com.sap.sailing.server.interface/src/com/sap/sailing/server/interfaces/CourseAndMarkConfigurationFactory.java
... ...
@@ -22,12 +22,12 @@ import com.sap.sailing.domain.coursetemplate.MarkConfigurationResponseAnnotation
22 22
import com.sap.sailing.domain.coursetemplate.MarkProperties;
23 23
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
24 24
import com.sap.sailing.domain.coursetemplate.MarkTemplateBasedMarkConfiguration;
25
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
26 25
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
27 26
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
28
-import com.sap.sailing.domain.coursetemplate.WithOptionalRepeatablePart;
29 27
import com.sap.sailing.domain.tracking.TrackedRace;
28
+import com.sap.sse.common.RepeatablePart;
30 29
import com.sap.sse.common.TimePoint;
30
+import com.sap.sse.common.WithOptionalRepeatablePart;
31 31
import com.sap.sse.security.shared.impl.UserGroup;
32 32
33 33
/**
... ...
@@ -90,7 +90,9 @@ public interface CourseAndMarkConfigurationFactory {
90 90
* {@link Regatta} is given, the {@link MarkTemplate}s are mapped to contained {@link Mark}s if possible.
91 91
* <p>
92 92
*
93
- * TODO how is this match-making performed? Looking at the Mark's getOriginatingMarkTemplateIdOrNull() values?
93
+ * Match-making happens in an inner implementation class called {@link LastUsageBasedAssociater}, basically based on
94
+ * the start times of the races using marks for {@link Mark#getOriginatingMarkTemplateIdOrNull() mark templates} in
95
+ * a {@link Course} {@link Course#getOriginatingCourseTemplateIdOrNull() derived} from a {@link CourseTemplate}.
94 96
* <p>
95 97
*
96 98
* Any {@link MarkTemplate} not mapped to a {@link Mark} (in case, no {@link Regatta} is given, these are just all
... ...
@@ -105,13 +107,13 @@ public interface CourseAndMarkConfigurationFactory {
105 107
* The {@link CourseConfiguration#getNumberOfLaps() number of laps} matches the
106 108
* {@link CourseTemplate#getDefaultNumberOfLaps() template's default number of laps} which is relevant only if the
107 109
* {@link CourseTemplate} specifies a {@link CourseTemplate#getRepeatablePart() repeatable part}.
110
+ *
108 111
* @param optionalRegatta
109 112
* If given, {@link MarkTemplate}s of the given {@link CourseTemplate} are automatically mapped to their
110 113
* {@link Mark} counterpart of the {@link Regatta}.
111 114
* @param tagsToFilterMarkProperties
112 115
* If given, any {@link MarkProperties} that is suggested to replace a {@link MarkTemplate} of the given
113 116
* {@link CourseTemplate} needs to match all given tags.
114
- * @param optionalNumberOfLaps TODO
115 117
*/
116 118
CourseConfiguration<MarkConfigurationResponseAnnotation> createCourseConfigurationFromTemplate(
117 119
CourseTemplate courseTemplate, Regatta optionalRegatta, Iterable<String> tagsToFilterMarkProperties, Integer optionalNumberOfLaps);
java/com.sap.sailing.server.test/src/com/sap/sailing/server/impl/CourseTemplateCompatibilityCheckerTest.java
... ...
@@ -0,0 +1,211 @@
1
+package com.sap.sailing.server.impl;
2
+
3
+import static org.junit.Assert.assertEquals;
4
+import static org.junit.Assert.assertNull;
5
+
6
+import java.util.Arrays;
7
+import java.util.HashMap;
8
+import java.util.Map;
9
+import java.util.UUID;
10
+
11
+import org.junit.Before;
12
+import org.junit.Test;
13
+
14
+import com.sap.sailing.domain.base.ControlPointWithTwoMarks;
15
+import com.sap.sailing.domain.base.CourseBase;
16
+import com.sap.sailing.domain.base.DomainFactory;
17
+import com.sap.sailing.domain.base.Mark;
18
+import com.sap.sailing.domain.base.Waypoint;
19
+import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl;
20
+import com.sap.sailing.domain.base.impl.CourseDataImpl;
21
+import com.sap.sailing.domain.base.impl.MarkImpl;
22
+import com.sap.sailing.domain.base.impl.WaypointImpl;
23
+import com.sap.sailing.domain.common.MarkType;
24
+import com.sap.sailing.domain.common.PassingInstruction;
25
+import com.sap.sailing.domain.coursetemplate.CourseTemplate;
26
+import com.sap.sailing.domain.coursetemplate.MarkRole;
27
+import com.sap.sailing.domain.coursetemplate.MarkRolePair;
28
+import com.sap.sailing.domain.coursetemplate.MarkTemplate;
29
+import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
30
+import com.sap.sailing.domain.coursetemplate.impl.CourseTemplateImpl;
31
+import com.sap.sailing.domain.coursetemplate.impl.MarkRoleImpl;
32
+import com.sap.sailing.domain.coursetemplate.impl.MarkRolePairImpl;
33
+import com.sap.sailing.domain.coursetemplate.impl.MarkTemplateImpl;
34
+import com.sap.sailing.domain.coursetemplate.impl.WaypointTemplateImpl;
35
+import com.sap.sailing.server.impl.CourseAndMarkConfigurationFactoryImpl.CourseTemplateCompatibilityCheckerForCourseBase;
36
+import com.sap.sse.common.Color;
37
+import com.sap.sse.common.impl.RepeatablePartImpl;
38
+
39
+public class CourseTemplateCompatibilityCheckerTest {
40
+ private MarkRole startFinishBoatRole, startFinishPinRole, windwardMarkRole, leewardGatePortRole, leewardGateStarboardRole;
41
+ private MarkTemplate startFinishBoatTemplate, startFinishPinTemplate, windwardMarkTemplate, leewardGatePortTemplate, leewardGateStarboardTemplate;
42
+ private MarkRolePair startFinishLineRoles, leewardGateRoles;
43
+ private WaypointTemplate startWaypointTemplate, firstWindwardMarkWaypointTemplate, leewardGateWaypointTemplate, repeatableWindwardMarkWaypointTemplate, finishWaypointTemplate;
44
+ private CourseTemplate windwardLeewardWithLeewardFinishCourseTemplate;
45
+ private CourseBase courseBase;
46
+ private Mark startBoat, startPin, windward, gatePort, gateStarboard;
47
+ private ControlPointWithTwoMarks startFinishLine, gate;
48
+
49
+ @Before
50
+ public void setUp() {
51
+ // mark roles:
52
+ startFinishBoatRole = new MarkRoleImpl(UUID.randomUUID(), "Start/Finish Boat", "SFB");
53
+ startFinishPinRole = new MarkRoleImpl(UUID.randomUUID(), "Start/Finish Pin", "SFP");
54
+ windwardMarkRole = new MarkRoleImpl(UUID.randomUUID(), "Windward Mark", "WW");
55
+ leewardGatePortRole = new MarkRoleImpl(UUID.randomUUID(), "Leeward Gate Port", "LGP");
56
+ leewardGateStarboardRole = new MarkRoleImpl(UUID.randomUUID(), "Leeward Gate Starboard", "LGS");
57
+ // mark templates:
58
+ startFinishBoatTemplate = new MarkTemplateImpl("Start/Finish Boat", "SFB", Color.BROWN, /* shape */ null, /* pattern */ null, MarkType.STARTBOAT);
59
+ startFinishPinTemplate = new MarkTemplateImpl("Start/Finish Pin", "SFP", Color.BROWN, /* shape */ null, /* pattern */ null, MarkType.BUOY);
60
+ windwardMarkTemplate = new MarkTemplateImpl("Windward Mark", "WW", Color.BROWN, /* shape */ null, /* pattern */ null, MarkType.BUOY);
61
+ leewardGatePortTemplate = new MarkTemplateImpl("Leeward Gate Port", "LGP", Color.BROWN, /* shape */ null, /* pattern */ null, MarkType.BUOY);
62
+ leewardGateStarboardTemplate = new MarkTemplateImpl("Leeward Gate Starboard", "LGS", Color.BROWN, /* shape */ null, /* pattern */ null, MarkType.BUOY);
63
+ // MarkRolePairs:
64
+ startFinishLineRoles = new MarkRolePairImpl("Start/Finish Line", "SFL", startFinishPinRole, startFinishBoatRole);
65
+ leewardGateRoles = new MarkRolePairImpl("Leeward Gate", "LG", leewardGatePortRole, leewardGateStarboardRole);
66
+ // role/mark-template associations:
67
+ final Map<MarkRole, MarkTemplate> defaultMarkTemplatesForMarkRoles = new HashMap<>();
68
+ defaultMarkTemplatesForMarkRoles.put(startFinishBoatRole, startFinishBoatTemplate);
69
+ defaultMarkTemplatesForMarkRoles.put(startFinishPinRole, startFinishPinTemplate);
70
+ defaultMarkTemplatesForMarkRoles.put(windwardMarkRole, windwardMarkTemplate);
71
+ defaultMarkTemplatesForMarkRoles.put(leewardGatePortRole, leewardGatePortTemplate);
72
+ defaultMarkTemplatesForMarkRoles.put(leewardGateStarboardRole, leewardGateStarboardTemplate);
73
+ final Map<MarkTemplate, MarkRole> defaultMarkRolesForMarkTemplates = new HashMap<>();
74
+ defaultMarkRolesForMarkTemplates.put(startFinishBoatTemplate, startFinishBoatRole);
75
+ defaultMarkRolesForMarkTemplates.put(startFinishPinTemplate, startFinishPinRole);
76
+ defaultMarkRolesForMarkTemplates.put(windwardMarkTemplate, windwardMarkRole);
77
+ defaultMarkRolesForMarkTemplates.put(leewardGatePortTemplate, leewardGatePortRole);
78
+ defaultMarkRolesForMarkTemplates.put(leewardGateStarboardTemplate, leewardGateStarboardRole);
79
+ // waypoint templates:
80
+ startWaypointTemplate = new WaypointTemplateImpl(startFinishLineRoles, PassingInstruction.Line);
81
+ firstWindwardMarkWaypointTemplate = new WaypointTemplateImpl(windwardMarkRole, PassingInstruction.Port);
82
+ leewardGateWaypointTemplate = new WaypointTemplateImpl(leewardGateRoles, PassingInstruction.Gate);
83
+ repeatableWindwardMarkWaypointTemplate = new WaypointTemplateImpl(windwardMarkRole, PassingInstruction.Port);
84
+ finishWaypointTemplate = new WaypointTemplateImpl(startFinishLineRoles, PassingInstruction.Line);
85
+ // assemble course template:
86
+ windwardLeewardWithLeewardFinishCourseTemplate = new CourseTemplateImpl(UUID.randomUUID(),
87
+ "Windward/Leeward with Leeward Finish", "L",
88
+ Arrays.asList(startFinishBoatTemplate, startFinishPinTemplate, windwardMarkTemplate,
89
+ leewardGatePortTemplate, leewardGateStarboardTemplate),
90
+ Arrays.asList(startWaypointTemplate, firstWindwardMarkWaypointTemplate, leewardGateWaypointTemplate,
91
+ repeatableWindwardMarkWaypointTemplate, finishWaypointTemplate),
92
+ defaultMarkTemplatesForMarkRoles, defaultMarkRolesForMarkTemplates, /* optionalImageURL */ null,
93
+ /* optionalRepeatablePart */ new RepeatablePartImpl(2, 4), /* defaultNumberOfLaps */ 1);
94
+ // now for the CourseBase set-up:
95
+ courseBase = new CourseDataImpl("L2", windwardLeewardWithLeewardFinishCourseTemplate.getId());
96
+ // marks:
97
+ startBoat = new MarkImpl(UUID.randomUUID(), "Start Boat", MarkType.STARTBOAT, /* color */ null, /* shape */ null, /* pattern */ null);
98
+ startPin = new MarkImpl(UUID.randomUUID(), "Start Pin");
99
+ windward = new MarkImpl(UUID.randomUUID(), "Winward");
100
+ gatePort = new MarkImpl(UUID.randomUUID(), "Gate Port");
101
+ gateStarboard = new MarkImpl(UUID.randomUUID(), "Gate Starboard");
102
+ // control points with two marks:
103
+ startFinishLine = new ControlPointWithTwoMarksImpl(startPin, startBoat, "Start/Finish Line", "SFL");
104
+ gate = new ControlPointWithTwoMarksImpl(gatePort, gateStarboard, "Leeward Gate", "LG");
105
+ }
106
+
107
+ @Test
108
+ public void testSimpleCourseComplianceWithTwoLaps() {
109
+ final Waypoint startWP, windward1WP, gateWP, windward2WP, finishWP;
110
+ // waypoints:
111
+ startWP = new WaypointImpl(startFinishLine, PassingInstruction.Line);
112
+ windward1WP = new WaypointImpl(windward, PassingInstruction.Port);
113
+ gateWP = new WaypointImpl(gate, PassingInstruction.Gate);
114
+ windward2WP = new WaypointImpl(windward, PassingInstruction.Port);
115
+ finishWP = new WaypointImpl(startFinishLine, PassingInstruction.Line);
116
+ // course:
117
+ courseBase.addWaypoint(0, startWP);
118
+ courseBase.addRoleMapping(startBoat, startFinishBoatRole.getId());
119
+ courseBase.addRoleMapping(startPin, startFinishPinRole.getId());
120
+ courseBase.addWaypoint(1, windward1WP);
121
+ courseBase.addRoleMapping(windward, windwardMarkRole.getId());
122
+ courseBase.addWaypoint(2, gateWP);
123
+ courseBase.addRoleMapping(gatePort, leewardGatePortRole.getId());
124
+ courseBase.addRoleMapping(gateStarboard, leewardGateStarboardRole.getId());
125
+ courseBase.addWaypoint(3, windward2WP);
126
+ courseBase.addWaypoint(4, finishWP);
127
+ final Integer numberOfLaps = getNumberOfLaps();
128
+ assertEquals(2, (int) numberOfLaps);
129
+ }
130
+
131
+ @Test
132
+ public void testSimpleCourseComplianceWithThreeLaps() {
133
+ final Waypoint startWP, windward1WP, gate1WP, windward2WP, gate2WP, windward3WP, finishWP;
134
+ // waypoints:
135
+ startWP = new WaypointImpl(startFinishLine, PassingInstruction.Line);
136
+ windward1WP = new WaypointImpl(windward, PassingInstruction.Port);
137
+ gate1WP = new WaypointImpl(gate, PassingInstruction.Gate);
138
+ windward2WP = new WaypointImpl(windward, PassingInstruction.Port);
139
+ gate2WP = new WaypointImpl(gate, PassingInstruction.Gate);
140
+ windward3WP = new WaypointImpl(windward, PassingInstruction.Port);
141
+ finishWP = new WaypointImpl(startFinishLine, PassingInstruction.Line);
142
+ // course:
143
+ courseBase.addWaypoint(0, startWP);
144
+ courseBase.addRoleMapping(startBoat, startFinishBoatRole.getId());
145
+ courseBase.addRoleMapping(startPin, startFinishPinRole.getId());
146
+ courseBase.addWaypoint(1, windward1WP);
147
+ courseBase.addRoleMapping(windward, windwardMarkRole.getId());
148
+ courseBase.addWaypoint(2, gate1WP);
149
+ courseBase.addRoleMapping(gatePort, leewardGatePortRole.getId());
150
+ courseBase.addRoleMapping(gateStarboard, leewardGateStarboardRole.getId());
151
+ courseBase.addWaypoint(3, windward2WP);
152
+ courseBase.addWaypoint(4, gate2WP);
153
+ courseBase.addWaypoint(5, windward3WP);
154
+ courseBase.addWaypoint(6, finishWP);
155
+ final Integer numberOfLaps = getNumberOfLaps();
156
+ assertEquals(3, (int) numberOfLaps);
157
+ }
158
+
159
+ @Test
160
+ public void testSimpleCourseComplianceWithIncompatibleSetup() {
161
+ final Waypoint startWP, windward1WP, gate1WP, windward2WP, gate2WP;
162
+ // waypoints:
163
+ startWP = new WaypointImpl(startFinishLine, PassingInstruction.Line);
164
+ windward1WP = new WaypointImpl(windward, PassingInstruction.Port);
165
+ gate1WP = new WaypointImpl(gate, PassingInstruction.Gate);
166
+ windward2WP = new WaypointImpl(windward, PassingInstruction.Port);
167
+ gate2WP = new WaypointImpl(gate, PassingInstruction.Line);
168
+ // course:
169
+ courseBase.addWaypoint(0, startWP);
170
+ courseBase.addRoleMapping(startBoat, startFinishBoatRole.getId());
171
+ courseBase.addRoleMapping(startPin, startFinishPinRole.getId());
172
+ courseBase.addWaypoint(1, windward1WP);
173
+ courseBase.addRoleMapping(windward, windwardMarkRole.getId());
174
+ courseBase.addWaypoint(2, gate1WP);
175
+ courseBase.addRoleMapping(gatePort, leewardGatePortRole.getId());
176
+ courseBase.addRoleMapping(gateStarboard, leewardGateStarboardRole.getId());
177
+ courseBase.addWaypoint(3, windward2WP);
178
+ courseBase.addWaypoint(4, gate2WP);
179
+ final Integer numberOfLaps = getNumberOfLaps();
180
+ assertNull(numberOfLaps);
181
+ }
182
+
183
+ @Test
184
+ public void testSimpleCourseComplianceWithOneLap() {
185
+ final Waypoint startWP, windward1WP, finishWP;
186
+ // waypoints:
187
+ startWP = new WaypointImpl(startFinishLine, PassingInstruction.Line);
188
+ windward1WP = new WaypointImpl(windward, PassingInstruction.Port);
189
+ finishWP = new WaypointImpl(startFinishLine, PassingInstruction.Line);
190
+ // course:
191
+ courseBase.addWaypoint(0, startWP);
192
+ courseBase.addRoleMapping(startBoat, startFinishBoatRole.getId());
193
+ courseBase.addRoleMapping(startPin, startFinishPinRole.getId());
194
+ courseBase.addWaypoint(1, windward1WP);
195
+ courseBase.addRoleMapping(windward, windwardMarkRole.getId());
196
+ courseBase.addRoleMapping(gatePort, leewardGatePortRole.getId());
197
+ courseBase.addRoleMapping(gateStarboard, leewardGateStarboardRole.getId());
198
+ courseBase.addWaypoint(2, finishWP);
199
+ final Integer numberOfLaps = getNumberOfLaps();
200
+ assertEquals(1, (int) numberOfLaps);
201
+ }
202
+
203
+ private Integer getNumberOfLaps() {
204
+ final CourseTemplateCompatibilityCheckerForCourseBase checker = new CourseAndMarkConfigurationFactoryImpl(
205
+ /* sharedSailingDataTracker */ null, /* sensorFixStore */ null, /* raceLogResolver */ null,
206
+ DomainFactory.INSTANCE).new CourseTemplateCompatibilityCheckerForCourseBase(courseBase,
207
+ windwardLeewardWithLeewardFinishCourseTemplate);
208
+ final Integer numberOfLaps = checker.isCourseInstanceOfCourseTemplate();
209
+ return numberOfLaps;
210
+ }
211
+}
java/com.sap.sailing.server/src/com/sap/sailing/server/impl/CourseAndMarkConfigurationFactoryImpl.java
... ...
@@ -69,7 +69,6 @@ import com.sap.sailing.domain.coursetemplate.MarkTemplateBasedMarkConfiguration;
69 69
import com.sap.sailing.domain.coursetemplate.Positioning;
70 70
import com.sap.sailing.domain.coursetemplate.PositioningVisitor;
71 71
import com.sap.sailing.domain.coursetemplate.RegattaMarkConfiguration;
72
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
73 72
import com.sap.sailing.domain.coursetemplate.TrackingDeviceBasedPositioning;
74 73
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
75 74
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
... ...
@@ -92,6 +91,7 @@ import com.sap.sailing.server.gateway.deserialization.impl.CourseConfigurationBu
92 91
import com.sap.sailing.server.interfaces.CourseAndMarkConfigurationFactory;
93 92
import com.sap.sailing.shared.server.SharedSailingData;
94 93
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
94
+import com.sap.sse.common.RepeatablePart;
95 95
import com.sap.sse.common.TimePoint;
96 96
import com.sap.sse.common.Timed;
97 97
import com.sap.sse.common.TransformationException;
... ...
@@ -995,7 +995,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
995 995
return result;
996 996
}
997 997
998
- private class CourseTemplateCompatibilityCheckerForCourseBase
998
+ class CourseTemplateCompatibilityCheckerForCourseBase
999 999
extends CourseTemplateCompatibilityChecker<CourseBase, Mark, Waypoint> {
1000 1000
public CourseTemplateCompatibilityCheckerForCourseBase(CourseBase course, CourseTemplate courseTemplate) {
1001 1001
super(course, courseTemplate);
... ...
@@ -1173,7 +1173,8 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
1173 1173
*
1174 1174
* Eventually, a list of {@code W} waypoint-like objects is created, one for each
1175 1175
* {@link WaypointWithMarkConfiguration} in the original list provided to the constructor, based on the {@code M}
1176
- * objects to which the mark configurations were mapped.
1176
+ * objects to which the mark configurations were mapped. The list can be found in {@link #effectiveWaypoints} after
1177
+ * the constructor has completed.<p>
1177 1178
*
1178 1179
* @param <CP>
1179 1180
* a control point-like type; something that is one or has two object(s) of type {@code M}.
java/com.sap.sailing.shared.persistence/src/com/sap/sailing/shared/persistence/impl/DomainObjectFactoryImpl.java
... ...
@@ -33,12 +33,10 @@ import com.sap.sailing.domain.coursetemplate.MarkPropertiesBuilder;
33 33
import com.sap.sailing.domain.coursetemplate.MarkRole;
34 34
import com.sap.sailing.domain.coursetemplate.MarkRolePair.MarkRolePairFactory;
35 35
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
36
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
37 36
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
38 37
import com.sap.sailing.domain.coursetemplate.impl.CourseTemplateImpl;
39 38
import com.sap.sailing.domain.coursetemplate.impl.MarkRoleImpl;
40 39
import com.sap.sailing.domain.coursetemplate.impl.MarkTemplateImpl;
41
-import com.sap.sailing.domain.coursetemplate.impl.RepeatablePartImpl;
42 40
import com.sap.sailing.domain.coursetemplate.impl.WaypointTemplateImpl;
43 41
import com.sap.sailing.domain.racelogtracking.impl.PlaceHolderDeviceIdentifierSerializationHandler;
44 42
import com.sap.sailing.shared.persistence.DomainObjectFactory;
... ...
@@ -46,11 +44,13 @@ import com.sap.sailing.shared.persistence.device.DeviceIdentifierMongoHandler;
46 44
import com.sap.sailing.shared.persistence.device.impl.PlaceHolderDeviceIdentifierMongoHandler;
47 45
import com.sap.sse.common.Color;
48 46
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
47
+import com.sap.sse.common.RepeatablePart;
49 48
import com.sap.sse.common.TimePoint;
50 49
import com.sap.sse.common.TypeBasedServiceFinder;
51 50
import com.sap.sse.common.TypeBasedServiceFinderFactory;
52 51
import com.sap.sse.common.impl.AbstractColor;
53 52
import com.sap.sse.common.impl.MillisecondsTimePoint;
53
+import com.sap.sse.common.impl.RepeatablePartImpl;
54 54
import com.sap.sse.common.TransformationException;
55 55
56 56
public class DomainObjectFactoryImpl implements DomainObjectFactory {
java/com.sap.sailing.shared.server/src/com/sap/sailing/shared/server/SharedSailingData.java
... ...
@@ -15,10 +15,10 @@ import com.sap.sailing.domain.coursetemplate.MarkProperties;
15 15
import com.sap.sailing.domain.coursetemplate.MarkRole;
16 16
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
17 17
import com.sap.sailing.domain.coursetemplate.Positioning;
18
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
19 18
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
20 19
import com.sap.sailing.shared.server.impl.ReplicatingSharedSailingData;
21 20
import com.sap.sailing.shared.server.impl.SharedSailingDataImpl;
21
+import com.sap.sse.common.RepeatablePart;
22 22
import com.sap.sse.common.TimePoint;
23 23
import com.sap.sse.common.impl.MillisecondsTimePoint;
24 24
import com.sap.sse.replication.OperationWithResult;
java/com.sap.sailing.shared.server/src/com/sap/sailing/shared/server/impl/ReplicatingSharedSailingData.java
... ...
@@ -9,9 +9,9 @@ import com.sap.sailing.domain.coursetemplate.CommonMarkProperties;
9 9
import com.sap.sailing.domain.coursetemplate.MarkRole;
10 10
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
11 11
import com.sap.sailing.domain.coursetemplate.Positioning;
12
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
13 12
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
14 13
import com.sap.sailing.shared.server.SharedSailingData;
14
+import com.sap.sse.common.RepeatablePart;
15 15
16 16
public interface ReplicatingSharedSailingData extends SharedSailingData {
17 17
java/com.sap.sailing.shared.server/src/com/sap/sailing/shared/server/impl/SharedSailingDataImpl.java
... ...
@@ -27,7 +27,6 @@ import com.sap.sailing.domain.coursetemplate.MarkRole;
27 27
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
28 28
import com.sap.sailing.domain.coursetemplate.MarkTemplate.MarkTemplateResolver;
29 29
import com.sap.sailing.domain.coursetemplate.Positioning;
30
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
31 30
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
32 31
import com.sap.sailing.domain.coursetemplate.impl.CommonMarkPropertiesImpl;
33 32
import com.sap.sailing.domain.coursetemplate.impl.CourseTemplateImpl;
... ...
@@ -50,6 +49,7 @@ import com.sap.sailing.shared.server.operations.RecordUsageForMarkTemplateOperat
50 49
import com.sap.sailing.shared.server.operations.SetPositioningInformationForMarkPropertiesOperation;
51 50
import com.sap.sailing.shared.server.operations.UpdateCourseTemplateOperation;
52 51
import com.sap.sailing.shared.server.operations.UpdateMarkPropertiesOperation;
52
+import com.sap.sse.common.RepeatablePart;
53 53
import com.sap.sse.common.TimePoint;
54 54
import com.sap.sse.common.TypeBasedServiceFinder;
55 55
import com.sap.sse.common.TypeBasedServiceFinderFactory;
java/com.sap.sailing.shared.server/src/com/sap/sailing/shared/server/operations/CreateCourseTemplateOperation.java
... ...
@@ -6,9 +6,9 @@ import java.util.UUID;
6 6
7 7
import com.sap.sailing.domain.coursetemplate.MarkRole;
8 8
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
9
-import com.sap.sailing.domain.coursetemplate.RepeatablePart;
10 9
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
11 10
import com.sap.sailing.shared.server.impl.ReplicatingSharedSailingData;
11
+import com.sap.sse.common.RepeatablePart;
12 12
13 13
public class CreateCourseTemplateOperation implements SharedSailingDataOperation<Void> {
14 14
private static final long serialVersionUID = 5028364832943967084L;
java/com.sap.sse.common/src/com/sap/sse/common/RepeatablePart.java
... ...
@@ -0,0 +1,87 @@
1
+package com.sap.sse.common;
2
+
3
+import java.io.Serializable;
4
+import java.util.ArrayList;
5
+import java.util.List;
6
+
7
+/**
8
+ * Reusable implementation of the semantics for the repeatable part of a course sequence. The sequence is defined by the
9
+ * start and end of the zero-based repeatable part of the complete sequence. The following requirements need to be
10
+ * fulfilled:
11
+ * <ul>
12
+ * <li>The {@link #getZeroBasedIndexOfRepeatablePartStart()} and {@link #getZeroBasedIndexOfRepeatablePartEnd()} are
13
+ * required to be >=0</li>
14
+ * <li>{@link #getZeroBasedIndexOfRepeatablePartStart()} is truly less than {@link #getZeroBasedIndexOfRepeatablePartEnd()}</li>
15
+ * </ul>
16
+ */
17
+public interface RepeatablePart extends Serializable {
18
+ /**
19
+ * The index into {@link #waypoints} of the first waypoint that is to be cloned for repetitive laps.
20
+ */
21
+ int getZeroBasedIndexOfRepeatablePartStart();
22
+
23
+ /**
24
+ * The index into {@link #waypoints} of the first waypoint that comes after the sub-sequence to be cloned for
25
+ * repetitive laps.
26
+ */
27
+ int getZeroBasedIndexOfRepeatablePartEnd();
28
+
29
+ default int length() {
30
+ return getZeroBasedIndexOfRepeatablePartEnd()-getZeroBasedIndexOfRepeatablePartStart();
31
+ }
32
+
33
+ /**
34
+ * Returns a sequence of waypoints (T) that can be use to construct a course. If this course template
35
+ * defines a repeatable waypoint sub-sequence, the {@code numberOfLaps} parameter is used to decide how many times
36
+ * to repeat this sub-sequence. Typically, the repeatable sub-sequence will be repeated one times fewer than the
37
+ * {@code numberOfLaps}. For example, in a typical windward-leeward "L" course we would have
38
+ * {@code Start/Finish, [1, 4p/4s], 1, Start/Finish}. For an "L1" course with only one lap, we'd like to have
39
+ * {@code Start/Finish, 1, Start/Finish}, so the repeatable sub-sequence, enclosed by the brackets in the example
40
+ * above, will occur zero times. For an "L2" the repeatable sub-sequence will occur once, and so on.
41
+ *
42
+ * @throws IllegalArgumentException
43
+ * in case the given {@code sequenceWithRepeatablePart} contains less or equal elements to
44
+ * {@link #getZeroBasedIndexOfRepeatablePartEnd()}.
45
+ */
46
+ default <T> Iterable<T> createSequence(int repetitions, Iterable<T> sequenceWithRepeatablePart) {
47
+ validateRepeatablePartForSequence(sequenceWithRepeatablePart);
48
+ final int zeroBasedIndexOfRepeatablePartStart = getZeroBasedIndexOfRepeatablePartStart();
49
+ final int zeroBasedIndexOfRepeatablePartEnd = getZeroBasedIndexOfRepeatablePartEnd();
50
+ final List<T> sequenceWithRepeatablePartAsList = new ArrayList<>();
51
+ Util.addAll(sequenceWithRepeatablePart, sequenceWithRepeatablePartAsList);
52
+ final int sequenceLength = sequenceWithRepeatablePartAsList.size();
53
+ final List<T> result = new ArrayList<>();
54
+ // Non-repeatable start of the sequence
55
+ for (int i = 0; i < zeroBasedIndexOfRepeatablePartStart; i++) {
56
+ result.add(sequenceWithRepeatablePartAsList.get(i));
57
+ }
58
+ // Repeatable part of the sequence
59
+ for (int lap = 1; lap < repetitions; lap++) {
60
+ for (int i = zeroBasedIndexOfRepeatablePartStart; i < zeroBasedIndexOfRepeatablePartEnd; i++) {
61
+ result.add(sequenceWithRepeatablePartAsList.get(i));
62
+ }
63
+ }
64
+ // Non-repeatable end of the sequence
65
+ for (int i = zeroBasedIndexOfRepeatablePartEnd; i < sequenceLength; i++) {
66
+ result.add(sequenceWithRepeatablePartAsList.get(i));
67
+ }
68
+ return result;
69
+ }
70
+
71
+ /**
72
+ * Validates that this repeatable part is compatible with the given {@code sequenceWithRepeatablePart} and causes an
73
+ * exception in case it isn't.
74
+ *
75
+ * @throws IllegalArgumentException
76
+ * in case the given {@code sequenceWithRepeatablePart} contains less or equal elements to
77
+ * {@link #getZeroBasedIndexOfRepeatablePartEnd()}.
78
+ */
79
+ default <T> void validateRepeatablePartForSequence(Iterable<T> sequenceWithRepeatablePart) {
80
+ final int zeroBasedIndexOfRepeatablePartEnd = getZeroBasedIndexOfRepeatablePartEnd();
81
+ final int sequenceLength = Util.size(sequenceWithRepeatablePart);
82
+ if (sequenceLength < zeroBasedIndexOfRepeatablePartEnd) {
83
+ throw new IllegalArgumentException("Repeatable part (" + getZeroBasedIndexOfRepeatablePartStart() + ", "
84
+ + zeroBasedIndexOfRepeatablePartEnd + ") is out of range for sequence of length " + sequenceLength);
85
+ }
86
+ }
87
+}
java/com.sap.sse.common/src/com/sap/sse/common/Util.java
... ...
@@ -869,7 +869,7 @@ public class Util {
869 869
* Input Iterable
870 870
* @return
871 871
* returns List<T> if {@code iterable} is an instance of List<?> and if it is an instance Serializable. If not,
872
- * an ArrayList<T> gets constructed and filled with all items of {@code iterable}
872
+ * an ArrayList<T> gets constructed and filled with all items of {@code iterable}
873 873
*/
874 874
public static <T> List<T> asList(Iterable<T> iterable) {
875 875
final List<T> list;
java/com.sap.sse.common/src/com/sap/sse/common/WithOptionalRepeatablePart.java
... ...
@@ -0,0 +1,9 @@
1
+package com.sap.sse.common;
2
+
3
+public interface WithOptionalRepeatablePart {
4
+ default boolean hasRepeatablePart() {
5
+ return getRepeatablePart() != null;
6
+ }
7
+
8
+ RepeatablePart getRepeatablePart();
9
+}
java/com.sap.sse.common/src/com/sap/sse/common/impl/RepeatablePartImpl.java
... ...
@@ -0,0 +1,39 @@
1
+package com.sap.sse.common.impl;
2
+
3
+import com.sap.sse.common.RepeatablePart;
4
+
5
+public class RepeatablePartImpl implements RepeatablePart {
6
+ private static final long serialVersionUID = -7432656529810302123L;
7
+
8
+ private final int zeroBasedIndexOfRepeatablePartStart;
9
+
10
+ private final int zeroBasedIndexOfRepeatablePartEnd;
11
+
12
+ public RepeatablePartImpl(int zeroBasedIndexOfRepeatablePartStart, int zeroBasedIndexOfRepeatablePartEnd) {
13
+ super();
14
+ if (zeroBasedIndexOfRepeatablePartStart < 0 || zeroBasedIndexOfRepeatablePartEnd < 0) {
15
+ throw new IllegalArgumentException("No negative indices are possible for the repeatable part.");
16
+ }
17
+ if (zeroBasedIndexOfRepeatablePartStart >= zeroBasedIndexOfRepeatablePartEnd) {
18
+ throw new IllegalArgumentException(
19
+ "The start of the repeatable part needs to be less than the end such that the repeatable part has at least one element.");
20
+ }
21
+ this.zeroBasedIndexOfRepeatablePartStart = zeroBasedIndexOfRepeatablePartStart;
22
+ this.zeroBasedIndexOfRepeatablePartEnd = zeroBasedIndexOfRepeatablePartEnd;
23
+ }
24
+
25
+ @Override
26
+ public int getZeroBasedIndexOfRepeatablePartStart() {
27
+ return zeroBasedIndexOfRepeatablePartStart;
28
+ }
29
+
30
+ @Override
31
+ public int getZeroBasedIndexOfRepeatablePartEnd() {
32
+ return zeroBasedIndexOfRepeatablePartEnd;
33
+ }
34
+
35
+ @Override
36
+ public String toString() {
37
+ return "["+getZeroBasedIndexOfRepeatablePartStart()+".."+getZeroBasedIndexOfRepeatablePartEnd()+"]";
38
+ }
39
+}
wiki/info/landscape/amazon-ec2.md
... ...
@@ -66,7 +66,8 @@ The webserver is registered as target in various locations:
66 66
* As DNS record with its internal IP address (e.g., 172.31.19.129) for the two DNS entries ``logfiles.internal.sapsailing.com`` used by various NFS mounts, and ``smtp.internal.sapsailing.com`` for e-mail traffic sent within the landscape and not requiring the AWS SES
67 67
* as IP target with its internal IP address for the ``HTTP-to-sapsailing-dot-com`` target group, accepting the HTTP traffic sent straight to ``sapsailing.com`` (not ``www.sapsailing.com``)
68 68
* as IP target with its internal IP address for the ``SSH-to-sapsailing-dot-com`` target group, accepting the SSH traffic for ``sapsailing.com``
69
-* as regular instance target in all load balancers' default rule's target group, such as ``DefDynsapsailing-com``, ``DNSMapped-0``, ``DNSMapped-1``, and so on; the names of the target groups are ``CentralWebServerHTTP-Dyn``, ``DDNSMapped-0-HTTP``, ``DDNSMapped-1-HTTP``, and so on, respectively.
69
+* as regular instance target in all load balancers' default rule's target group, such as ``DefDynsapsailing-com``, ``DNSMapped-0``, ``DNSMapped-1``, and so on; the names of the target groups are ``CentralWebServerHTTP-Dyn``, ``DDNSMapped-0-HTTP``, ``DDNSMapped-1-HTTP``, and so on, respectively
70
+* as regular instance target in ``DNSMapped-0``'s target group ``DNSMapped0-Central-HTTP`` to which requests for services available only on the *central* reverse proxy are forwarded to, such as ``releases.sapsailing.com``, ``bugzilla.sapsailing.com``, and so on
70 71
* as target of the elastic IP address ``54.229.94.254``
71 72
72 73
Changing the DNS entry especially for ``logfiles.internal.sapsailing.com`` requires re-mounting those NFS shares wherever they were used. Go to at least all instances tagged with ``sailing-analytics-server`` and, as user ``root``, execute the following commands: