f0ab97bac5eaf0d3300aa8dade40fcfc8251c027
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: |