configuration/sailing
... ...
@@ -4,6 +4,18 @@
4 4
#
5 5
# chkconfig: 2345 95 10
6 6
# description: Sailing contains all sailing services
7
+#
8
+### BEGIN INIT INFO
9
+# Provides: sailing
10
+# Required-Start: $local_fs $network $named $remote_fs
11
+# Should-Start:
12
+# Required-Stop:
13
+# Should-Stop:
14
+# Default-Start: 2 3 4 5
15
+# Default-Stop: 0 1 6
16
+# Short-Description: The sailing service
17
+# Description: Start all sailing services required for this instance
18
+### END INIT INFO
7 19
8 20
# Source function library.
9 21
. /etc/init.d/functions
... ...
@@ -14,8 +26,8 @@ JAVA_START_INSTANCES="server"
14 26
SERVERS_DIR=/home/sailing/servers
15 27
GIT_REPOSITORY=/home/sailing/code
16 28
APACHE_CONFIG_DIR=/etc/httpd/conf.d
17
-rm /var/log/sailing.out
18
-rm /var/log/sailing.err
29
+
30
+echo "Executing with $1" >>/var/log/sailing.out
19 31
20 32
start_tmux() {
21 33
su - sailing -c "/home/sailing/bin/tmuxConsole.sh unattended"
... ...
@@ -63,13 +75,21 @@ start_servers() {
63 75
64 76
stop_servers() {
65 77
for conf in $JAVA_START_INSTANCES; do
66
- echo "Stopping Java server $conf"
78
+ echo "Stopping Java server $conf" >> /var/log/sailing.out
67 79
su - sailing -c "cd $SERVERS_DIR/$conf && ./stop"
68 80
RETVAL=$?
69 81
[ $RETVAL -eq 0 ] && success || failure
82
+ stop_httpd
83
+ sync_logs
70 84
done
71 85
}
72 86
87
+sync_logs() {
88
+ echo "Executing logrotate followed by a sync to ensure that logs are synchronized" >> /var/log/sailing.out
89
+ logrotate -f /etc/logrotate.conf
90
+ sync
91
+}
92
+
73 93
# launch_httpd(server_name, port, event_id)
74 94
launch_httpd() {
75 95
echo "Will try to launch httpd so this replica can work with an ELB easily." >>/var/log/sailing.out
... ...
@@ -78,7 +98,7 @@ launch_httpd() {
78 98
source $SERVERS_DIR/$FIRST_SERVER/env.sh
79 99
# Append Apache macro invocation for /internal-server-status based on mod_status and INSTANCE_DNS to $APACHE_CONFIG_DIR/001-events.conf
80 100
echo "Appending macro usage for $INSTANCE_DNS/internal-server-status URL for mod_status based Apache monitoring to $APACHE_CONFIG_DIR/001-events.conf" >>/var/log/sailing.out
81
- echo "## SERVER STATUS" >>$APACHE_CONFIG_DIR/001-events.conf
101
+ echo "## SERVER STATUS" >>$APACHE_CONFIG_DIR/001-events.conf
82 102
echo "Use Status $INSTANCE_DNS internal-server-status" >>$APACHE_CONFIG_DIR/001-events.conf
83 103
echo "Launching httpd..." >>/var/log/sailing.out
84 104
service httpd start
... ...
@@ -87,13 +107,23 @@ launch_httpd() {
87 107
fi
88 108
}
89 109
110
+stop_httpd() {
111
+ if [ -x /etc/init.d/httpd ]; then
112
+ service httpd stop
113
+ echo "Stopped httpd..." >>/var/log/sailing.out
114
+ fi
115
+}
116
+
90 117
# See how we were called.
91 118
case "$1" in
92 119
start)
120
+ /usr/sbin/update-motd
93 121
start_servers
122
+ touch /var/lock/subsys/sailing
94 123
;;
95 124
stop)
96 125
stop_servers
126
+ rm -f /var/lock/subsys/sailing
97 127
;;
98 128
status)
99 129
status java
java/com.sap.sailing.dashboards.gwt/.project
... ...
@@ -21,16 +21,6 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
25
- <arguments>
26
- </arguments>
27
- </buildCommand>
28
- <buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
30
- <arguments>
31
- </arguments>
32
- </buildCommand>
33
- <buildCommand>
34 24
<name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
35 25
<arguments>
36 26
</arguments>
... ...
@@ -44,7 +34,6 @@
44 34
<natures>
45 35
<nature>org.eclipse.pde.PluginNature</nature>
46 36
<nature>org.eclipse.jdt.core.javanature</nature>
47
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
48 37
<nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
49 38
</natures>
50 39
</projectDescription>
java/com.sap.sailing.dashboards.gwt/GWT Dashboards DevMode.launch
... ...
@@ -1,103 +1,47 @@
1 1
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 2
<launchConfiguration type="com.gwtplugins.gdt.eclipse.suite.webapp">
3
-<booleanAttribute key="com.gwtplugins.gdt.eclipse.core.RUN_SERVER" value="false"/>
4
-<stringAttribute key="com.gwtplugins.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.DevMode"/>
5
-<booleanAttribute key="com.gwtplugins.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
6
-<stringAttribute key="com.gwtplugins.gwt.eclipse.core.CLASSIC_DEVMODE_CODE_SERVER_PORT" value="9876"/>
7
-<stringAttribute key="com.gwtplugins.gwt.eclipse.core.URL" value="/security/ui/Login.html"/>
8
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
9
-<listEntry value="/com.sap.sailing.dashboards.gwt"/>
10
-</listAttribute>
11
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
12
-<listEntry value="4"/>
13
-</listAttribute>
14
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
15
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
16
-<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
17
-</listAttribute>
18
-<booleanAttribute key="org.eclipse.jdt.debug.ui.CONSIDER_INHERITED_MAIN" value="true"/>
19
-<booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
20
-<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
21
-<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
22
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
23
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
24
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
25
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
26
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
27
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.shared.android/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
28
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
29
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
30
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.annotations/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
31
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
32
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
33
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.shared.android/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
34
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
35
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
36
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
37
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
38
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
39
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
40
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
41
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
42
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
43
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
44
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server.gateway.serialization.shared.android/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
45
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
46
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
47
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
48
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.filestorage/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
49
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.filestorage/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
50
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
51
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
52
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
53
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
54
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
55
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server.gateway.serialization/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
56
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.simulator/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
57
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.simulator/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
58
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
59
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.tractrac.clientmodule/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
60
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
61
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
62
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.mail/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
63
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
64
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.xrr.resultimport/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
65
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.resultimport/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
66
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.competitorimport/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
67
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.xrr.schema/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
68
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
69
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
70
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
71
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.freg.resultimport/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
72
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingreplayadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
73
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.igtimiadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
74
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.igtimiadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
75
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
76
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
77
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
78
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
79
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
80
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining.provider/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
81
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.racelogtrackingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
82
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.racelogtrackingadapter/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
83
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.manage2sail/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
84
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.manage2sail/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
85
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.xrr.structureimport/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
86
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
87
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
88
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
89
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.news/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
90
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.polars.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
91
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.polars.datamining/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
92
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.polars.datamining/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
93
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
94
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry path=&quot;3&quot; projectName=&quot;com.sap.sse.common&quot; type=&quot;1&quot;/&gt;&#10;"/>
95
-</listAttribute>
96
-<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.gwtplugins.gwt.eclipse.core.moduleClasspathProvider"/>
97
-<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
98
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
99
-<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -startupUrl /security/ui/Login.html -logLevel INFO -noserver -incremental -workDir &quot;${project_loc:com.sap.sse.security.ui}/.tmp/gwt-work&quot; -war &quot;${project_loc:com.sap.sse.security.ui}&quot; -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -codeServerPort 9876 com.sap.sailing.dashboards.gwt.RibDashboard -startupUrl /dashboards/RibDashboard.html com.sap.sailing.dashboards.gwt.RibDashboard"/>
100
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.dashboards.gwt"/>
101
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+UseG1GC -XX:+UseStringDeduplication -Dgwt.watchFileChanges=false -Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
102
-<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work"/>
3
+ <booleanAttribute key="com.gwtplugins.gdt.eclipse.core.RUN_SERVER" value="false"/>
4
+ <stringAttribute key="com.gwtplugins.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.DevMode"/>
5
+ <booleanAttribute key="com.gwtplugins.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
6
+ <stringAttribute key="com.gwtplugins.gwt.eclipse.core.CLASSIC_DEVMODE_CODE_SERVER_PORT" value="9875"/>
7
+ <listAttribute key="com.gwtplugins.gwt.eclipse.core.ENTRY_POINT_MODULES">
8
+ <listEntry value="com.sap.sailing.dashboards.gwt.RibDashboard"/>
9
+ </listAttribute>
10
+ <stringAttribute key="com.gwtplugins.gwt.eclipse.core.URL" value="/security/ui/Login.html"/>
11
+ <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
12
+ <listEntry value="/com.sap.sailing.dashboards.gwt"/>
13
+ </listAttribute>
14
+ <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
15
+ <listEntry value="4"/>
16
+ </listAttribute>
17
+ <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
18
+ <listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
19
+ <listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
20
+ </listAttribute>
21
+ <booleanAttribute key="org.eclipse.jdt.debug.ui.CONSIDER_INHERITED_MAIN" value="true"/>
22
+ <booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
23
+ <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
24
+ <listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
25
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
26
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
27
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
28
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.dashboards.gwt/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
29
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
30
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
31
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
32
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
33
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10; &lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.dashboards.gwt&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
34
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
35
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
36
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
37
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
38
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
39
+ </listAttribute>
40
+ <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.gwtplugins.gwt.eclipse.core.moduleClasspathProvider"/>
41
+ <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
42
+ <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
43
+ <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -startupUrl /security/ui/Login.html -logLevel INFO -noserver -incremental -war &quot;${project_loc:com.sap.sailing.dashboards.gwt}&quot; -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -codeServerPort 9875 -startupUrl /dashboards/RibDashboard.html com.sap.sailing.dashboards.gwt.RibDashboard"/>
44
+ <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.dashboards.gwt"/>
45
+ <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+UseG1GC -XX:+UseStringDeduplication -Dgwt.watchFileChanges=false -Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
46
+ <stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work"/>
103 47
</launchConfiguration>
java/com.sap.sailing.dashboards.gwt/GWT Dashboards SDM.launch
... ...
@@ -1,46 +1,48 @@
1 1
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 2
<launchConfiguration type="com.gwtplugins.gdt.eclipse.suite.webapp">
3
-<booleanAttribute key="com.gwtplugins.gdt.eclipse.core.RUN_SERVER" value="false"/>
4
-<stringAttribute key="com.gwtplugins.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.DevMode"/>
5
-<booleanAttribute key="com.gwtplugins.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
6
-<stringAttribute key="com.gwtplugins.gwt.eclipse.core.CLASSIC_DEVMODE_CODE_SERVER_PORT" value="9876"/>
7
-<listAttribute key="com.gwtplugins.gwt.eclipse.core.ENTRY_POINT_MODULES">
8
-<listEntry value="com.sap.sailing.dashboards.gwt.RibDashboard"/>
9
-</listAttribute>
10
-<booleanAttribute key="com.gwtplugins.gwt.eclipse.core.SUPERDEVMODE_ENABLED" value="true"/>
11
-<stringAttribute key="com.gwtplugins.gwt.eclipse.core.URL" value="/security/ui/Login.html"/>
12
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
13
-<listEntry value="/com.sap.sailing.dashboards.gwt"/>
14
-</listAttribute>
15
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
16
-<listEntry value="4"/>
17
-</listAttribute>
18
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
19
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
20
-<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
21
-</listAttribute>
22
-<booleanAttribute key="org.eclipse.jdt.debug.ui.CONSIDER_INHERITED_MAIN" value="true"/>
23
-<booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
24
-<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
25
-<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
26
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
27
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
28
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
29
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.dashboards.gwt/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
30
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
31
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
32
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
33
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
34
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.dashboards.gwt&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
35
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
36
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
37
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
38
-</listAttribute>
39
-<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.gwtplugins.gwt.eclipse.core.moduleClasspathProvider"/>
40
-<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
41
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
42
-<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-startupUrl /security/ui/Login.html -logLevel INFO -noserver -incremental -war &quot;${project_loc:com.sap.sailing.dashboards.gwt}&quot; -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -codeServerPort 9876 com.sap.sailing.dashboards.gwt.RibDashboard -startupUrl /dashboards/RibDashboard.html com.sap.sailing.dashboards.gwt.RibDashboard"/>
43
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.dashboards.gwt"/>
44
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+UseG1GC -XX:+UseStringDeduplication -Dgwt.watchFileChanges=false -Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
45
-<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work"/>
3
+ <booleanAttribute key="com.gwtplugins.gdt.eclipse.core.RUN_SERVER" value="false"/>
4
+ <stringAttribute key="com.gwtplugins.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.DevMode"/>
5
+ <booleanAttribute key="com.gwtplugins.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
6
+ <stringAttribute key="com.gwtplugins.gwt.eclipse.core.CLASSIC_DEVMODE_CODE_SERVER_PORT" value="9875"/>
7
+ <listAttribute key="com.gwtplugins.gwt.eclipse.core.ENTRY_POINT_MODULES">
8
+ <listEntry value="com.sap.sailing.dashboards.gwt.RibDashboard"/>
9
+ </listAttribute>
10
+ <booleanAttribute key="com.gwtplugins.gwt.eclipse.core.SUPERDEVMODE_ENABLED" value="true"/>
11
+ <stringAttribute key="com.gwtplugins.gwt.eclipse.core.URL" value="/security/ui/Login.html"/>
12
+ <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
13
+ <listEntry value="/com.sap.sailing.dashboards.gwt"/>
14
+ </listAttribute>
15
+ <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
16
+ <listEntry value="4"/>
17
+ </listAttribute>
18
+ <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
19
+ <listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
20
+ <listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
21
+ </listAttribute>
22
+ <booleanAttribute key="org.eclipse.jdt.debug.ui.CONSIDER_INHERITED_MAIN" value="true"/>
23
+ <booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
24
+ <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
25
+ <listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
26
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
27
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
28
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
29
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.dashboards.gwt/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
30
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
31
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
32
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
33
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
34
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10; &lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.dashboards.gwt&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
35
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
36
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
37
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
38
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
39
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
40
+ </listAttribute>
41
+ <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.gwtplugins.gwt.eclipse.core.moduleClasspathProvider"/>
42
+ <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
43
+ <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
44
+ <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-startupUrl /security/ui/Login.html -logLevel INFO -noserver -incremental -war &quot;${project_loc:com.sap.sailing.dashboards.gwt}&quot; -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -codeServerPort 9875 -startupUrl /dashboards/RibDashboard.html com.sap.sailing.dashboards.gwt.RibDashboard"/>
45
+ <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.dashboards.gwt"/>
46
+ <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+UseG1GC -XX:+UseStringDeduplication -Dgwt.watchFileChanges=false -Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
47
+ <stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work"/>
46 48
</launchConfiguration>
java/com.sap.sailing.datamining.shared/.project
... ...
@@ -21,12 +21,12 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
24
+ <name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
25 25
<arguments>
26 26
</arguments>
27 27
</buildCommand>
28 28
<buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
29
+ <name>com.gwtplugins.gwt.eclipse.core.gwtProjectValidator</name>
30 30
<arguments>
31 31
</arguments>
32 32
</buildCommand>
... ...
@@ -34,6 +34,6 @@
34 34
<natures>
35 35
<nature>org.eclipse.pde.PluginNature</nature>
36 36
<nature>org.eclipse.jdt.core.javanature</nature>
37
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
37
+ <nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
38 38
</natures>
39 39
</projectDescription>
java/com.sap.sailing.datamining.test/src/com/sap/sailing/datamining/impl/components/TestLeaderboardGroupRetrievalProcessor.java
... ...
@@ -15,7 +15,7 @@ import org.junit.Before;
15 15
import org.junit.Ignore;
16 16
import org.junit.Test;
17 17
18
-import com.sap.sailing.datamining.impl.data.LeaderboardGroupWithContext;
18
+import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
19 19
import com.sap.sailing.datamining.test.util.ConcurrencyTestsUtil;
20 20
import com.sap.sailing.datamining.test.util.NullProcessor;
21 21
import com.sap.sailing.domain.leaderboard.Leaderboard;
... ...
@@ -27,7 +27,7 @@ import com.sap.sse.datamining.components.Processor;
27 27
public class TestLeaderboardGroupRetrievalProcessor {
28 28
29 29
private RacingEventService service;
30
- private Processor<RacingEventService, LeaderboardGroupWithContext> retriever;
30
+ private Processor<RacingEventService, HasLeaderboardGroupContext> retriever;
31 31
32 32
private Collection<LeaderboardGroup> retrievedGroups;
33 33
... ...
@@ -37,14 +37,14 @@ public class TestLeaderboardGroupRetrievalProcessor {
37 37
stub(service.getLeaderboardGroups()).toReturn(getGroupsInService());
38 38
39 39
retrievedGroups = new HashSet<>();
40
- Processor<LeaderboardGroupWithContext, Void> receiver = new NullProcessor<LeaderboardGroupWithContext, Void>(LeaderboardGroupWithContext.class, Void.class) {
40
+ Processor<HasLeaderboardGroupContext, Void> receiver = new NullProcessor<HasLeaderboardGroupContext, Void>(HasLeaderboardGroupContext.class, Void.class) {
41 41
@Override
42
- public void processElement(LeaderboardGroupWithContext element) {
42
+ public void processElement(HasLeaderboardGroupContext element) {
43 43
retrievedGroups.add(element.getLeaderboardGroup());
44 44
}
45 45
};
46 46
47
- Collection<Processor<LeaderboardGroupWithContext, ?>> resultReceivers = new ArrayList<>();
47
+ Collection<Processor<HasLeaderboardGroupContext, ?>> resultReceivers = new ArrayList<>();
48 48
resultReceivers.add(receiver);
49 49
retriever = new LeaderboardGroupRetrievalProcessor(ConcurrencyTestsUtil.getExecutor(), resultReceivers, 0);
50 50
}
java/com.sap.sailing.datamining/.project
... ...
@@ -21,18 +21,19 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
24
+ <name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
25 25
<arguments>
26 26
</arguments>
27 27
</buildCommand>
28 28
<buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
29
+ <name>com.gwtplugins.gwt.eclipse.core.gwtProjectValidator</name>
30 30
<arguments>
31 31
</arguments>
32
- </buildCommand> </buildSpec>
32
+ </buildCommand>
33
+ </buildSpec>
33 34
<natures>
34 35
<nature>org.eclipse.pde.PluginNature</nature>
35 36
<nature>org.eclipse.jdt.core.javanature</nature>
36
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
37
+ <nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
37 38
</natures>
38 39
</projectDescription>
java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages.properties
... ...
@@ -188,7 +188,7 @@ AbsRelativeBearingToNextMarkAfterManeuver=Abs. relative bearing to the next mark
188 188
RatioBetweenDistanceSailedWithAndWithoutManeuver=Ratio between distance sailed with and without maneuver
189 189
RatioBetweenDistanceSailedTowardMiddleAngleProjectionWithAndWithoutManeuver=Ratio between distance sailed toward middle angle projection with and without maneuver
190 190
DurationLostByManeuver=Duration lost by maneuver
191
-DurationLostByManeuverTowardMiddleAngleProjection=duration lost by maneuver toward middle angle projection
191
+DurationLostByManeuverTowardMiddleAngleProjection=Duration lost by maneuver toward middle angle projection
192 192
JibingCount=Jibing count
193 193
TackingCount=Tacking count
194 194
AbsTwaAtMaxTurningRate=Abs. TWA at max. turning rate
... ...
@@ -198,4 +198,5 @@ PercentageOfMainCurveProgressUntilLowestSpeed=Percentage of main curve progress
198 198
PercentageOfMainCurveProgressUntilHighestSpeed=Percentage of main curve progress until highest speed
199 199
PercentageOfMainCurveProgressUntilMaxTurningRate=Percentage of main curve progress until max. turning rate speed
200 200
AbsTwaAtManeuverMiddle=Abs. TWA at maneuver middle
201
-GpsSamplingRate=GPS sampling rate
... ...
\ No newline at end of file
0
+GpsSamplingRate=GPS sampling rate
1
+RaceDuration=Race duration
... ...
\ No newline at end of file
java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_de.properties
... ...
@@ -201,4 +201,5 @@ PercentageOfMainCurveProgressUntilHighestSpeed=Prozentualer Fortschritt der Haup
201 201
PercentageOfMainCurveProgressUntilMaxTurningRate=Prozentualer Fortschritt der Hauptkurve bis zum Erreichen von max. Drehrate
202 202
ManeuverTypeForCompleteManeuverCurve=Manövertyp für komplette Manöverkurve
203 203
AbsTwaAtManeuverMiddle=Abs. TWA während Manövermitte
204
-GpsSamplingRate=GPS-Samplingrate
... ...
\ No newline at end of file
0
+GpsSamplingRate=GPS-Samplingrate
1
+RaceDuration=Renndauer
... ...
\ No newline at end of file
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/SailingDataRetrievalChainDefinitions.java
... ...
@@ -5,12 +5,13 @@ import java.util.Collection;
5 5
6 6
import com.sap.sailing.datamining.data.HasBravoFixContext;
7 7
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
8
+import com.sap.sailing.datamining.data.HasCompleteManeuverCurveWithEstimationDataContext;
8 9
import com.sap.sailing.datamining.data.HasFoilingSegmentContext;
9 10
import com.sap.sailing.datamining.data.HasGPSFixContext;
10 11
import com.sap.sailing.datamining.data.HasLeaderboardContext;
12
+import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
11 13
import com.sap.sailing.datamining.data.HasManeuverContext;
12 14
import com.sap.sailing.datamining.data.HasManeuverSpeedDetailsContext;
13
-import com.sap.sailing.datamining.data.HasCompleteManeuverCurveWithEstimationDataContext;
14 15
import com.sap.sailing.datamining.data.HasMarkPassingContext;
15 16
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
16 17
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
... ...
@@ -22,13 +23,13 @@ import com.sap.sailing.datamining.data.HasWindTrackContext;
22 23
import com.sap.sailing.datamining.impl.components.BravoFixRetrievalProcessor;
23 24
import com.sap.sailing.datamining.impl.components.BravoFixTrackRetrievalProcessor;
24 25
import com.sap.sailing.datamining.impl.components.CompetitorOfRaceInLeaderboardRetrievalProcessor;
26
+import com.sap.sailing.datamining.impl.components.CompleteManeuverCurveWithEstimationDataRetrievalProcessor;
25 27
import com.sap.sailing.datamining.impl.components.FoilingSegmentRetrievalProcessor;
26 28
import com.sap.sailing.datamining.impl.components.GPSFixRetrievalProcessor;
27 29
import com.sap.sailing.datamining.impl.components.LeaderboardGroupRetrievalProcessor;
28 30
import com.sap.sailing.datamining.impl.components.LeaderboardRetrievalProcessor;
29 31
import com.sap.sailing.datamining.impl.components.ManeuverRetrievalProcessor;
30 32
import com.sap.sailing.datamining.impl.components.ManeuverSpeedDetailsRetrievalProcessor;
31
-import com.sap.sailing.datamining.impl.components.CompleteManeuverCurveWithEstimationDataRetrievalProcessor;
32 33
import com.sap.sailing.datamining.impl.components.MarkPassingRetrievalProcessor;
33 34
import com.sap.sailing.datamining.impl.components.RaceOfCompetitorRetrievalProcessor;
34 35
import com.sap.sailing.datamining.impl.components.TrackedLegOfCompetitorRetrievalProcessor;
... ...
@@ -36,7 +37,6 @@ import com.sap.sailing.datamining.impl.components.TrackedLegRetrievalProcessor;
36 37
import com.sap.sailing.datamining.impl.components.TrackedRaceRetrievalProcessor;
37 38
import com.sap.sailing.datamining.impl.components.WindFixRetrievalProcessor;
38 39
import com.sap.sailing.datamining.impl.components.WindTrackRetrievalProcessor;
39
-import com.sap.sailing.datamining.impl.data.LeaderboardGroupWithContext;
40 40
import com.sap.sailing.datamining.shared.FoilingSegmentsDataMiningSettings;
41 41
import com.sap.sailing.datamining.shared.ManeuverSettings;
42 42
import com.sap.sailing.datamining.shared.ManeuverSettingsImpl;
... ...
@@ -55,7 +55,7 @@ public class SailingDataRetrievalChainDefinitions {
55 55
56 56
final DataRetrieverChainDefinition<RacingEventService, HasLeaderboardContext> leaderboardRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
57 57
RacingEventService.class, HasLeaderboardContext.class, "LeaderboardSailingDomainRetrieverChain");
58
- leaderboardRetrieverChainDefinition.startWith(LeaderboardGroupRetrievalProcessor.class, LeaderboardGroupWithContext.class, "LeaderboardGroup");
58
+ leaderboardRetrieverChainDefinition.startWith(LeaderboardGroupRetrievalProcessor.class, HasLeaderboardGroupContext.class, "LeaderboardGroup");
59 59
leaderboardRetrieverChainDefinition.endWith(LeaderboardGroupRetrievalProcessor.class, LeaderboardRetrievalProcessor.class,
60 60
HasLeaderboardContext.class, "Leaderboard");
61 61
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/data/HasBravoFixContext.java
... ...
@@ -16,7 +16,7 @@ public interface HasBravoFixContext {
16 16
@Connector(ordinal=1)
17 17
BravoFix getBravoFix();
18 18
19
- @Connector(messageKey="Speed")
19
+ @Connector(messageKey="")
20 20
SpeedWithBearing getSpeed();
21 21
22 22
@Connector(messageKey="Wind")
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/data/HasLeaderboardContext.java
... ...
@@ -2,7 +2,6 @@ package com.sap.sailing.datamining.data;
2 2
3 3
import com.sap.sailing.domain.base.BoatClass;
4 4
import com.sap.sailing.domain.leaderboard.Leaderboard;
5
-import com.sap.sailing.domain.polars.PolarDataService;
6 5
import com.sap.sse.datamining.annotations.Connector;
7 6
import com.sap.sse.datamining.annotations.Dimension;
8 7
... ...
@@ -12,8 +11,6 @@ public interface HasLeaderboardContext {
12 11
13 12
Leaderboard getLeaderboard();
14 13
15
- PolarDataService getPolarDataService();
16
-
17 14
@Dimension(messageKey="Leaderboard", ordinal=1)
18 15
String getName();
19 16
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/data/HasRaceOfCompetitorContext.java
... ...
@@ -4,6 +4,7 @@ import com.sap.sailing.domain.base.Competitor;
4 4
import com.sap.sailing.domain.common.NoWindException;
5 5
import com.sap.sailing.domain.common.Tack;
6 6
import com.sap.sse.common.Distance;
7
+import com.sap.sse.common.Duration;
7 8
import com.sap.sse.common.Util.Pair;
8 9
import com.sap.sse.common.Speed;
9 10
import com.sap.sse.datamining.annotations.Connector;
... ...
@@ -14,74 +15,74 @@ import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
14 15
public interface HasRaceOfCompetitorContext {
15 16
16 17
@Connector(scanForStatistics=false)
17
- public HasTrackedRaceContext getTrackedRaceContext();
18
+ HasTrackedRaceContext getTrackedRaceContext();
18 19
19 20
@Connector(messageKey="Competitor")
20
- @Statistic(messageKey="")
21
- public Competitor getCompetitor();
21
+ @Statistic(messageKey="Competitor")
22
+ Competitor getCompetitor();
22 23
23 24
@Dimension(messageKey="TackAtStart", ordinal=12)
24
- public Tack getTackAtStart() throws NoWindException;
25
+ Tack getTackAtStart() throws NoWindException;
25 26
26 27
@Dimension(messageKey="DistanceToStarboardSideAtStartOfCompetitor", ordinal=13)
27
- public ClusterDTO getPercentageClusterForDistanceToStarboardSideAtStart();
28
+ ClusterDTO getPercentageClusterForDistanceToStarboardSideAtStart();
28 29
29 30
@Dimension(messageKey="RelativeScoreInPercent", ordinal=14)
30
- public ClusterDTO getPercentageClusterForRelativeScore();
31
+ ClusterDTO getPercentageClusterForRelativeScore();
31 32
32 33
@Statistic(messageKey="DistanceAtStart", resultDecimals=2, ordinal=0)
33
- public Distance getDistanceToStartLineAtStart();
34
+ Distance getDistanceToStartLineAtStart();
34 35
35 36
@Statistic(messageKey="DistanceToStarboardSideAtStartOfCompetitor", resultDecimals=2, ordinal=1)
36
- public Double getNormalizedDistanceToStarboardSideAtStartOfCompetitor();
37
+ Double getNormalizedDistanceToStarboardSideAtStartOfCompetitor();
37 38
38 39
@Statistic(messageKey="DistanceToStarboardSideAtStartOfCompetitorVsRankAtFirstMark", resultDecimals=2, ordinal=1)
39
- public Pair<Double, Double> getNormalizedDistanceToStarboardSideAtStartOfCompetitorVsRankAtFirstMark();
40
+ Pair<Double, Double> getNormalizedDistanceToStarboardSideAtStartOfCompetitorVsRankAtFirstMark();
40 41
41 42
@Statistic(messageKey="WindwardDistanceToAdvantageousEndOfLineAtStartOfRace", resultDecimals=2, ordinal=2)
42
- public Distance getWindwardDistanceToAdvantageousLineEndAtStartofRace();
43
+ Distance getWindwardDistanceToAdvantageousLineEndAtStartofRace();
43 44
44 45
@Statistic(messageKey="WindwardDistanceToAdvantageousEndOfLineAtStartOfCompetitor", resultDecimals=2, ordinal=2)
45
- public Distance getWindwardDistanceToAdvantageousLineEndAtStartofCompetitor();
46
+ Distance getWindwardDistanceToAdvantageousLineEndAtStartofCompetitor();
46 47
47 48
@Connector(messageKey="SpeedWhenStarting", ordinal=3)
48
- public Speed getSpeedWhenStarting();
49
+ Speed getSpeedWhenStarting();
49 50
50 51
@Connector(messageKey="SpeedTenSecondsBeforeStart", ordinal=4)
51
- public Speed getSpeedTenSecondsBeforeStart();
52
+ Speed getSpeedTenSecondsBeforeStart();
52 53
53 54
@Connector(messageKey="SpeedTenSecondsAfterStart", ordinal=5)
54
- public Speed getSpeedTenSecondsAfterStartOfRace();
55
+ Speed getSpeedTenSecondsAfterStartOfRace();
55 56
56 57
@Statistic(messageKey="RankThirtySecondsAfterStart", resultDecimals=2, ordinal=6)
57
- public Double getRankThirtySecondsAfterStartOfRace();
58
+ Double getRankThirtySecondsAfterStartOfRace();
58 59
59 60
@Statistic(messageKey="RankAfterHalfOfTheFirstLeg", resultDecimals=2, ordinal=7)
60
- public Double getRankAfterHalfOfTheFirstLeg();
61
+ Double getRankAfterHalfOfTheFirstLeg();
61 62
62 63
@Statistic(messageKey="RankAtFirstMark", resultDecimals=2, ordinal=8)
63
- public Double getRankAtFirstMark();
64
+ Double getRankAtFirstMark();
64 65
65 66
@Statistic(messageKey="RankGainsOrLossesBetweenFirstMarkAndFinish", resultDecimals=2, ordinal=9)
66
- public Double getRankGainsOrLossesBetweenFirstMarkAndFinish();
67
+ Double getRankGainsOrLossesBetweenFirstMarkAndFinish();
67 68
68 69
@Statistic(messageKey="NumberOfManeuvers", resultDecimals=0, ordinal=10)
69
- public int getNumberOfManeuvers();
70
+ int getNumberOfManeuvers();
70 71
71 72
@Statistic(messageKey="NumberOfTacks", resultDecimals=0, ordinal=11)
72
- public int getNumberOfTacks();
73
+ int getNumberOfTacks();
73 74
74 75
@Statistic(messageKey="NumberOfJibes", resultDecimals=0, ordinal=12)
75
- public int getNumberOfJibes();
76
+ int getNumberOfJibes();
76 77
77 78
@Statistic(messageKey="NumberOfPenaltyCircles", resultDecimals=0, ordinal=13)
78
- public int getNumberOfPenaltyCircles();
79
+ int getNumberOfPenaltyCircles();
79 80
80 81
@Statistic(messageKey="DistanceTraveled", resultDecimals=1)
81
- public Distance getDistanceTraveled();
82
+ Distance getDistanceTraveled();
82 83
83 84
@Statistic(messageKey="LineLengthAtStart", resultDecimals=1)
84
- public Distance getLineLengthAtStart();
85
+ Distance getLineLengthAtStart();
85 86
86 87
@Statistic(messageKey="AbsoluteWindwardDistanceToStarboardSideAtStartOfCompetitor", resultDecimals=2)
87 88
Distance getAbsoluteWindwardDistanceToStarboardSideAtStartOfCompetitor();
... ...
@@ -94,4 +95,8 @@ public interface HasRaceOfCompetitorContext {
94 95
95 96
@Statistic(messageKey="RelativeDistanceToAdvantageousEndOfLineAtStartOfRace", resultDecimals=2)
96 97
Double getRelativeDistanceToAdvantageousEndOfLineAtStartOfRace();
98
+
99
+ @Statistic(messageKey="RaceDuration")
100
+ Duration getDuration();
101
+
97 102
}
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/data/HasTrackedRaceContext.java
... ...
@@ -8,6 +8,7 @@ import com.sap.sailing.domain.base.RaceDefinition;
8 8
import com.sap.sailing.domain.base.Regatta;
9 9
import com.sap.sailing.domain.common.NauticalSide;
10 10
import com.sap.sailing.domain.tracking.TrackedRace;
11
+import com.sap.sse.common.Duration;
11 12
import com.sap.sse.datamining.annotations.Connector;
12 13
import com.sap.sse.datamining.annotations.Dimension;
13 14
import com.sap.sse.datamining.annotations.Statistic;
... ...
@@ -46,10 +47,13 @@ public interface HasTrackedRaceContext {
46 47
@Dimension(messageKey="IsTracked", ordinal=9)
47 48
public Boolean isTracked();
48 49
49
- @Statistic(messageKey="NumberOfCompetitorFixes", resultDecimals=0, ordinal=0)
50
+ @Statistic(messageKey="RaceDuration", ordinal=0)
51
+ public Duration getDuration();
52
+
53
+ @Statistic(messageKey="NumberOfCompetitorFixes", resultDecimals=0, ordinal=1)
50 54
public int getNumberOfCompetitorFixes();
51 55
52
- @Statistic(messageKey="NumberOfMarkFixes", resultDecimals=0, ordinal=1)
56
+ @Statistic(messageKey="NumberOfMarkFixes", resultDecimals=0, ordinal=2)
53 57
public int getNumberOfMarkFixes();
54 58
55 59
// Convenience methods for race dependent calculation to avoid code duplication
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/data/HasWindFixContext.java
... ...
@@ -11,7 +11,7 @@ public interface HasWindFixContext extends HasWind {
11 11
@Connector(scanForStatistics=false)
12 12
public HasTrackedRaceContext getTrackedRaceContext();
13 13
14
- @Statistic(messageKey="", ordinal=0)
14
+ @Statistic(messageKey="WindFix", ordinal=0)
15 15
public Wind getWind();
16 16
17 17
@Statistic(messageKey="windFrom", resultDecimals=1, ordinal=1)
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/BravoFixRetrievalProcessor.java
... ...
@@ -24,21 +24,24 @@ public class BravoFixRetrievalProcessor extends AbstractRetrievalProcessor<HasTr
24 24
@Override
25 25
protected Iterable<HasBravoFixContext> retrieveData(HasTrackedLegOfCompetitorContext element) {
26 26
Collection<HasBravoFixContext> bravoFixesWithContext = new ArrayList<>();
27
- BravoFixTrack<Competitor> bravoFixTrack = element.getTrackedLegContext().getTrackedRaceContext().getTrackedRace().getSensorTrack(element.getCompetitor(), BravoFixTrack.TRACK_NAME);
28
- if (bravoFixTrack != null) {
29
- bravoFixTrack.lockForRead();
30
- try {
31
- TrackedLegOfCompetitor trackedLegOfCompetitor = element.getTrackedLegOfCompetitor();
32
- if (trackedLegOfCompetitor.getStartTime() != null && trackedLegOfCompetitor.getFinishTime() != null) {
27
+ TrackedLegOfCompetitor trackedLegOfCompetitor = element.getTrackedLegOfCompetitor();
28
+ if (trackedLegOfCompetitor.getStartTime() != null && trackedLegOfCompetitor.getFinishTime() != null) {
29
+ BravoFixTrack<Competitor> bravoFixTrack = element.getTrackedLegContext().getTrackedRaceContext().getTrackedRace().getSensorTrack(element.getCompetitor(), BravoFixTrack.TRACK_NAME);
30
+ if (bravoFixTrack != null) {
31
+ bravoFixTrack.lockForRead();
32
+ try {
33 33
for (BravoFix bravoFix : bravoFixTrack.getFixes(trackedLegOfCompetitor.getStartTime(), true, trackedLegOfCompetitor.getFinishTime(), true)) {
34
+ if (isAborted()) {
35
+ break;
36
+ }
34 37
BravoFixWithContext gpsFixWithContext = new BravoFixWithContext(
35 38
new TrackedLegOfCompetitorWithSpecificTimePointWithContext(
36 39
element.getTrackedLegContext(), element.getTrackedLegOfCompetitor(), bravoFix.getTimePoint()), bravoFix);
37 40
bravoFixesWithContext.add(gpsFixWithContext);
38 41
}
42
+ } finally {
43
+ bravoFixTrack.unlockAfterRead();
39 44
}
40
- } finally {
41
- bravoFixTrack.unlockAfterRead();
42 45
}
43 46
}
44 47
return bravoFixesWithContext;
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/BravoFixTrackRetrievalProcessor.java
... ...
@@ -1,7 +1,7 @@
1 1
package com.sap.sailing.datamining.impl.components;
2 2
3
-import java.util.ArrayList;
4 3
import java.util.Collection;
4
+import java.util.Collections;
5 5
import java.util.concurrent.ExecutorService;
6 6
7 7
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
... ...
@@ -28,13 +28,9 @@ public class BravoFixTrackRetrievalProcessor extends AbstractRetrievalProcessor<
28 28
29 29
@Override
30 30
protected Iterable<HasBravoFixTrackContext> retrieveData(HasRaceOfCompetitorContext element) {
31
- Collection<HasBravoFixTrackContext> bravoTracksWithContext = new ArrayList<>();
32 31
final TrackedRace trackedRace = element.getTrackedRaceContext().getTrackedRace();
33 32
final BravoFixTrack<Competitor> bravoFixTrack = trackedRace.getSensorTrack(element.getCompetitor(), BravoFixTrack.TRACK_NAME);
34
- if (bravoFixTrack != null) {
35
- bravoTracksWithContext.add(new BravoFixTrackWithContext(element, bravoFixTrack));
36
- }
37
- return bravoTracksWithContext;
33
+ return bravoFixTrack == null ? Collections.emptySet() : Collections.singleton(new BravoFixTrackWithContext(element, bravoFixTrack));
38 34
}
39 35
40 36
}
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/CompetitorOfRaceInLeaderboardRetrievalProcessor.java
... ...
@@ -24,9 +24,15 @@ public class CompetitorOfRaceInLeaderboardRetrievalProcessor extends
24 24
protected Iterable<HasRaceResultOfCompetitorContext> retrieveData(HasLeaderboardContext element) {
25 25
Collection<HasRaceResultOfCompetitorContext> raceResultsOfCompetitor = new ArrayList<>();
26 26
for (RaceColumn raceColumn : element.getLeaderboard().getRaceColumns()) {
27
+ if (isAborted()) {
28
+ break;
29
+ }
27 30
for (Competitor competitor : element.getLeaderboard().getCompetitors()) {
31
+ if (isAborted()) {
32
+ break;
33
+ }
28 34
HasRaceResultOfCompetitorContext raceResultOfCompetitorContext = new RaceResultOfCompetitorWithContext(element, raceColumn, competitor,
29
- element.getPolarDataService());
35
+ element.getLeaderboardGroupContext().getPolarDataService());
30 36
raceResultsOfCompetitor.add(raceResultOfCompetitorContext);
31 37
}
32 38
}
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/CompleteManeuverCurveWithEstimationDataRetrievalProcessor.java
... ...
@@ -48,15 +48,27 @@ public class CompleteManeuverCurveWithEstimationDataRetrievalProcessor extends
48 48
Competitor competitor = element.getCompetitor();
49 49
ManeuverDetectorWithEstimationDataSupport maneuverDetector = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl(
50 50
new ManeuverDetectorImpl(trackedRace, competitor),
51
- element.getTrackedRaceContext().getLeaderboardContext().getPolarDataService());
51
+ element.getTrackedRaceContext().getLeaderboardContext().getLeaderboardGroupContext().getPolarDataService());
52
+
52 53
Iterable<Maneuver> maneuvers = trackedRace.getManeuvers(competitor, false);
54
+ if (isAborted()) {
55
+ return result;
56
+ }
57
+
53 58
Iterable<CompleteManeuverCurve> maneuverCurves = maneuverDetector.getCompleteManeuverCurves(maneuvers);
59
+ if (isAborted()) {
60
+ return result;
61
+ }
62
+
54 63
Iterable<CompleteManeuverCurveWithEstimationData> maneuversWithEstimationData = maneuverDetector
55 64
.getCompleteManeuverCurvesWithEstimationData(maneuverCurves);
56
-
57 65
CompleteManeuverCurveWithEstimationData previousManeuver = null;
58 66
CompleteManeuverCurveWithEstimationData currentManeuver = null;
59 67
for (CompleteManeuverCurveWithEstimationData nextManeuver : maneuversWithEstimationData) {
68
+ if (isAborted()) {
69
+ break;
70
+ }
71
+
60 72
if (currentManeuver != null) {
61 73
CompleteManeuverCurveWithEstimationDataWithContext maneuverWithContext = new CompleteManeuverCurveWithEstimationDataWithContext(
62 74
element, currentManeuver, settings, previousManeuver, nextManeuver);
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/FoilingSegmentRetrievalProcessor.java
... ...
@@ -50,6 +50,9 @@ public class FoilingSegmentRetrievalProcessor extends AbstractRetrievalProcessor
50 50
bravoFixTrack.lockForRead();
51 51
try {
52 52
for (final BravoFix bravoFix : bravoFixTrack.getFixes(startOfRace, /* fromInclusive */ true, end, /* toInclusive */ false)) {
53
+ if (isAborted()) {
54
+ break;
55
+ }
53 56
final boolean currentFixIsFoiling =
54 57
(bravoFix.isFoiling(settings.getMinimumRideHeight()) &&
55 58
(settings.getMinimumSpeedForFoiling() == null || settings.getMinimumSpeedForFoiling().compareTo(
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/GPSFixRetrievalProcessor.java
... ...
@@ -30,6 +30,9 @@ public class GPSFixRetrievalProcessor extends AbstractRetrievalProcessor<HasTrac
30 30
TrackedLegOfCompetitor trackedLegOfCompetitor = element.getTrackedLegOfCompetitor();
31 31
if (trackedLegOfCompetitor.getStartTime() != null && trackedLegOfCompetitor.getFinishTime() != null) {
32 32
for (GPSFixMoving gpsFix : competitorTrack.getFixes(trackedLegOfCompetitor.getStartTime(), true, trackedLegOfCompetitor.getFinishTime(), true)) {
33
+ if (isAborted()) {
34
+ break;
35
+ }
33 36
HasGPSFixContext gpsFixWithContext = new GPSFixWithContext(new TrackedLegOfCompetitorWithSpecificTimePointWithContext(
34 37
element.getTrackedLegContext(), element.getTrackedLegOfCompetitor(), gpsFix.getTimePoint()), gpsFix);
35 38
gpsFixesWithContext.add(gpsFixWithContext);
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/LeaderboardGroupRetrievalProcessor.java
... ...
@@ -1,30 +1,36 @@
1 1
package com.sap.sailing.datamining.impl.components;
2 2
3 3
import java.util.Collection;
4
+import java.util.HashSet;
5
+import java.util.Set;
4 6
import java.util.concurrent.ExecutorService;
5
-import java.util.stream.Collectors;
6 7
8
+import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
7 9
import com.sap.sailing.datamining.impl.data.LeaderboardGroupWithContext;
10
+import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
8 11
import com.sap.sailing.domain.polars.PolarDataService;
9 12
import com.sap.sailing.server.RacingEventService;
10 13
import com.sap.sse.datamining.components.Processor;
11 14
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
12 15
13
-public class LeaderboardGroupRetrievalProcessor extends AbstractRetrievalProcessor<RacingEventService, LeaderboardGroupWithContext> {
16
+public class LeaderboardGroupRetrievalProcessor extends AbstractRetrievalProcessor<RacingEventService, HasLeaderboardGroupContext> {
14 17
15 18
public LeaderboardGroupRetrievalProcessor(ExecutorService executor,
16
- Collection<Processor<LeaderboardGroupWithContext, ?>> resultReceivers, int retrievalLevel) {
17
- super(RacingEventService.class, LeaderboardGroupWithContext.class, executor, resultReceivers, retrievalLevel);
19
+ Collection<Processor<HasLeaderboardGroupContext, ?>> resultReceivers, int retrievalLevel) {
20
+ super(RacingEventService.class, HasLeaderboardGroupContext.class, executor, resultReceivers, retrievalLevel);
18 21
}
19 22
20 23
@Override
21
- protected Iterable<LeaderboardGroupWithContext> retrieveData(RacingEventService element) {
22
- final PolarDataService polarDataService = element.getPolarDataService();
23
- return element.getLeaderboardGroups()
24
- .values()
25
- .stream()
26
- .map(lg -> new LeaderboardGroupWithContext(lg, polarDataService))
27
- .collect(Collectors.toSet());
24
+ protected Iterable<HasLeaderboardGroupContext> retrieveData(RacingEventService element) {
25
+ Set<HasLeaderboardGroupContext> data = new HashSet<>();
26
+ PolarDataService polarDataService = element.getPolarDataService();
27
+ for (LeaderboardGroup leaderboardGroup : element.getLeaderboardGroups().values()) {
28
+ if (isAborted()) {
29
+ break;
30
+ }
31
+ data.add(new LeaderboardGroupWithContext(leaderboardGroup, polarDataService));
32
+ }
33
+ return data;
28 34
}
29 35
30 36
}
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/LeaderboardRetrievalProcessor.java
... ...
@@ -5,24 +5,27 @@ import java.util.Collection;
5 5
import java.util.concurrent.ExecutorService;
6 6
7 7
import com.sap.sailing.datamining.data.HasLeaderboardContext;
8
-import com.sap.sailing.datamining.impl.data.LeaderboardGroupWithContext;
8
+import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
9 9
import com.sap.sailing.datamining.impl.data.LeaderboardWithContext;
10 10
import com.sap.sailing.domain.leaderboard.Leaderboard;
11 11
import com.sap.sse.datamining.components.Processor;
12 12
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
13 13
14
-public class LeaderboardRetrievalProcessor extends AbstractRetrievalProcessor<LeaderboardGroupWithContext, HasLeaderboardContext> {
14
+public class LeaderboardRetrievalProcessor extends AbstractRetrievalProcessor<HasLeaderboardGroupContext, HasLeaderboardContext> {
15 15
16 16
public LeaderboardRetrievalProcessor(ExecutorService executor,
17 17
Collection<Processor<HasLeaderboardContext, ?>> resultReceivers, int retrievalLevel) {
18
- super(LeaderboardGroupWithContext.class, HasLeaderboardContext.class, executor, resultReceivers, retrievalLevel);
18
+ super(HasLeaderboardGroupContext.class, HasLeaderboardContext.class, executor, resultReceivers, retrievalLevel);
19 19
}
20 20
21 21
@Override
22
- protected Iterable<HasLeaderboardContext> retrieveData(LeaderboardGroupWithContext element) {
22
+ protected Iterable<HasLeaderboardContext> retrieveData(HasLeaderboardGroupContext element) {
23 23
Collection<HasLeaderboardContext> leaderboardsWithContext = new ArrayList<>();
24 24
for (Leaderboard leaderboard : element.getLeaderboardGroup().getLeaderboards()) {
25
- leaderboardsWithContext.add(new LeaderboardWithContext(leaderboard, element, element.getPolarDataService()));
25
+ if (isAborted()) {
26
+ break;
27
+ }
28
+ leaderboardsWithContext.add(new LeaderboardWithContext(leaderboard, element));
26 29
}
27 30
return leaderboardsWithContext;
28 31
}
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/ManeuverRetrievalProcessor.java
... ...
@@ -48,6 +48,10 @@ public class ManeuverRetrievalProcessor
48 48
Maneuver previousManeuver = null;
49 49
Maneuver currentManeuver = null;
50 50
for (Maneuver nextManeuver : maneuvers) {
51
+ if (isAborted()) {
52
+ break;
53
+ }
54
+
51 55
if (currentManeuver != null) {
52 56
ManeuverWithContext maneuverWithContext = new ManeuverWithContext(new TrackedLegOfCompetitorWithSpecificTimePointWithContext(
53 57
element.getTrackedLegContext(), element.getTrackedLegOfCompetitor(), currentManeuver.getTimePoint()), currentManeuver,
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/ManeuverSpeedDetailsRetrievalProcessor.java
... ...
@@ -87,6 +87,10 @@ public class ManeuverSpeedDetailsRetrievalProcessor
87 87
88 88
double directionChangeForAnalysisSignum = Math.signum(directionChangeInDegreesForAnalysis);
89 89
for (SpeedWithBearingStep bearingStep : maneuverBearingSteps) {
90
+ if (isAborted()) {
91
+ break;
92
+ }
93
+
90 94
currentDirectionChangeSumInDegrees += bearingStep.getCourseChangeInDegrees();
91 95
if (previousRoundedTWA != -1
92 96
&& Math.signum(currentDirectionChangeSumInDegrees) != directionChangeForAnalysisSignum
... ...
@@ -123,6 +127,9 @@ public class ManeuverSpeedDetailsRetrievalProcessor
123 127
for (int step = 1, fillingTWA = twaIterationFunction
124 128
.apply(previousRoundedTWA); fillingTWA != roundedTWA; fillingTWA = twaIterationFunction
125 129
.apply(fillingTWA), ++step) {
130
+ if (isAborted()) {
131
+ break;
132
+ }
126 133
if (speedPerTWA[fillingTWA] == 0) {
127 134
speedPerTWA[fillingTWA] = previousSpeed
128 135
+ diffWithPreviousSpeed * step / diffWithPreviousTWA;
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/MarkPassingRetrievalProcessor.java
... ...
@@ -29,6 +29,9 @@ public class MarkPassingRetrievalProcessor extends AbstractRetrievalProcessor<Ha
29 29
try {
30 30
Iterable<Maneuver> maneuvers = element.getTrackedLegOfCompetitor().getManeuvers(finishTime, false);
31 31
for (Maneuver maneuver : maneuvers) {
32
+ if (isAborted()) {
33
+ break;
34
+ }
32 35
if (maneuver.isMarkPassing()) {
33 36
maneuversWithContext.add(new MarkPassingWithContext(new TrackedLegOfCompetitorWithSpecificTimePointWithContext(
34 37
element.getTrackedLegContext(), element.getTrackedLegOfCompetitor(), maneuver.getTimePoint()), maneuver));
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/RaceOfCompetitorRetrievalProcessor.java
... ...
@@ -22,6 +22,9 @@ public class RaceOfCompetitorRetrievalProcessor extends AbstractRetrievalProcess
22 22
protected Iterable<HasRaceOfCompetitorContext> retrieveData(HasTrackedRaceContext element) {
23 23
Collection<HasRaceOfCompetitorContext> raceOfCompetitorsWithContext = new ArrayList<>();
24 24
for (Competitor competitor : element.getTrackedRace().getRace().getCompetitors()) {
25
+ if (isAborted()) {
26
+ break;
27
+ }
25 28
HasRaceOfCompetitorContext raceOfCompetitorWithContext = new RaceOfCompetitorWithContext(element, competitor);
26 29
raceOfCompetitorsWithContext.add(raceOfCompetitorWithContext);
27 30
}
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/TrackedLegOfCompetitorRetrievalProcessor.java
... ...
@@ -22,6 +22,9 @@ public class TrackedLegOfCompetitorRetrievalProcessor extends AbstractRetrievalP
22 22
protected Iterable<HasTrackedLegOfCompetitorContext> retrieveData(HasTrackedLegContext element) {
23 23
Collection<HasTrackedLegOfCompetitorContext> trackedLegOfCompetitorsWithContext = new ArrayList<>();
24 24
for (Competitor competitor : element.getTrackedRaceContext().getTrackedRace().getRace().getCompetitors()) {
25
+ if (isAborted()) {
26
+ break;
27
+ }
25 28
HasTrackedLegOfCompetitorContext trackedLegOfCompetitorWithContext = new TrackedLegOfCompetitorWithContext(element, element.getTrackedLeg().getTrackedLeg(competitor));
26 29
trackedLegOfCompetitorsWithContext.add(trackedLegOfCompetitorWithContext);
27 30
}
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/TrackedLegRetrievalProcessor.java
... ...
@@ -23,6 +23,9 @@ public class TrackedLegRetrievalProcessor extends AbstractRetrievalProcessor<Has
23 23
Collection<HasTrackedLegContext> trackedLegsWithContext = new ArrayList<>();
24 24
int legNumber = 1;
25 25
for (TrackedLeg trackedLeg : element.getTrackedRace().getTrackedLegs()) {
26
+ if (isAborted()) {
27
+ break;
28
+ }
26 29
HasTrackedLegContext trackedLegWithContext = new TrackedLegWithContext(element, trackedLeg, legNumber);
27 30
trackedLegsWithContext.add(trackedLegWithContext);
28 31
legNumber++;
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/TrackedRaceRetrievalProcessor.java
... ...
@@ -25,7 +25,13 @@ public class TrackedRaceRetrievalProcessor extends AbstractRetrievalProcessor<Ha
25 25
protected Iterable<HasTrackedRaceContext> retrieveData(HasLeaderboardContext element) {
26 26
Collection<HasTrackedRaceContext> trackedRacesWithContext = new ArrayList<>();
27 27
for (RaceColumn raceColumn : element.getLeaderboard().getRaceColumns()) {
28
+ if (isAborted()) {
29
+ break;
30
+ }
28 31
for (Fleet fleet : raceColumn.getFleets()) {
32
+ if (isAborted()) {
33
+ break;
34
+ }
29 35
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
30 36
if (trackedRace != null) {
31 37
Regatta regatta = trackedRace.getTrackedRegatta().getRegatta();
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/WindFixRetrievalProcessor.java
... ...
@@ -33,6 +33,9 @@ public class WindFixRetrievalProcessor extends AbstractRetrievalProcessor<HasWin
33 33
windTrack.lockForRead();
34 34
try {
35 35
for (final Wind wind : windTrack.getFixes()) {
36
+ if (isAborted()) {
37
+ break;
38
+ }
36 39
windFixesWithContext.add(new WindFixWithContext(element.getTrackedRaceContext(), wind, element.getWindSourceType()));
37 40
}
38 41
} finally {
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/WindTrackRetrievalProcessor.java
... ...
@@ -31,6 +31,9 @@ public class WindTrackRetrievalProcessor extends AbstractRetrievalProcessor<HasT
31 31
Collection<HasWindTrackContext> windTracksWithContext = new ArrayList<>();
32 32
final TrackedRace trackedRace = element.getTrackedRace();
33 33
for (final WindSource windSource : trackedRace.getWindSources()) {
34
+ if (isAborted()) {
35
+ break;
36
+ }
34 37
if (!trackedRace.getWindSourcesToExclude().contains(windSource)) {
35 38
final WindTrack windTrack = trackedRace.getOrCreateWindTrack(windSource);
36 39
windTracksWithContext.add(new WindTrackWithContext(element, windTrack, windSource));
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/aggregators/AbstractParallelAverageAggregationProcessor.java
... ...
@@ -64,6 +64,9 @@ public abstract class AbstractParallelAverageAggregationProcessor<T extends Comp
64 64
Map<GroupKey, T> minAggregation = minAggregationProcessor.getResult();
65 65
Map<GroupKey, T> maxAggregation = maxAggregationProcessor.getResult();
66 66
for (Entry<GroupKey, T> sumAggregationEntry : sumAggregation.entrySet()) {
67
+ if (isAborted()) {
68
+ break;
69
+ }
67 70
GroupKey key = sumAggregationEntry.getKey();
68 71
result.put(key, new AverageWithStatsImpl<>(
69 72
/* average */ divide(sumAggregationEntry.getValue(), elementAmountPerKey.get(key).longValue()),
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/aggregators/AbstractParallelSumAggregationProcessor.java
... ...
@@ -19,8 +19,6 @@ public abstract class AbstractParallelSumAggregationProcessor<T> extends
19 19
super(executor, resultReceivers, "Sum");
20 20
results = new HashMap<>();
21 21
}
22
-
23
- protected abstract T add(T t1, T t2);
24 22
25 23
@Override
26 24
protected void handleElement(GroupedDataEntry<T> element) {
... ...
@@ -31,6 +29,8 @@ public abstract class AbstractParallelSumAggregationProcessor<T> extends
31 29
results.put(key, add(results.get(key), element.getDataEntry()));
32 30
}
33 31
}
32
+
33
+ protected abstract T add(T t1, T t2);
34 34
35 35
@Override
36 36
protected Map<GroupKey, T> getResult() {
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/aggregators/ParallelBearingAverageDegreesAggregationProcessor.java
... ...
@@ -47,6 +47,9 @@ public class ParallelBearingAverageDegreesAggregationProcessor
47 47
protected Map<GroupKey, Double> aggregateResult() {
48 48
Map<GroupKey, Double> result = new HashMap<>();
49 49
for (Entry<GroupKey, BearingCluster> clusterEntry : results.entrySet()) {
50
+ if (isAborted()) {
51
+ break;
52
+ }
50 53
GroupKey key = clusterEntry.getKey();
51 54
result.put(key, clusterEntry.getValue().getAverage().getDegrees());
52 55
}
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/aggregators/ParallelDistanceMedianAggregationProcessor.java
... ...
@@ -50,6 +50,9 @@ public class ParallelDistanceMedianAggregationProcessor
50 50
protected Map<GroupKey, Distance> aggregateResult() {
51 51
Map<GroupKey, Distance> result = new HashMap<>();
52 52
for (Entry<GroupKey, List<Distance>> groupedValuesEntry : groupedValues.entrySet()) {
53
+ if (isAborted()) {
54
+ break;
55
+ }
53 56
result.put(groupedValuesEntry.getKey(), getMedianOf(groupedValuesEntry.getValue()));
54 57
}
55 58
return result;
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/data/LeaderboardWithContext.java
... ...
@@ -4,17 +4,14 @@ import com.sap.sailing.datamining.data.HasLeaderboardContext;
4 4
import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
5 5
import com.sap.sailing.domain.base.BoatClass;
6 6
import com.sap.sailing.domain.leaderboard.Leaderboard;
7
-import com.sap.sailing.domain.polars.PolarDataService;
8 7
9 8
public class LeaderboardWithContext implements HasLeaderboardContext {
10 9
private final Leaderboard leaderboard;
11 10
private final HasLeaderboardGroupContext leaderboardGroupContext;
12
- private final PolarDataService polarDataService;
13 11
14
- public LeaderboardWithContext(Leaderboard leaderboard, HasLeaderboardGroupContext leaderboardGroupContext, PolarDataService polarDataService) {
12
+ public LeaderboardWithContext(Leaderboard leaderboard, HasLeaderboardGroupContext leaderboardGroupContext) {
15 13
this.leaderboard = leaderboard;
16 14
this.leaderboardGroupContext = leaderboardGroupContext;
17
- this.polarDataService = polarDataService;
18 15
}
19 16
20 17
public HasLeaderboardGroupContext getLeaderboardGroupContext() {
... ...
@@ -32,11 +29,6 @@ public class LeaderboardWithContext implements HasLeaderboardContext {
32 29
}
33 30
34 31
@Override
35
- public PolarDataService getPolarDataService() {
36
- return polarDataService;
37
- }
38
-
39
- @Override
40 32
public String getName() {
41 33
return getLeaderboard().getName();
42 34
}
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/data/RaceOfCompetitorWithContext.java
... ...
@@ -29,10 +29,12 @@ import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
29 29
import com.sap.sailing.domain.tracking.TrackedRace;
30 30
import com.sap.sailing.domain.tracking.WindPositionMode;
31 31
import com.sap.sse.common.Distance;
32
+import com.sap.sse.common.Duration;
32 33
import com.sap.sse.common.Speed;
33 34
import com.sap.sse.common.TimePoint;
34 35
import com.sap.sse.common.Util;
35 36
import com.sap.sse.common.Util.Pair;
37
+import com.sap.sse.common.impl.MillisecondsDurationImpl;
36 38
import com.sap.sse.common.impl.MillisecondsTimePoint;
37 39
import com.sap.sse.datamining.data.Cluster;
38 40
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
... ...
@@ -357,4 +359,18 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
357 359
return distance / length;
358 360
}
359 361
362
+ @Override
363
+ public Duration getDuration() {
364
+ Duration duration = null;
365
+ TrackedRace race = getTrackedRace();
366
+ Course course = race.getRace().getCourse();
367
+ MarkPassing startPassing = race.getMarkPassing(competitor, course.getFirstWaypoint());
368
+ MarkPassing finishPassing = race.getMarkPassing(competitor, course.getLastWaypoint());
369
+ if (startPassing != null && finishPassing != null) {
370
+ long durationMillis = finishPassing.getTimePoint().asMillis() - startPassing.getTimePoint().asMillis();
371
+ duration = new MillisecondsDurationImpl(durationMillis);
372
+ }
373
+ return duration;
374
+ }
375
+
360 376
}
... ...
\ No newline at end of file
java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/data/TrackedRaceWithContext.java
... ...
@@ -17,8 +17,10 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
17 17
import com.sap.sailing.domain.tracking.GPSFixTrack;
18 18
import com.sap.sailing.domain.tracking.LineDetails;
19 19
import com.sap.sailing.domain.tracking.TrackedRace;
20
+import com.sap.sse.common.Duration;
20 21
import com.sap.sse.common.TimePoint;
21 22
import com.sap.sse.common.Util;
23
+import com.sap.sse.common.impl.MillisecondsDurationImpl;
22 24
import com.sap.sse.common.impl.MillisecondsTimePoint;
23 25
24 26
public class TrackedRaceWithContext implements HasTrackedRaceContext {
... ...
@@ -113,6 +115,26 @@ public class TrackedRaceWithContext implements HasTrackedRaceContext {
113 115
public Boolean isTracked() {
114 116
return getTrackedRace().hasStarted(MillisecondsTimePoint.now());
115 117
}
118
+
119
+ @Override
120
+ public Duration getDuration() {
121
+ Duration duration = null;
122
+ TrackedRace race = getTrackedRace();
123
+ TimePoint start = race.getStartOfRace();
124
+ if (start == null) {
125
+ start = race.getStartOfTracking();
126
+ }
127
+ if (start != null) {
128
+ TimePoint end = race.getEndOfRace();
129
+ if (end == null) {
130
+ end = race.getEndOfTracking();
131
+ }
132
+ if (end != null) {
133
+ duration = new MillisecondsDurationImpl(end.asMillis() - start.asMillis());
134
+ }
135
+ }
136
+ return duration;
137
+ }
116 138
117 139
@Override
118 140
public int getNumberOfCompetitorFixes() {
java/com.sap.sailing.domain.common/.project
... ...
@@ -21,12 +21,12 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
24
+ <name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
25 25
<arguments>
26 26
</arguments>
27 27
</buildCommand>
28 28
<buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
29
+ <name>com.gwtplugins.gwt.eclipse.core.gwtProjectValidator</name>
30 30
<arguments>
31 31
</arguments>
32 32
</buildCommand>
... ...
@@ -34,6 +34,6 @@
34 34
<natures>
35 35
<nature>org.eclipse.pde.PluginNature</nature>
36 36
<nature>org.eclipse.jdt.core.javanature</nature>
37
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
37
+ <nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
38 38
</natures>
39 39
</projectDescription>
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/maneuverdetection/impl/IncrementalManeuverComputationTest.java
... ...
@@ -130,11 +130,14 @@ public class IncrementalManeuverComputationTest extends AbstractManeuverDetectio
130 130
performanceMeasurementStartedAt = System.currentTimeMillis();
131 131
List<Maneuver> normallyDetectedManeuvers = normalManeuverDetector.detectManeuvers();
132 132
long millisForNormalManeuverDetection = System.currentTimeMillis() - performanceMeasurementStartedAt;
133
+ int performanceBenefitOfIncrementalManeuverDetectionInPercent = (int) ((1.0 * (millisForNormalManeuverDetection - millisForIncrementalManeuverDetection)
134
+ / millisForNormalManeuverDetection) * 100);
133 135
assertEquals("Incrementally calculated maneuvers differ from normally calculated maneuvers",
134 136
normallyDetectedManeuvers, incrementallyDetectedManeuvers);
135 137
assertTrue(
136
- "Incremental maneuver detection was not 30% faster in detecting maneuvers incrementally, than the full maneuver detection",
137
- millisForIncrementalManeuverDetection * 1.3 < millisForNormalManeuverDetection);
138
+ "Incremental maneuver detection was not 20% faster in detecting maneuvers incrementally, than the full maneuver detection. The actual performance benefit was: "
139
+ + performanceBenefitOfIncrementalManeuverDetectionInPercent + "%",
140
+ performanceBenefitOfIncrementalManeuverDetectionInPercent >= 20);
138 141
}
139 142
140 143
}
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RouteAssemblyTest.java
... ...
@@ -15,6 +15,7 @@ import com.sap.sailing.domain.tractracadapter.LoadingQueueDoneCallBack;
15 15
import com.sap.sailing.domain.tractracadapter.Receiver;
16 16
import com.sap.sse.common.Util;
17 17
import com.tractrac.model.lib.api.route.IControlRoute;
18
+import com.tractrac.model.lib.api.route.IPathRoute;
18 19
import com.tractrac.subscription.lib.api.control.IControlRouteChangeListener;
19 20
20 21
public class RouteAssemblyTest extends AbstractTracTracLiveTest {
... ...
@@ -66,6 +67,11 @@ public class RouteAssemblyTest extends AbstractTracTracLiveTest {
66 67
first = false;
67 68
}
68 69
}
70
+
71
+ @Override
72
+ public void gotRouteChange(IPathRoute pathRoute, long timeStamp) {
73
+ // will never be invoked for sailing events
74
+ }
69 75
});
70 76
}
71 77
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java
... ...
@@ -37,6 +37,7 @@ import com.tractrac.model.lib.api.event.IEvent;
37 37
import com.tractrac.model.lib.api.event.IRace;
38 38
import com.tractrac.model.lib.api.route.IControl;
39 39
import com.tractrac.model.lib.api.route.IControlRoute;
40
+import com.tractrac.model.lib.api.route.IPathRoute;
40 41
import com.tractrac.model.lib.api.route.IRoute;
41 42
import com.tractrac.subscription.lib.api.IEventSubscriber;
42 43
import com.tractrac.subscription.lib.api.IRaceSubscriber;
... ...
@@ -97,6 +98,13 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<IControlRoute,
97 98
public void gotRouteChange(IControlRoute controlRoute, long timeStamp) {
98 99
enqueue(new Triple<IControlRoute, Long, Void>(controlRoute, timeStamp, null));
99 100
}
101
+
102
+ @Override
103
+ public void gotRouteChange(IPathRoute pathRoute, long timeStamp) {
104
+ // will never be invoked for sailing events; Jorge Llodra (2018-07-30):
105
+ // "The IControlRouteChangeListener has been extended adding a new method to get updates of a
106
+ // IPathRoute. If you are managing "sailing events" this method will never be invoked."
107
+ }
100 108
};
101 109
}
102 110
java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/CompleteManeuverCurveWithEstimationData.java
... ...
@@ -100,9 +100,9 @@ public interface CompleteManeuverCurveWithEstimationData extends Timed, Position
100 100
101 101
Distance getDistanceToClosestMark();
102 102
103
- Double getDeviationOfManeuverAngleFromTargetTackAngleInDegrees();
103
+ Double getTargetTackAngleInDegrees();
104 104
105
- Double getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees();
105
+ Double getTargetJibeAngleInDegrees();
106 106
107 107
/**
108 108
* Gets whether a mark was crossed within the maneuver curve.
java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/CompleteManeuverCurveWithEstimationDataImpl.java
... ...
@@ -27,14 +27,15 @@ public class CompleteManeuverCurveWithEstimationDataImpl implements CompleteMane
27 27
private final boolean markPassing;
28 28
private final Position position;
29 29
private final Distance distanceToClosestMark;
30
- private final Double deviationOfManeuverAngleFromTargetTackAngleInDegrees;
31
- private final Double deviationOfManeuverAngleFromTargetJibeAngleInDegrees;
30
+ private final Double targetTackAngleInDegrees;
31
+ private final Double targetJibeAngleInDegrees;
32 32
33 33
public CompleteManeuverCurveWithEstimationDataImpl(Position position, ManeuverMainCurveWithEstimationData mainCurve,
34 34
ManeuverCurveWithUnstableCourseAndSpeedWithEstimationData curveWithUnstableCourseAndSpeed, Wind wind,
35 35
int tackingCount, int jibingCount, boolean maneuverStartsByRunningAwayFromWind,
36 36
Bearing relativeBearingToNextMarkBeforeManeuver, Bearing relativeBearingToNextMarkAfterManeuver,
37
- boolean markPassing, Distance distanceToClosestMark, Double deviationOfManeuverAngleFromTargetTackAngleInDegrees, Double deviationOfManeuverAngleFromTargetJibeAngleInDegrees) {
37
+ boolean markPassing, Distance distanceToClosestMark, Double targetTackAngleInDegrees,
38
+ Double targetJibeAngleInDegrees) {
38 39
this.position = position;
39 40
this.mainCurve = mainCurve;
40 41
this.curveWithUnstableCourseAndSpeed = curveWithUnstableCourseAndSpeed;
... ...
@@ -46,8 +47,8 @@ public class CompleteManeuverCurveWithEstimationDataImpl implements CompleteMane
46 47
this.relativeBearingToNextMarkAfterManeuver = relativeBearingToNextMarkAfterManeuver;
47 48
this.markPassing = markPassing;
48 49
this.distanceToClosestMark = distanceToClosestMark;
49
- this.deviationOfManeuverAngleFromTargetTackAngleInDegrees = deviationOfManeuverAngleFromTargetTackAngleInDegrees;
50
- this.deviationOfManeuverAngleFromTargetJibeAngleInDegrees = deviationOfManeuverAngleFromTargetJibeAngleInDegrees;
50
+ this.targetTackAngleInDegrees = targetTackAngleInDegrees;
51
+ this.targetJibeAngleInDegrees = targetJibeAngleInDegrees;
51 52
}
52 53
53 54
@Override
... ...
@@ -99,20 +100,20 @@ public class CompleteManeuverCurveWithEstimationDataImpl implements CompleteMane
99 100
public Position getPosition() {
100 101
return position;
101 102
}
102
-
103
+
103 104
@Override
104 105
public Distance getDistanceToClosestMark() {
105 106
return distanceToClosestMark;
106 107
}
107
-
108
+
108 109
@Override
109
- public Double getDeviationOfManeuverAngleFromTargetTackAngleInDegrees() {
110
- return deviationOfManeuverAngleFromTargetTackAngleInDegrees;
110
+ public Double getTargetTackAngleInDegrees() {
111
+ return targetTackAngleInDegrees;
111 112
}
112
-
113
+
113 114
@Override
114
- public Double getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees() {
115
- return deviationOfManeuverAngleFromTargetJibeAngleInDegrees;
115
+ public Double getTargetJibeAngleInDegrees() {
116
+ return targetJibeAngleInDegrees;
116 117
}
117 118
118 119
}
java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/ManeuverDetectorWithEstimationDataSupportDecoratorImpl.java
... ...
@@ -278,7 +278,8 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl
278 278
stepWithHighestSpeed.getSpeedWithBearing(), stepWithHighestSpeed.getTimePoint(),
279 279
maneuverCurve.getMainCurveBoundaries().getTimePoint(),
280 280
maneuverCurve.getMainCurveBoundaries().getMaxTurningRateInDegreesPerSecond(), courseAtMaxTurningRate,
281
- distanceSailedWithinManeuver, projectedManeuverLoss.getDistanceSailedProjectedOnMiddleManeuverAngle(), distanceSailedIfNotManeuvering,
281
+ distanceSailedWithinManeuver, projectedManeuverLoss.getDistanceSailedProjectedOnMiddleManeuverAngle(),
282
+ distanceSailedIfNotManeuvering,
282 283
projectedManeuverLoss.getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle(),
283 284
Math.abs(maneuverCurve.getMainCurveBoundaries().getDirectionChangeInDegrees())
284 285
/ maneuverCurve.getMainCurveBoundaries().getDuration().asSeconds(),
... ...
@@ -338,9 +339,9 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl
338 339
gpsFixesCountFromPreviousManeuver, durationAndAvgSpeedWithBearingAfter.getB(),
339 340
durationAndAvgSpeedWithBearingAfter.getA(), gpsFixesCountToNextManeuver, distanceSailedWithinManeuver,
340 341
projectedManeuverLoss.getDistanceSailedProjectedOnMiddleManeuverAngle(), distanceSailedIfNotManeuvering,
341
- projectedManeuverLoss.getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle(), gpsFixCountWithinWholeCurve,
342
- longestGpsFixIntervalBetweenTwoFixes, intervalBetweenLastFixOfCurveAndNextFix,
343
- intervalBetweenFirstFixOfCurveAndPreviousFix);
342
+ projectedManeuverLoss.getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle(),
343
+ gpsFixCountWithinWholeCurve, longestGpsFixIntervalBetweenTwoFixes,
344
+ intervalBetweenLastFixOfCurveAndNextFix, intervalBetweenFirstFixOfCurveAndPreviousFix);
344 345
TimePoint maneuverTimePoint = maneuverCurve.getMainCurveBoundaries().getTimePoint();
345 346
Position maneuverPosition = maneuverDetector.track.getEstimatedPosition(maneuverTimePoint,
346 347
/* extrapolate */false);
... ...
@@ -357,8 +358,8 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl
357 358
.getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingAfter().getBearing());
358 359
BoatClass boatClass = maneuverDetector.trackedRace.getRace().getBoatOfCompetitor(maneuverDetector.competitor)
359 360
.getBoatClass();
360
- Double deviationFromTackAngle = null;
361
- Double deviationFromJibeAngle = null;
361
+ Double targetTackAngle = null;
362
+ Double targetJibeAngle = null;
362 363
Speed boatSpeed = curveWithUnstableCourseAndSpeed.getSpeedWithBearingBefore()
363 364
.compareTo(curveWithUnstableCourseAndSpeed.getSpeedWithBearingAfter()) < 0
364 365
? curveWithUnstableCourseAndSpeed.getSpeedWithBearingBefore()
... ...
@@ -369,11 +370,11 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl
369 370
SpeedWithBearingWithConfidence<Void> closestJibeTwa = polarDataService.getClosestTwaTws(ManeuverType.JIBE,
370 371
boatSpeed, curveWithUnstableCourseAndSpeed.getDirectionChangeInDegrees(), boatClass);
371 372
if (closestTackTwa != null) {
372
- deviationFromTackAngle = polarDataService.getManeuverAngleInDegreesFromTwa(
373
+ targetTackAngle = polarDataService.getManeuverAngleInDegreesFromTwa(
373 374
closestTackTwa.getObject().getBearing().getDegrees(), ManeuverType.TACK);
374 375
}
375 376
if (closestJibeTwa != null) {
376
- deviationFromJibeAngle = polarDataService.getManeuverAngleInDegreesFromTwa(
377
+ targetJibeAngle = polarDataService.getManeuverAngleInDegreesFromTwa(
377 378
closestJibeTwa.getObject().getBearing().getDegrees(), ManeuverType.JIBE);
378 379
}
379 380
}
... ...
@@ -383,7 +384,7 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl
383 384
curveWithUnstableCourseAndSpeed, wind, numberOfTacks, numberOfJibes,
384 385
maneuverStartsByRunningAwayFromWind, relativeBearingToNextMarkPassingBeforeManeuver,
385 386
relativeBearingToNextMarkPassingAfterManeuver, maneuverCurve.isMarkPassing(), closestDistanceToMark,
386
- deviationFromTackAngle, deviationFromJibeAngle);
387
+ targetTackAngle, targetJibeAngle);
387 388
}
388 389
389 390
public Distance getClosestDistanceToMark(TimePoint timePoint) {
java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/CandidateFinder.java
... ...
@@ -54,6 +54,13 @@ public interface CandidateFinder {
54 54
Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterRaceStartTimeChange();
55 55
56 56
/**
57
+ * Notifies this finder about the race's start of tracking time having changed. In case of a race that infers
58
+ * the race start time from the start mark passings, a change in start of tracking needs to adjust the time range
59
+ * in which candidates are considered valid.
60
+ */
61
+ Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterStartOfTrackingChange();
62
+
63
+ /**
57 64
* Notifies this finder about the race's finished time having changed. The candidates collections are adjusted
58 65
* accordingly: new candidates may be added if the finished time was moved to a later point in time and therefore
59 66
* extends the time range for candidates; candidates are removed if the finished time was moved to an earlier point
java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingUpdateListener.java
... ...
@@ -196,6 +196,25 @@ public class MarkPassingUpdateListener extends AbstractRaceChangeListener {
196 196
}
197 197
198 198
@Override
199
+ public void startOfTrackingChanged(TimePoint oldStartOfTracking, TimePoint newStartOfTracking) {
200
+ markPassingCalculator.enqueueUpdate(new StorePositionUpdateStrategy() {
201
+ @Override
202
+ public void storePositionUpdate(Map<Competitor, List<GPSFix>> competitorFixes,
203
+ Map<Mark, List<GPSFix>> markFixes, List<Waypoint> addedWaypoints, List<Waypoint> removedWaypoints,
204
+ IntHolder smallestChangedWaypointIndex,
205
+ List<Triple<Competitor, Integer, TimePoint>> fixedMarkPassings,
206
+ List<Pair<Competitor, Integer>> removedMarkPassings,
207
+ List<Pair<Competitor, Integer>> suppressedMarkPassings, List<Competitor> unSuppressedMarkPassings, CandidateFinder candidateFinder, CandidateChooser candidateChooser) {
208
+ final Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> newAndRemovedCandidatesPerCompetitor =
209
+ candidateFinder.getCandidateDeltasAfterStartOfTrackingChange();
210
+ for (final Entry<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> i : newAndRemovedCandidatesPerCompetitor.entrySet()) {
211
+ candidateChooser.calculateMarkPassDeltas(i.getKey(), i.getValue().getA(), i.getValue().getB());
212
+ }
213
+ }
214
+ });
215
+ }
216
+
217
+ @Override
199 218
public void finishedTimeChanged(TimePoint oldFinishedTime, TimePoint newFinishedTime) {
200 219
markPassingCalculator.enqueueUpdate(new StorePositionUpdateStrategy() {
201 220
@Override
java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImpl.java
... ...
@@ -37,6 +37,7 @@ import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
37 37
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
38 38
import com.sap.sailing.domain.tracking.GPSFixTrack;
39 39
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
40
+import com.sap.sailing.domain.tracking.TrackedRace;
40 41
import com.sap.sailing.domain.tracking.impl.MarkPositionAtTimePointCacheImpl;
41 42
import com.sap.sailing.domain.tracking.impl.TimedComparator;
42 43
import com.sap.sse.common.Bearing;
... ...
@@ -1455,12 +1456,26 @@ public class CandidateFinderImpl implements CandidateFinder {
1455 1456
/**
1456 1457
* If the {@link #race}'s regatta is configured to infer the start times from start mark passings then {@code null}
1457 1458
* must be tolerated as a value for {@code from}, leading to an open interval starting at the
1458
- * {@link TimePoint#BeginningOfTime beginning of time}. However, if the start time is expected to be set and not
1459
- * inferred, mark passings need to be detected only from the start minus some tolerance interval. In this case,
1460
- * an interval that has {@code null} as its {@code from} time point and thus is considered empty will be returned.
1461
- * It hence returns {@code null} from its {@link TimeRangeWithNullStartMeaningEmpty#getTimeRangeOrNull()} method.
1459
+ * {@link TrackedRace#getStartOfTracking()} or, if not set, the {@link TimePoint#BeginningOfTime beginning of time}.
1460
+ * However, if the start time is expected to be set and not inferred, mark passings need to be detected only from
1461
+ * the start minus some tolerance interval. In this case, an interval that has {@code null} as its {@code from} time
1462
+ * point and thus is considered empty will be returned. It hence returns {@code null} from its
1463
+ * {@link TimeRangeWithNullStartMeaningEmpty#getTimeRangeOrNull()} method.
1462 1464
*/
1463 1465
private TimeRangeWithNullStartMeaningEmpty getTimeRangeOrNull(TimePoint from, TimePoint to) {
1466
+ final TimePoint effectiveFrom = getEffectiveFrom(from);
1467
+ return new TimeRangeWithNullStartMeaningEmpty(effectiveFrom, to);
1468
+ }
1469
+
1470
+ /**
1471
+ * If the {@link #race}'s regatta is configured to infer the start times from start mark passings then {@code null}
1472
+ * must be tolerated as a value for {@code from}, leading to an open interval starting at the
1473
+ * {@link TrackedRace#getStartOfTracking()} or, if not set, the {@link TimePoint#BeginningOfTime beginning of time}.
1474
+ * However, if the start time is expected to be set and not inferred, mark passings need to be detected only from
1475
+ * the start minus some tolerance interval. In this case, for an interval that has {@code null} as its {@code from} time
1476
+ * point and thus is considered empty, {@code null} will be returned.
1477
+ */
1478
+ private TimePoint getEffectiveFrom(TimePoint from) {
1464 1479
final TimePoint effectiveFrom;
1465 1480
if (from == null && race.getTrackedRegatta().getRegatta().useStartTimeInference()) {
1466 1481
// need to check the whole track to be able to find start mark passings
... ...
@@ -1470,15 +1485,22 @@ public class CandidateFinderImpl implements CandidateFinder {
1470 1485
} else {
1471 1486
effectiveFrom = from;
1472 1487
}
1473
- return new TimeRangeWithNullStartMeaningEmpty(effectiveFrom, to);
1488
+ return effectiveFrom;
1474 1489
}
1475 1490
1476 1491
@Override
1477 1492
public Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterRaceStartTimeChange() {
1478
- final Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> result;
1479 1493
final TimePoint newNonInferredStartTime = race.getStartOfRace(/* inferred */ false);
1480 1494
final TimePoint newTimePointWhenToStartConsideringCandidates = getTimePointWhenToStartConsideringCandidates(newNonInferredStartTime);
1481
- final TimeRangeWithNullStartMeaningEmpty newTimeRange = timeRangeForValidCandidates.getWithNewFrom(newTimePointWhenToStartConsideringCandidates);
1495
+ final TimePoint newEffectiveTimePointWhenToStartConsideringCandidates = getEffectiveFrom(newTimePointWhenToStartConsideringCandidates);
1496
+ final TimeRangeWithNullStartMeaningEmpty newTimeRange = timeRangeForValidCandidates.getWithNewFrom(newEffectiveTimePointWhenToStartConsideringCandidates);
1497
+ return getCandidateDeltasAfterTimingChange(newEffectiveTimePointWhenToStartConsideringCandidates, newTimeRange);
1498
+ }
1499
+
1500
+ private Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterTimingChange(
1501
+ final TimePoint newTimePointWhenToStartConsideringCandidates,
1502
+ final TimeRangeWithNullStartMeaningEmpty newTimeRange) {
1503
+ final Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> result;
1482 1504
if (!Util.equalsWithNull(newTimeRange, timeRangeForValidCandidates)) {
1483 1505
if (newTimeRange.getTimeRangeOrNull() == null) {
1484 1506
result = clearAllCandidates();
... ...
@@ -1500,6 +1522,15 @@ public class CandidateFinderImpl implements CandidateFinder {
1500 1522
}
1501 1523
1502 1524
@Override
1525
+ public Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterStartOfTrackingChange() {
1526
+ final TimePoint newNonInferredStartTime = race.getStartOfRace(/* inferred */ false);
1527
+ final TimePoint newTimePointWhenToStartConsideringCandidates = getTimePointWhenToStartConsideringCandidates(newNonInferredStartTime);
1528
+ final TimePoint newEffectiveTimePointWhenToStartConsideringCandidates = getEffectiveFrom(newTimePointWhenToStartConsideringCandidates);
1529
+ final TimeRangeWithNullStartMeaningEmpty newTimeRange = timeRangeForValidCandidates.getWithNewFrom(newEffectiveTimePointWhenToStartConsideringCandidates);
1530
+ return getCandidateDeltasAfterTimingChange(newEffectiveTimePointWhenToStartConsideringCandidates, newTimeRange);
1531
+ }
1532
+
1533
+ @Override
1503 1534
public Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterRaceFinishedTimeChange(
1504 1535
TimePoint oldFinishedTime, TimePoint newFinishedTime) {
1505 1536
final Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> result;
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CrossTrackErrorCache.java
... ...
@@ -205,6 +205,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
205 205
owner.addListener(this);
206 206
}
207 207
208
+ @FunctionalInterface
208 209
private interface CrossTrackErrorMeterRetriever {
209 210
double getDistanceInMetersSumFromStart(CrossTrackErrorSumAndNumberOfFixes cacheEntry);
210 211
}
... ...
@@ -220,12 +221,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
220 221
*/
221 222
public Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly,
222 223
boolean waitForLatest) throws NoWindException {
223
- CrossTrackErrorMeterRetriever absoluteMetersRetriever = new CrossTrackErrorMeterRetriever() {
224
- @Override
225
- public double getDistanceInMetersSumFromStart(CrossTrackErrorSumAndNumberOfFixes cacheEntry) {
226
- return cacheEntry.getAbsoluteDistanceInMetersSumFromStart();
227
- }
228
- };
224
+ CrossTrackErrorMeterRetriever absoluteMetersRetriever = cacheEntry->cacheEntry.getAbsoluteDistanceInMetersSumFromStart();
229 225
return getAbsoluteOrSignedAverageCrossTrackError(competitor, from, to, upwindOnly, waitForLatest, absoluteMetersRetriever);
230 226
}
231 227
... ...
@@ -240,20 +236,15 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
240 236
*/
241 237
public Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly,
242 238
boolean waitForLatest) throws NoWindException {
243
- CrossTrackErrorMeterRetriever signedMetersRetriever = new CrossTrackErrorMeterRetriever() {
244
- @Override
245
- public double getDistanceInMetersSumFromStart(CrossTrackErrorSumAndNumberOfFixes cacheEntry) {
246
- return cacheEntry.getSignedDistanceInMetersSumFromStart();
247
- }
248
- };
239
+ CrossTrackErrorMeterRetriever signedMetersRetriever = cacheEntry->cacheEntry.getSignedDistanceInMetersSumFromStart();
249 240
return getAbsoluteOrSignedAverageCrossTrackError(competitor, from, to, upwindOnly, waitForLatest, signedMetersRetriever);
250 241
}
251 242
252 243
/**
253
- * @param absoluteMetersRetriever determines whether the absolute or signed cross track error will be aggregated
244
+ * @param absoluteOrSignedMetersRetriever determines whether the absolute or signed cross track error will be aggregated
254 245
*/
255 246
private Distance getAbsoluteOrSignedAverageCrossTrackError(Competitor competitor, TimePoint from, TimePoint to,
256
- boolean upwindOnly, boolean waitForLatest, CrossTrackErrorMeterRetriever absoluteMetersRetriever)
247
+ boolean upwindOnly, boolean waitForLatest, CrossTrackErrorMeterRetriever absoluteOrSignedMetersRetriever)
257 248
throws NoWindException {
258 249
Track<CrossTrackErrorSumAndNumberOfFixes> cacheForCompetitor = cachePerCompetitor.get(competitor, waitForLatest);
259 250
double distanceInMeters = 0;
... ...
@@ -268,7 +259,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
268 259
final MarkPassing legStartMarkPassing = owner.getMarkPassing(competitor, leg.getFrom());
269 260
if (legStartMarkPassing != null) {
270 261
if (!upwindOnly || trackedLeg.getLegType(legStartMarkPassing.getTimePoint()) == LegType.UPWIND) {
271
- TimePoint start;
262
+ final TimePoint start;
272 263
final TimePoint legStart = legStartMarkPassing.getTimePoint();
273 264
if (legStart.compareTo(from) < 0) {
274 265
// the interval requested starts after this leg's start:
... ...
@@ -277,7 +268,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
277 268
start = legStart;
278 269
}
279 270
final MarkPassing legEndMarkPassing = owner.getMarkPassing(competitor, leg.getTo());
280
- TimePoint end;
271
+ final TimePoint end;
281 272
if (legEndMarkPassing == null || legEndMarkPassing.getTimePoint().compareTo(to) >= 0) {
282 273
// no next mark passing, or next mark passing is beyond the "to" time point; aggregate up to "to"
283 274
end = to;
... ...
@@ -294,7 +285,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
294 285
}
295 286
CrossTrackErrorSumAndNumberOfFixes endAggregate = cacheForCompetitor.getLastFixAtOrBefore(end);
296 287
if (endAggregate != null) {
297
- distanceInMeters += absoluteMetersRetriever.getDistanceInMetersSumFromStart(endAggregate) - absoluteMetersRetriever.getDistanceInMetersSumFromStart(startAggregate);
288
+ distanceInMeters += absoluteOrSignedMetersRetriever.getDistanceInMetersSumFromStart(endAggregate) - absoluteOrSignedMetersRetriever.getDistanceInMetersSumFromStart(startAggregate);
298 289
count += endAggregate.getFixCountFromStart() - startAggregate.getFixCountFromStart();
299 290
startAggregate = endAggregate;
300 291
}
java/com.sap.sailing.expeditionconnector.common/.project
... ...
@@ -21,12 +21,12 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
24
+ <name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
25 25
<arguments>
26 26
</arguments>
27 27
</buildCommand>
28 28
<buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
29
+ <name>com.gwtplugins.gwt.eclipse.core.gwtProjectValidator</name>
30 30
<arguments>
31 31
</arguments>
32 32
</buildCommand>
... ...
@@ -34,6 +34,6 @@
34 34
<natures>
35 35
<nature>org.eclipse.pde.PluginNature</nature>
36 36
<nature>org.eclipse.jdt.core.javanature</nature>
37
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
37
+ <nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
38 38
</natures>
39 39
</projectDescription>
java/com.sap.sailing.gwt.ui.test/.project
... ...
@@ -21,16 +21,6 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
25
- <arguments>
26
- </arguments>
27
- </buildCommand>
28
- <buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
30
- <arguments>
31
- </arguments>
32
- </buildCommand>
33
- <buildCommand>
34 24
<name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
35 25
<arguments>
36 26
</arguments>
... ...
@@ -44,7 +34,6 @@
44 34
<natures>
45 35
<nature>org.eclipse.pde.PluginNature</nature>
46 36
<nature>org.eclipse.jdt.core.javanature</nature>
47
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
48 37
<nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
49 38
</natures>
50 39
</projectDescription>
java/com.sap.sailing.gwt.ui/.project
... ...
@@ -21,16 +21,6 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
25
- <arguments>
26
- </arguments>
27
- </buildCommand>
28
- <buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
30
- <arguments>
31
- </arguments>
32
- </buildCommand>
33
- <buildCommand>
34 24
<name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
35 25
<arguments>
36 26
</arguments>
... ...
@@ -44,7 +34,6 @@
44 34
<natures>
45 35
<nature>org.eclipse.pde.PluginNature</nature>
46 36
<nature>org.eclipse.jdt.core.javanature</nature>
47
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
48 37
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
49 38
<nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
50 39
</natures>
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html
... ...
@@ -6,8 +6,13 @@
6 6
<div class="innerContent">
7 7
<h5 class="articleSubheadline">July 2018</h5>
8 8
<ul class="bulletList">
9
- <li>In <tt>RaceBoard.html</tt> there is a new feature for maneuver loss visualization. There is a setting in the map settings and in the maneuver pop up.
9
+ <li>The Maneuver Table now uses the same color coding for competitors as the leaderboard to help
10
+ recognize competitor tracks for selected maneuvers more easily.</li>
11
+ <li>In <tt>RaceBoard.html</tt> there is a new feature for maneuver loss visualization. There is a setting in the map settings and in the maneuver pop up.</li>
10 12
<li>In <tt>RaceBoard.html</tt> when zooming into a specific time range, the time slider will provide a "reset zoom" button in expanded mode.</li>
13
+ <li>Issues with sporadic incorrect zoom/pan states in the Race Board / race viewer have been fixed.</li>
14
+ <li>Fixed an issue with the "Winning Lanes" mode for large races that could lead to full tails for
15
+ all competitors to be loaded instead of only the ones for the podium competitors.</li>
11 16
</ul>
12 17
13 18
<h5 class="articleSubheadline">June 2018</h5>
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.gss
... ...
@@ -180,18 +180,18 @@
180 180
text-overflow: ellipsis;
181 181
}
182 182
183
-.regattacompetition_phase_fleetfullwidth, .regattacompetition_phase_fleet_race_title {
183
+.regattacompetition_phase_fleet_race_title_big {
184 184
width: 27%;
185 185
}
186 186
187 187
@media (min-width: 375px) {
188
- .regattacompetition_phase_fleetfullwidth, .regattacompetition_phase_fleet_race_title {
188
+ .regattacompetition_phase_fleet_race_title_big {
189 189
width: 33%;
190 190
}
191 191
}
192 192
193 193
@media (min-width: 700px) {
194
- .regattacompetition_phase_fleetfullwidth, .regattacompetition_phase_fleet_race_title {
194
+ .regattacompetition_phase_fleet_race_title_big {
195 195
width: 40%;
196 196
}
197 197
}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleet.java
... ...
@@ -17,6 +17,9 @@ import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompet
17 17
public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
18 18
19 19
private static RegattaCompetitionFleetUiBinder uiBinder = GWT.create(RegattaCompetitionFleetUiBinder.class);
20
+
21
+ private int fleetCount = -1;
22
+ private RegattaCompetitionFleetRace raceView;
20 23
21 24
interface RegattaCompetitionFleetUiBinder extends UiBinder<Widget, RegattaCompetitionFleet> {
22 25
}
... ...
@@ -32,8 +35,9 @@ public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
32 35
33 36
@Override
34 37
public RegattaCompetitionRaceView addRaceView(SimpleRaceMetadataDTO race, RegattaCompetitionPresenter presenter) {
35
- RegattaCompetitionFleetRace raceView = new RegattaCompetitionFleetRace(race, presenter);
38
+ raceView = new RegattaCompetitionFleetRace(race, presenter);
36 39
raceContainerUi.add(raceView);
40
+ updateRaceViewIfReady();
37 41
return raceView;
38 42
}
39 43
... ...
@@ -42,6 +46,8 @@ public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
42 46
getElement().getStyle().setWidth(100.0 / fleetCount, Unit.PCT);
43 47
setStyleName(local_res.css().regattacompetition_phase_fleetfullwidth(), fleetCount < 2);
44 48
setStyleName(local_res.css().regattacompetition_phase_fleetcompact(), fleetCount > 4);
49
+ this.fleetCount = fleetCount;
50
+ updateRaceViewIfReady();
45 51
}
46 52
47 53
@Override
... ...
@@ -64,5 +70,10 @@ public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
64 70
protected Element getFleetCornerUiElement() {
65 71
return fleetCornerUi;
66 72
}
67
-
73
+
74
+ private void updateRaceViewIfReady() {
75
+ if (raceView != null && fleetCount > 1) {
76
+ raceView.removeBigRaceTitleCSS();
77
+ }
78
+ }
68 79
}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleetRace.java
... ...
@@ -65,5 +65,9 @@ public class RegattaCompetitionFleetRace extends AbstractRegattaCompetitionFleet
65 65
protected String getRaceUntrackedStyleName() {
66 66
return local_res.css().regattacompetition_phase_fleet_raceuntracked();
67 67
}
68
+
69
+ public void removeBigRaceTitleCSS() {
70
+ raceNameUi.removeClassName(local_res.css().regattacompetition_phase_fleet_race_title_big());
71
+ }
68 72
69 73
}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleetRace.ui.xml
... ...
@@ -1,15 +1,15 @@
1 1
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
2 2
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
3
- xmlns:mp="urn:import:com.sap.sailing.gwt.home.mobile.partials" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
4
- <ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
5
- <ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
6
- <ui:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.regattacompetition.RegattaCompetitionResources" />
3
+ xmlns:mp="urn:import:com.sap.sailing.gwt.home.mobile.partials" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
4
+ <ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
5
+ <ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
6
+ <ui:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.regattacompetition.RegattaCompetitionResources" />
7 7
<div class="{local_res.css.regattacompetition_phase_fleet_race}" style="display:block; text-decoration:none;">
8
- <div class="{local_res.css.regattacompetition_phase_fleet_race_title}" ui:field="raceNameUi"></div>
9
- <div class="{local_res.css.regattacompetition_phase_fleet_race_subtitle}">
10
- <div class="{local_res.css.regattacompetition_phase_fleet_race_state}" ui:field="raceStateUi"></div>
11
- <div class="{local_res.css.regattacompetition_phase_fleet_race_date}" ui:field="raceDateUi"></div>
12
- </div>
8
+ <div class="{local_res.css.regattacompetition_phase_fleet_race_title} {local_res.css.regattacompetition_phase_fleet_race_title_big}" ui:field="raceNameUi"></div>
9
+ <div class="{local_res.css.regattacompetition_phase_fleet_race_subtitle}">
10
+ <div class="{local_res.css.regattacompetition_phase_fleet_race_state}" ui:field="raceStateUi"></div>
11
+ <div class="{local_res.css.regattacompetition_phase_fleet_race_date}" ui:field="raceDateUi"></div>
12
+ </div>
13 13
<div class="{local_res.css.regattacompetition_phase_fleet_race_arrow}"></div>
14
- </div>
14
+ </div>
15 15
</ui:UiBinder>
... ...
\ No newline at end of file
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionResources.java
... ...
@@ -33,5 +33,6 @@ public interface RegattaCompetitionResources extends SharedHomeResources {
33 33
String regattacompetition_phase_fleet_raceplanned();
34 34
String regattacompetition_phase_fleet_race_state();
35 35
String regattacompetition_phase_fleet_race_date();
36
+ String regattacompetition_phase_fleet_race_title_big();
36 37
}
37 38
}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/actions/GetBoatPositionsAction.java
... ...
@@ -20,7 +20,6 @@ public class GetBoatPositionsAction extends AbstractGetMapRelatedDataAction<Comp
20 20
@Override
21 21
public void execute(final AsyncCallback<CompactBoatPositionsDTO> callback) {
22 22
Map<String, Date> fromByCompetitorIdAsString = new HashMap<String, Date>();
23
- System.out.println(fromByCompetitorIdAsString);
24 23
for (Map.Entry<CompetitorDTO, Date> fromEntry : getFrom().entrySet()) {
25 24
fromByCompetitorIdAsString.put(fromEntry.getKey().getIdAsString(), fromEntry.getValue());
26 25
}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties
... ...
@@ -1163,7 +1163,8 @@ racesScoredTooltip=Número de carreras que ha completado un competidor o en las
1163 1163
averageNumberOfOperationsPerMessage=Número promedio de operaciones por mensaje
1164 1164
showUncorrectedTotalPoints=Mostrar puntos totales no corregidos
1165 1165
setStartTimeReceived=Fijar hora de inicio recibida
1166
-setStartTimeReceivedDescription=Fija la HoraInicioRecibida del RegistroRastreado seleccionado que no es persistente. Esto significa que el nuevo valor se ignorará después del reinicio del servidor.
1166
+setStartTimeReceivedDescription=Fija la startTimeReceived de la TrackedRace seleccionada en el valor proporcionado. Deje el valor en blanco para eliminar la startTimeReceived actual.
1167
+setStartTimeReceivedNotice=Esta modificación no es persistente, es decir, el valor nuevo se olvidará cuando se reinicie el servidor.
1167 1168
lastScoreCorrectionsTime=Última hora de corrección de puntuación
1168 1169
lastScoreCorrectionsComment=Último comentario de corrección de puntuación
1169 1170
setTimeToNow=Fijar la hora a "ahora"
... ...
@@ -1275,11 +1276,13 @@ uploadSuccessful=Carga correcta
1275 1276
fileUploadResult=Carga de archivos: {0} {1}. En caso de error, compruebe que su servicio de alojamiento de archivos está configurado correctamente.
1276 1277
removeUploadedFile=Eliminar archivo
1277 1278
showCompetitorBoatColumn=Embarcación del competidor
1279
+showCompetitorSailIdColumn=ID de vela
1280
+showCompetitorSailIdColumnTooltip=Muestra el ID de vela más la bandera del país o imagen del competidor. Si está disponible, se prioriza la imagen de competidor a la bandera del país. Se mostrarán ambos iconos si se fija "{0}".
1278 1281
showCompetitorShortNameColumn=Denominación breve de competidor
1279 1282
showCompetitorShortNameColumnTooltip=Muestra el nombre breve más la bandera del país o imagen del competidor. Si está disponible, se prioriza la imagen de competidor a la bandera del país. Se mostrarán ambos iconos si se fija "{0}".
1280 1283
showCompetitorFullNameColumn=Nombre completo del competidor
1281
-showCompetitorNationalityColumn=Siempre mostrar la nacionalidad del competidor
1282
-showCompetitorNationalityColumnTooltip=Muestra ambos, las banderas de país así como las imágenes de competidor, si están disponibles.
1284
+alwaysShowCompetitorNationalityColumn=Siempre mostrar la nacionalidad del competidor
1285
+alwaysShowCompetitorNationalityColumnTooltip=Muestra ambos, las banderas de país así como las imágenes de competidor, si están disponibles.
1283 1286
loadingDimensionValues=Cargando valores de dimensión
1284 1287
inviteBuoyTenders=Invitar a balizadores
1285 1288
orMultipleEmails=o varios correos electrónicos separados por una coma
... ...
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=Windfinder
1970 1973
windFinderWindSourceTypeTooltip=Viento medido de uno o más puntos de www.windfinder.com
1971 1974
windFinder=Windfinder
1972 1975
enterTagsForTheVideo=Indique las etiquetas para el vídeo
1973
-enterIdOfWindfinderReviewedSpotCollection=Indique el ID de una colección de puntos de Windfinder revisada, por ejemplo "schilksee"
1976
+enterIdOfWindFinderReviewedSpotCollection=Indique el ID de una colección de puntos de Windfinder revisada, por ejemplo "schilksee"
1974 1977
windFinderSpotCollectionsList=Colecciones de puntos de WindFinder
1975 1978
enterTagsForTheImage=Indique las etiquetas para la imagen
1976 1979
unableToResolveWindFinderSpotId=Imposible resolver el punto Windfinder con ID {0}: {1}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties
... ...
@@ -1163,7 +1163,8 @@ racesScoredTooltip=Nombre de courses que le concurrent a terminées, ou pour les
1163 1163
averageNumberOfOperationsPerMessage=Nombre moyen d''opérations par message
1164 1164
showUncorrectedTotalPoints=Afficher total des points non corrigé
1165 1165
setStartTimeReceived=Afficher heure de départ reçue
1166
-setStartTimeReceivedDescription=Définit l''heure de départ reçue de la course suivie sélectionnée non persistante. Cela signifie que la nouvelle valeur sera oubliée une fois que le serveur sera relancé.
1166
+setStartTimeReceivedDescription=Définit l''heure de départ reçue de la course suivie sélectionnée sur la valeur indiquée. Ne renseignez pas cette valeur si vous voulez supprimer l''actuelle heure de départ reçue définie.
1167
+setStartTimeReceivedNotice=Cette modification n''est pas persistante. Cela signifie que la nouvelle valeur sera oubliée une fois que le serveur sera redémarré.
1167 1168
lastScoreCorrectionsTime=Dernière heure de correction du score
1168 1169
lastScoreCorrectionsComment=Dernier commentaire sur la correction du score
1169 1170
setTimeToNow=Définir heure sur "maintenant"
... ...
@@ -1275,11 +1276,13 @@ uploadSuccessful=Chargement réussi
1275 1276
fileUploadResult=Chargement du fichier : {0} {1}.\nEn cas d''erreur, vérifiez que votre service de stockage de fichier est correctement configuré.
1276 1277
removeUploadedFile=Supprimer fichier chargé
1277 1278
showCompetitorBoatColumn=Bateau du concurrent
1279
+showCompetitorSailIdColumn=ID de voile
1280
+showCompetitorSailIdColumnTooltip=Affiche l''ID de voile ainsi que le drapeau national ou l''image du concurrent. Si les deux sont disponibles, l''image du concurrent aura la priorité sur le drapeau national. Si le code "{0}" est activé, les deux icônes seront affichées.
1278 1281
showCompetitorShortNameColumn=Nom court du concurrent
1279 1282
showCompetitorShortNameColumnTooltip=Affiche le nom court ainsi que le drapeau national ou l''image du concurrent. Si les deux sont disponibles, l''image du concurrent aura la priorité sur le drapeau national. Si le code "{0}" est activé, les deux icônes seront affichées.
1280 1283
showCompetitorFullNameColumn=Nom complet du concurrent
1281
-showCompetitorNationalityColumn=Afficher toujours la nationalité du concurrent
1282
-showCompetitorNationalityColumnTooltip=Si disponibles, afficher les deux : le drapeau national ainsi que l''image du concurrent
1284
+alwaysShowCompetitorNationalityColumn=Afficher toujours la nationalité du concurrent
1285
+alwaysShowCompetitorNationalityColumnTooltip=Si disponibles, afficher les deux : le drapeau national ainsi que l''image du concurrent
1283 1286
loadingDimensionValues=Chargement des valeurs de dimension
1284 1287
inviteBuoyTenders=Inviter navire baliseur
1285 1288
orMultipleEmails=ou plusieurs adresses e-mails séparées par des virgules
... ...
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=WindFinder
1970 1973
windFinderWindSourceTypeTooltip=Vent mesuré d''un ou plusieurs endroits de www.windfinder.com
1971 1974
windFinder=WindFinder
1972 1975
enterTagsForTheVideo=Entrez des balises pour la vidéo.
1973
-enterIdOfWindfinderReviewedSpotCollection=Entrez l''ID d''un ensemble d''endroits WindFinder révisé, par exemple, "Schilksee".
1976
+enterIdOfWindFinderReviewedSpotCollection=Entrez l''ID d''un ensemble d''endroits WindFinder révisé, par exemple, "Schilksee".
1974 1977
windFinderSpotCollectionsList=Ensemble d''endroits WindFinder
1975 1978
enterTagsForTheImage=Entrez des balises pour l''image.
1976 1979
unableToResolveWindFinderSpotId=Impossible de traiter l''endroit WindFinder ayant l''ID {0} : {1}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties
... ...
@@ -1163,7 +1163,8 @@ racesScoredTooltip=このリーダーボードにおいて競技者が完了し
1163 1163
averageNumberOfOperationsPerMessage=メッセージごとの操作の平均数
1164 1164
showUncorrectedTotalPoints=未修正総得点表示
1165 1165
setStartTimeReceived=設定済スタート時刻を受信
1166
-setStartTimeReceivedDescription=これにより、永続的でない選択した TrackedRace の startTimeReceived が設定されます。したがって、サーバが再起動された後は新規の値は忘れられます。
1166
+setStartTimeReceivedDescription=選択した TrackedRace の startTimeReceived が指定した値に設定されます。値を空白のままにすると、現在設定されている startTimeReceived は削除されます。
1167
+setStartTimeReceivedNotice=この変更は永続的なものではありません。つまり、新しい値はサーバが再起動したときに失われます。
1167 1168
lastScoreCorrectionsTime=最終得点修正時刻
1168 1169
lastScoreCorrectionsComment=最終得点修正コメント
1169 1170
setTimeToNow=時刻を ''現在'' に設定
... ...
@@ -1275,11 +1276,13 @@ uploadSuccessful=正常にアップロード済
1275 1276
fileUploadResult=ファイルアップロード: {0} {1}\nエラー発生の場合は、ファイルストレージサービスが適切に設定されていることを確認してください。
1276 1277
removeUploadedFile=アップロード済ファイルの削除
1277 1278
showCompetitorBoatColumn=競技者の艇
1279
+showCompetitorSailIdColumn=セール ID
1280
+showCompetitorSailIdColumnTooltip=セール ID に加えて国旗または競技者画像を表示します。競技者画像が利用可能な場合はそれを国旗よりも優先させます。"{0}" が設定されている場合、両方のアイコンが表示されます。
1278 1281
showCompetitorShortNameColumn=競技者の名前 (短)
1279 1282
showCompetitorShortNameColumnTooltip=名前 (短) に加えて国旗または競技者画像を表示します。競技者画像が利用可能な場合はそれを国旗よりも優先させます。"{0}" が設定されている場合、両方のアイコンが表示されます。
1280 1283
showCompetitorFullNameColumn=競技者氏名
1281
-showCompetitorNationalityColumn=競技者国籍を常に表示
1282
-showCompetitorNationalityColumnTooltip=国旗と競技者画像 (利用可能な場合) の両方を表示
1284
+alwaysShowCompetitorNationalityColumn=競技者国籍を常に表示
1285
+alwaysShowCompetitorNationalityColumnTooltip=国旗と競技者画像 (利用可能な場合) の両方を表示
1283 1286
loadingDimensionValues=次元値ロード中
1284 1287
inviteBuoyTenders=ブイ入札の招待
1285 1288
orMultipleEmails=または複数の電子メールをカンマで区切り
... ...
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=Windfinder
1970 1973
windFinderWindSourceTypeTooltip=www.windfinder.com の 1 つ以上のスポットから風を測定しました
1971 1974
windFinder=Windfinder
1972 1975
enterTagsForTheVideo=動画のタグを入力
1973
-enterIdOfWindfinderReviewedSpotCollection=レビューする Windfinder スポットコレクションの ID を入力 (例: "schilksee")
1976
+enterIdOfWindFinderReviewedSpotCollection=レビューする Windfinder スポットコレクションの ID を入力 (例: "schilksee")
1974 1977
windFinderSpotCollectionsList=WindFinder スポットコレクション
1975 1978
enterTagsForTheImage=画像のタグを入力
1976 1979
unableToResolveWindFinderSpotId=ID {0} で Windfinder スポットを決定できませんでした: {1}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties
... ...
@@ -1163,7 +1163,8 @@ racesScoredTooltip=Número de corridas que o competidor concluiu ou nas quais ob
1163 1163
averageNumberOfOperationsPerMessage=Número médio de operações por mensagem
1164 1164
showUncorrectedTotalPoints=Visualizar total de pontos não corrigidos
1165 1165
setStartTimeReceived=Definir hora de partida recebida
1166
-setStartTimeReceivedDescription=Isto define a hora de partida recebida da corrida rastreada selecionada que não é persistente. Isto significa que o novo valor será esquecido após a reinicialização do servidor.
1166
+setStartTimeReceivedDescription=Define a hora de partida recebida da corrida rastreada selecionada para o valor fornecido. Deixe o valor em branco para remover a hora de partida recebida definida atualmente.
1167
+setStartTimeReceivedNotice=Esta modificação não é persistente, ou seja, o novo valor será esquecido quando o servidor for reiniciado.
1167 1168
lastScoreCorrectionsTime=Hora de correção da última pontuação
1168 1169
lastScoreCorrectionsComment=Comentário de correção da última pontuação
1169 1170
setTimeToNow=Definir hora para ''agora''
... ...
@@ -1275,11 +1276,13 @@ uploadSuccessful=Carregamento efetuado com êxito
1275 1276
fileUploadResult=Carregamento de arquivo: {0} {1}.\nEm caso de erro, verifique se seu serviço de armazenamento de arquivos está configurado de modo apropriado.
1276 1277
removeUploadedFile=Remover arquivo carregado
1277 1278
showCompetitorBoatColumn=Barco do competidor
1279
+showCompetitorSailIdColumn=ID da vela
1280
+showCompetitorSailIdColumnTooltip=Exibe o ID da vela mais a bandeira de nacionalidade ou a imagem do competidor. Se disponível, é priorizada uma imagem do competidor em relação a uma bandeira da nacionalidade. Se "{0}" estiver definido, ambos os ícones serão exibidos.
1278 1281
showCompetitorShortNameColumn=Nome abreviado do competidor
1279 1282
showCompetitorShortNameColumnTooltip=Exibe o nome abreviado mais a bandeira de nacionalidade ou a imagem do competidor. Se disponível, é priorizada uma imagem do competidor em relação a uma bandeira da nacionalidade. Se "{0}" estiver definido, ambos os ícones serão exibidos.
1280 1283
showCompetitorFullNameColumn=Nome completo do competidor
1281
-showCompetitorNationalityColumn=Exibir sempre a nacionalidade do competidor
1282
-showCompetitorNationalityColumnTooltip=Exibir ambos, bandeiras de nacionalidade e imagens do competidor, se disponíveis
1284
+alwaysShowCompetitorNationalityColumn=Exibir sempre a nacionalidade do competidor
1285
+alwaysShowCompetitorNationalityColumnTooltip=Exibir ambos, bandeiras de nacionalidade e imagens do competidor, se disponíveis
1283 1286
loadingDimensionValues=Carregando valores de dimensão
1284 1287
inviteBuoyTenders=Convidar navios-balizadores
1285 1288
orMultipleEmails=ou vários e-mails separados por vírgula
... ...
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=WindFinder
1970 1973
windFinderWindSourceTypeTooltip=Vento medido de um ou mais locais de www.windfinder.com
1971 1974
windFinder=WindFinder
1972 1975
enterTagsForTheVideo=Inserir etiquetas para o vídeo
1973
-enterIdOfWindfinderReviewedSpotCollection=Inserir ID de uma coleção revisada de locais do WindFinder, por exemplo, "schilksee"
1976
+enterIdOfWindFinderReviewedSpotCollection=Inserir ID de uma coleção revisada de locais do WindFinder, por exemplo, "schilksee"
1974 1977
windFinderSpotCollectionsList=Coleções de locais do WindFinder
1975 1978
enterTagsForTheImage=Inserir etiquetas para a imagem
1976 1979
unableToResolveWindFinderSpotId=Impossível resolver local do WindFinder com ID {0}: {1}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties
... ...
@@ -1163,7 +1163,8 @@ racesScoredTooltip=Число гонок, которые участник зав
1163 1163
averageNumberOfOperationsPerMessage=Среднее число операций на сообщение
1164 1164
showUncorrectedTotalPoints=Показать неисправленный общий балл
1165 1165
setStartTimeReceived=Установить полученное время старта
1166
-setStartTimeReceivedDescription=Устанавливает полученное время старта для выбранной отслеживаемой гонки, которое не хранится постоянно. Это значит, что после перезагрузки сервера новое значение будет забыто.
1166
+setStartTimeReceivedDescription=Устанавливает введенное значение для полученного времени старта выбранной отслеживаемой гонки. Оставьте значение пустым, чтобы удалить текущее установленное полученное время старта.
1167
+setStartTimeReceivedNotice=Это изменение не хранится, т.е. новое значение будет забыто после перезагрузки сервера.
1167 1168
lastScoreCorrectionsTime=Время последнего исправления оценки
1168 1169
lastScoreCorrectionsComment=Комментарий последнего исправления оценки
1169 1170
setTimeToNow=Установить время ''сейчас''
... ...
@@ -1275,11 +1276,13 @@ uploadSuccessful=Отправлено успешно
1275 1276
fileUploadResult=Отправка файла: {0} {1}.\nВ случае ошибки проверьте правильность конфигурации службы хранилища файлов.
1276 1277
removeUploadedFile=Удалить отправленный файл
1277 1278
showCompetitorBoatColumn=Лодка участника
1279
+showCompetitorSailIdColumn=Ид. паруса
1280
+showCompetitorSailIdColumnTooltip=Показывает ид. паруса плюс государственный флаг или изображение участника. Изображение участника, при наличии, имеет приоритет над государственным флагом. Если установлен параметр "{0}", будут отображены оба значка.
1278 1281
showCompetitorShortNameColumn=Краткое имя участника
1279 1282
showCompetitorShortNameColumnTooltip=Показывает краткое имя плюс государственный флаг или изображение участника. Изображение участника, при наличии, имеет приоритет над государственным флагом. Если установлен параметр "{0}", будут отображены оба значка.
1280 1283
showCompetitorFullNameColumn=Полное имя участника
1281
-showCompetitorNationalityColumn=Всегда показывать государственную принадлежность участника
1282
-showCompetitorNationalityColumnTooltip=Показывать и флаги государств, и изображения участников (при наличии)
1284
+alwaysShowCompetitorNationalityColumn=Всегда показывать государственную принадлежность участника
1285
+alwaysShowCompetitorNationalityColumnTooltip=Показывать и флаги государств, и изображения участников (при наличии)
1283 1286
loadingDimensionValues=Загрузка значений измерения
1284 1287
inviteBuoyTenders=Пригласить лоцманов
1285 1288
orMultipleEmails=или несколько адресов эл. почты через запятую
... ...
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=WindFinder
1970 1973
windFinderWindSourceTypeTooltip=Измерения ветра из одного или нескольких мест www.windfinder.com
1971 1974
windFinder=WindFinder
1972 1975
enterTagsForTheVideo=Введите теги для видео
1973
-enterIdOfWindfinderReviewedSpotCollection=Введите ид. просмотренной коллекции мест WindFinder (например, "schilksee")
1976
+enterIdOfWindFinderReviewedSpotCollection=Введите ид. просмотренной коллекции мест WindFinder (например, "schilksee")
1974 1977
windFinderSpotCollectionsList=Коллекции мест WindFinder
1975 1978
enterTagsForTheImage=Введите теги для изображения
1976 1979
unableToResolveWindFinderSpotId=Не удалось разрешить место WindFinder по ид. {0}: {1}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties
... ...
@@ -1163,7 +1163,8 @@ racesScoredTooltip=参赛队完成并记录在此积分榜上的比赛轮次数
1163 1163
averageNumberOfOperationsPerMessage=各消息操作的平均数
1164 1164
showUncorrectedTotalPoints=显示未更正的总分
1165 1165
setStartTimeReceived=设置接收的开始时间
1166
-setStartTimeReceivedDescription=设置非持久的所选 TrackedRace 的 startTimeReceived。这意味着,重启服务器后,将忘记新值。
1166
+setStartTimeReceivedDescription=将所选 TrackedRace 的 startTimeReceived 设置为提供的值。将此值留空,以移除当前设置的 startTimeReceived。
1167
+setStartTimeReceivedNotice=此更改并不持久,即重启服务器后,新值将被忘记。
1167 1168
lastScoreCorrectionsTime=上次得分更正时间
1168 1169
lastScoreCorrectionsComment=上次得分更正评论
1169 1170
setTimeToNow=将时间设为“现在”
... ...
@@ -1275,11 +1276,13 @@ uploadSuccessful=上传成功
1275 1276
fileUploadResult=文件上传: {0} {1}。\n如果出错,请检查文件存储服务配置是否正确。
1276 1277
removeUploadedFile=移除上传的文件
1277 1278
showCompetitorBoatColumn=参赛队的船只
1279
+showCompetitorSailIdColumn=帆号
1280
+showCompetitorSailIdColumnTooltip=显示帆号和国籍旗帜或参赛队图像。如果可用,参赛队图像优先于国籍旗帜。如果设置 "{0}",将显示这两种图标。
1278 1281
showCompetitorShortNameColumn=参赛队短名称
1279 1282
showCompetitorShortNameColumnTooltip=显示短名称和国籍旗帜或参赛队图像。如果可用,参赛队图像优先于国籍旗帜。如果设置 "{0}",将显示这两种图标。
1280 1283
showCompetitorFullNameColumn=参赛队全名
1281
-showCompetitorNationalityColumn=始终显示参赛队国籍
1282
-showCompetitorNationalityColumnTooltip=如果可用,显示两者:国籍旗帜和参赛队图像
1284
+alwaysShowCompetitorNationalityColumn=始终显示参赛队国籍
1285
+alwaysShowCompetitorNationalityColumnTooltip=如果可用,显示两者:国籍旗帜和参赛队图像
1283 1286
loadingDimensionValues=正在加载尺寸值
1284 1287
inviteBuoyTenders=邀请浮标供应船
1285 1288
orMultipleEmails=或使用逗号隔开的多个电子邮件
... ...
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=WindFinder
1970 1973
windFinderWindSourceTypeTooltip=Www.windfinder.com 中一个或多个地点的测量风力
1971 1974
windFinder=WindFinder
1972 1975
enterTagsForTheVideo=为视频输入标记
1973
-enterIdOfWindfinderReviewedSpotCollection=输入经检查的 WindFinder 地点集合的编号,例如 "schilksee"
1976
+enterIdOfWindFinderReviewedSpotCollection=输入经检查的 WindFinder 地点集合的编号,例如 "schilksee"
1974 1977
windFinderSpotCollectionsList=WindFinder 地点集合
1975 1978
enterTagsForTheImage=为图像输入标记
1976 1979
unableToResolveWindFinderSpotId=无法解析编号为{0}的 WindFinder 地点:{1}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/JSDownloadUtils.java
... ...
@@ -10,6 +10,7 @@ import com.google.gwt.typedarrays.shared.Int8Array;
10 10
*/
11 11
public class JSDownloadUtils {
12 12
private static final Double REQUIRED_SIZE = 10000000.0;
13
+ protected static final Double MAX_MEMORY_USAGE_FOR_DL = 1024 * 1024 * 1024 * 2d;
13 14
14 15
public interface JSDownloadCallback {
15 16
void progress(Double current, Double total);
... ...
@@ -43,7 +44,7 @@ public class JSDownloadUtils {
43 44
getDataFast(url, callback, total, REQUIRED_SIZE);
44 45
} else {
45 46
//fallback will always work, if cors is supported, does not require any other server configuration
46
- getDataSlow(url, callback, REQUIRED_SIZE);
47
+ getDataSlow(url, callback, REQUIRED_SIZE, MAX_MEMORY_USAGE_FOR_DL);
47 48
}
48 49
}
49 50
});
... ...
@@ -53,75 +54,77 @@ public class JSDownloadUtils {
53 54
* Fast file download method based on range requests, only the first and the last REQUIRED_SIZE is loaded.
54 55
*/
55 56
private native static void getDataFast(String url, JSDownloadCallback callback, Double length, Double REQUIRED_SIZE) /*-{
56
- try {
57
- var xhr = new XMLHttpRequest();
58
- xhr.open("GET", url, true);
59
- xhr.setRequestHeader("Range", "bytes=0-" + REQUIRED_SIZE);
60
- xhr.responseType = "arraybuffer";
61
- xhr.onprogress = function(evt) {
62
- callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::progress(Ljava/lang/Double;Ljava/lang/Double;)(evt.loaded, evt.total);
63
- }
64
- xhr.error = function(error) {
65
- callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
66
- }
67
-
68
- xhr.onreadystatechange = function() {
69
- var state = xhr.readyState;
70
- if (state == 4) {
71
- if (xhr.response) {
72
- var startLength = xhr.response.byteLength;
73
- var start = new Int8Array(xhr.response);
57
+ try {
58
+ var xhr = new XMLHttpRequest();
59
+ xhr.open("GET", url, true);
60
+ xhr.setRequestHeader("Range", "bytes=0-" + REQUIRED_SIZE);
61
+ xhr.responseType = "arraybuffer";
62
+ xhr.onprogress = function(evt) {
63
+ callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::progress(Ljava/lang/Double;Ljava/lang/Double;)(evt.loaded, evt.total);
64
+ }
65
+ xhr.error = function(error) {
66
+ callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
67
+ }
74 68
75
- try {
76
- var xhr2 = new XMLHttpRequest();
77
- xhr2.open("GET", url, true);
78
- xhr2.setRequestHeader("Range", "bytes=" + (length - REQUIRED_SIZE));
79
- xhr2.responseType = "arraybuffer";
80
- xhr2.onprogress = function(evt) {
81
- callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::progress(Ljava/lang/Double;Ljava/lang/Double;)(evt.loaded, evt.total);
82
- }
83
- xhr2.error = function(error) {
69
+ xhr.onreadystatechange = function() {
70
+ var state = xhr.readyState;
71
+ if (state == 4) {
72
+ if (xhr.response) {
73
+ var startLength = xhr.response.byteLength;
74
+ var start = new Int8Array(xhr.response);
75
+
76
+ try {
77
+ var xhr2 = new XMLHttpRequest();
78
+ xhr2.open("GET", url, true);
79
+ xhr2.setRequestHeader("Range", "bytes="
80
+ + (length - REQUIRED_SIZE) + "-");
81
+ xhr2.responseType = "arraybuffer";
82
+ xhr2.onprogress = function(evt) {
83
+ callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::progress(Ljava/lang/Double;Ljava/lang/Double;)(evt.loaded, evt.total);
84
+ }
85
+ xhr2.error = function(error) {
86
+ callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
87
+ }
88
+
89
+ xhr2.onreadystatechange = function() {
90
+ var state = xhr2.readyState;
91
+ if (state == 4) {
92
+ if (xhr2.response) {
93
+ var endLength = xhr2.response.byteLength;
94
+ var end = new Int8Array(xhr2.response);
95
+ var sparse = length - startLength
96
+ - endLength;
97
+ callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::complete(Lcom/google/gwt/typedarrays/shared/Int8Array;Lcom/google/gwt/typedarrays/shared/Int8Array;Ljava/lang/Double;)(start, end, sparse);
98
+ }
99
+ }
100
+ };
101
+ xhr2.send();
102
+ } catch (error) {
84 103
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
85 104
}
86
-
87
- xhr2.onreadystatechange = function() {
88
- var state = xhr2.readyState;
89
- if (state == 4) {
90
- if (xhr2.response) {
91
- var endLength = xhr2.response.byteLength;
92
- var end = new Int8Array(xhr2.response);
93
- var sparse = length - startLength - endLength;
94
- callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::complete(Lcom/google/gwt/typedarrays/shared/Int8Array;Lcom/google/gwt/typedarrays/shared/Int8Array;Ljava/lang/Double;)(start, end, sparse);
95
- }
96
- }
97
- };
98
- xhr2.send();
99
- } catch (error) {
100
- callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
101 105
}
102 106
}
103
- }
104
- };
105
- xhr.send();
106
- } catch (error) {
107
- callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
108
- }
109
-}-*/;
107
+ };
108
+ xhr.send();
109
+ } catch (error) {
110
+ callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
111
+ }
112
+ }-*/;
110 113
111 114
/**
112 115
* Determines if a server can deliver a file with range requests, and if so returns the size of the file
113 116
*/
114 117
private native static void getFileSizeIfFastPath(String url, JSSizeCallback callback) /*-{
115
- try {
118
+ try {
116 119
var xhr = new XMLHttpRequest();
117 120
xhr.open("HEAD", url, true);
118 121
xhr.responseType = "arraybuffer";
119 122
xhr.error = function(error) {
120 123
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSSizeCallback::size(Ljava/lang/Double;)(-1.0);
121 124
}
122
-
125
+
123 126
xhr.onreadystatechange = function() {
124
- var state = xhr.readyState;
127
+ var state = xhr.readyState;
125 128
if (state == 4) {
126 129
if (xhr.response) {
127 130
var length = xhr.getResponseHeader("Content-Length");
... ...
@@ -141,29 +144,36 @@ public class JSDownloadUtils {
141 144
/**
142 145
* If range requests are not possible, the whole file is downloaded and then slices to the required parts
143 146
*/
144
- private native static void getDataSlow(String url, JSDownloadCallback callback, Double REQUIRED_SIZE) /*-{
147
+ private native static void getDataSlow(String url, JSDownloadCallback callback, Double REQUIRED_SIZE,
148
+ Double maxMemoryUsage) /*-{
145 149
try {
146 150
var xhr = new XMLHttpRequest();
147 151
xhr.open("GET", url, true);
148 152
xhr.responseType = "arraybuffer";
149 153
xhr.onprogress = function(evt) {
154
+ //ensure not more memory is used by the tab than commonly available in browsers
155
+ if (evt.total > maxMemoryUsage || evt.loaded > maxMemoryUsage) {
156
+ xhr.abort();
157
+ }
150 158
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::progress(Ljava/lang/Double;Ljava/lang/Double;)(evt.loaded, evt.total);
151 159
}
152 160
xhr.error = function(error) {
153 161
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
154 162
}
155
-
163
+
156 164
xhr.onreadystatechange = function() {
157
- var state = xhr.readyState;
165
+ var state = xhr.readyState;
158 166
if (state == 4) {
159 167
if (xhr.response) {
160 168
var length = xhr.response.byteLength;
161
- var start = new Int8Array(xhr.response.slice(0, REQUIRED_SIZE));
162
- var end = new Int8Array(xhr.response.slice(length - REQUIRED_SIZE));
169
+ var start = new Int8Array(xhr.response.slice(0,
170
+ REQUIRED_SIZE));
171
+ var end = new Int8Array(xhr.response.slice(length
172
+ - REQUIRED_SIZE));
163 173
var sparse = length - 2 * REQUIRED_SIZE;
164 174
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::complete(Lcom/google/gwt/typedarrays/shared/Int8Array;Lcom/google/gwt/typedarrays/shared/Int8Array;Ljava/lang/Double;)(start, end, sparse);
165 175
} else {
166
- callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)("No result");
176
+ callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)("No result");
167 177
}
168 178
}
169 179
};
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPassingsPanel.java
... ...
@@ -11,6 +11,7 @@ import com.google.gwt.cell.client.AbstractCell;
11 11
import com.google.gwt.event.dom.client.ClickEvent;
12 12
import com.google.gwt.event.dom.client.ClickHandler;
13 13
import com.google.gwt.i18n.client.DateTimeFormat;
14
+import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
14 15
import com.google.gwt.safehtml.shared.SafeHtml;
15 16
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
16 17
import com.google.gwt.user.cellview.client.CellTable;
... ...
@@ -134,7 +135,7 @@ public class EditMarkPassingsPanel extends AbstractCompositeComponent<AbstractSe
134 135
};
135 136
}
136 137
}, stringMessages.waypoint());
137
- final DateTimeFormat timeFormat = DateTimeFormat.getFormat("HH:mm:ss");
138
+ final DateTimeFormat timeFormat = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_FULL);
138 139
wayPointSelectionTable.addColumn(new Column<Util.Pair<Integer, Date>, SafeHtml>(new AnchorCell()) {
139 140
@Override
140 141
public SafeHtml getValue(final Pair<Integer, Date> object) {
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPositionPanel.java
... ...
@@ -5,9 +5,11 @@ import java.util.Collection;
5 5
import java.util.Comparator;
6 6
import java.util.Date;
7 7
import java.util.HashMap;
8
+import java.util.HashSet;
8 9
import java.util.List;
9 10
import java.util.Map;
10 11
import java.util.Map.Entry;
12
+import java.util.Set;
11 13
import java.util.SortedMap;
12 14
import java.util.TreeMap;
13 15
... ...
@@ -132,6 +134,8 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
132 134
private final RaceIdentifierToLeaderboardRaceColumnAndFleetMapper raceIdentifierToLeaderboardRaceColumnAndFleetMapper;
133 135
protected boolean nonTrackingWarningWasDisplayed;
134 136
137
+ private final Set<MarkDTO> marksCurrentlyRequestedViaRemoteCall = new HashSet<>();
138
+
135 139
public EditMarkPositionPanel(Component<?> parent, ComponentContext<?> context, final RaceMap raceMap,
136 140
final SingleRaceLeaderboardPanel leaderboardPanel,
137 141
RegattaAndRaceIdentifier selectedRaceIdentifier, String leaderboardName, final StringMessages stringMessages,
... ...
@@ -735,10 +739,7 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
735 739
}
736 740
raceMap.unregisterAllCourseMarkInfoWindowClickHandlers();
737 741
} else {
738
- if (currentFixPositionChooser != null) {
739
- currentFixPositionChooser.cancel();
740
- currentFixPositionChooser = null;
741
- }
742
+ cancelFixPositionChooserAndNotification();
742 743
marksPanel.deselectMark();
743 744
selectedMark = null;
744 745
if (sideBySideComponentViewer != null) {
... ...
@@ -754,6 +755,17 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
754 755
super.setVisible(visible);
755 756
}
756 757
758
+ private void cancelFixPositionChooserAndNotification() {
759
+ if (currentFixPositionChooser != null) {
760
+ currentFixPositionChooser.cancel();
761
+ currentFixPositionChooser = null;
762
+ if (notificationTimer.isRunning()) {
763
+ notificationTimer.run();
764
+ notificationTimer.cancel();
765
+ }
766
+ }
767
+ }
768
+
757 769
private void checkIfTracking(Runnable continuation) {
758 770
if (nonTrackingWarningWasDisplayed) {
759 771
continuation.run();
... ...
@@ -859,11 +871,10 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
859 871
}
860 872
861 873
private void selectMark(MarkDTO mark) {
862
- selectedMark = mark;
863
- if (currentFixPositionChooser != null) {
864
- currentFixPositionChooser.cancel();
865
- currentFixPositionChooser = null;
874
+ if (selectedMark != mark) {
875
+ cancelFixPositionChooserAndNotification();
866 876
}
877
+ selectedMark = mark;
867 878
if (selectedMark != null) {
868 879
if (marksFromToTimes.get(selectedMark) != null) {
869 880
// For some reason the time slider does not change with this method only if you comment out line 430 and 432 in TimePanel it works
... ...
@@ -905,24 +916,43 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
905 916
@Override
906 917
public void onSelectionChange(SelectionChangeEvent event) {
907 918
final MarkDTO mark = marksPanel.getSelectedMark();
919
+ retrieveAndSelectMarkIfNecessary(mark, null);
920
+ }
921
+
922
+ protected void retrieveAndSelectMarkIfNecessary(final MarkDTO mark, final Runnable callback) {
908 923
if (mark != null && (marks.get(mark) == null || marks.get(mark).isEmpty())) {
909
- if (mark != null) {
910
- markPositionService.getMarkTrack(raceIdentifierToLeaderboardRaceColumnAndFleetMapper.getLeaderboardNameAndRaceColumnNameAndFleetName(selectedRaceIdentifier),
924
+
925
+ if (marksCurrentlyRequestedViaRemoteCall.add(mark)) {
926
+ markPositionService.getMarkTrack(
927
+ raceIdentifierToLeaderboardRaceColumnAndFleetMapper
928
+ .getLeaderboardNameAndRaceColumnNameAndFleetName(selectedRaceIdentifier),
911 929
mark.getIdAsString(), new AsyncCallback<MarkTrackDTO>() {
912 930
@Override
913 931
public void onFailure(Throwable caught) {
914
- errorReporter.reportError(stringMessages.errorCommunicatingWithServer()+": "+caught.getMessage());
932
+ marksCurrentlyRequestedViaRemoteCall.remove(mark);
933
+ errorReporter.reportError(
934
+ stringMessages.errorCommunicatingWithServer() + ": " + caught.getMessage());
915 935
}
916
-
936
+
917 937
@Override
918 938
public void onSuccess(MarkTrackDTO result) {
939
+ marksCurrentlyRequestedViaRemoteCall.remove(mark);
919 940
createMarkTrackUi(mark, result.getFixes());
920 941
selectMark(mark);
942
+ if (callback != null) {
943
+ callback.run();
944
+ }
921 945
}
922 946
});
923 947
}
948
+ else {
949
+ // remote call of the same mark already in progress -> ignore this request
950
+ }
924 951
} else {
925 952
selectMark(mark);
953
+ if (callback != null) {
954
+ callback.run();
955
+ }
926 956
}
927 957
}
928 958
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MarksPanel.java
... ...
@@ -85,22 +85,27 @@ public class MarksPanel extends AbstractCompositeComponent<AbstractSettings> {
85 85
@Override
86 86
public void update(int index, final MarkDTO mark, String value) {
87 87
final Date timePoint = parent.timer.getTime();
88
- select(mark);
89
- if (parent.hasFixAtTimePoint(mark, timePoint)) {
90
- parent.showNotification(stringMessages.pleaseSelectOtherTimepoint(), NotificationType.ERROR);
91
- } else {
92
- parent.createFixPositionChooserToAddFixToMark(mark, new Callback<Position, Exception>() {
93
- @Override
94
- public void onFailure(Exception reason) {
95
- parent.resetCurrentFixPositionChooser();
88
+ parent.retrieveAndSelectMarkIfNecessary(mark, new Runnable() {
89
+
90
+ @Override
91
+ public void run() {
92
+ if (parent.hasFixAtTimePoint(mark, timePoint)) {
93
+ parent.showNotification(stringMessages.pleaseSelectOtherTimepoint(), NotificationType.ERROR);
94
+ } else {
95
+ parent.createFixPositionChooserToAddFixToMark(mark, new Callback<Position, Exception>() {
96
+ @Override
97
+ public void onFailure(final Exception reason) {
98
+ parent.resetCurrentFixPositionChooser();
99
+ }
100
+ @Override
101
+ public void onSuccess(Position result) {
102
+ parent.addMarkFix(mark, timePoint, result);
103
+ parent.resetCurrentFixPositionChooser();
104
+ }
105
+ });
96 106
}
97
- @Override
98
- public void onSuccess(Position result) {
99
- parent.addMarkFix(mark, timePoint, result);
100
- parent.resetCurrentFixPositionChooser();
101
- }
102
- });
103
- }
107
+ }
108
+ });
104 109
}
105 110
});
106 111
markTable.addColumn(addFixColumn);
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java
... ...
@@ -622,116 +622,123 @@ public class RaceMap extends AbstractCompositeComponent<RaceMapSettings> impleme
622 622
loadLibraries.add(LoadLibrary.GEOMETRY);
623 623
624 624
Runnable onLoad = new Runnable() {
625
- @Override
626
- public void run() {
627
- MapOptions mapOptions = getMapOptions(showMapControls, /* wind up */ false);
628
- map = new MapWidget(mapOptions);
629
- rootPanel.add(map, 0, 0);
630
- if (showHeaderPanel) {
631
- Image sapLogo = createSAPLogo();
632
- rootPanel.add(sapLogo);
633
- }
634
-
635
- map.setControls(ControlPosition.LEFT_TOP, topLeftControlsWrapperPanel);
636
- adjustLeftControlsIndent();
637
-
638
- RaceMap.this.raceMapImageManager.loadMapIcons(map);
639
- map.setSize("100%", "100%");
640
- map.addZoomChangeHandler(new ZoomChangeMapHandler() {
641
- @Override
642
- public void onEvent(ZoomChangeMapEvent event) {
643
- if (!autoZoomIn && !autoZoomOut && !orientationChangeInProgress) {
644
- // stop automatic zoom after a manual zoom event; automatic zoom in zoomMapToNewBounds will restore old settings
645
- final List<RaceMapZoomSettings.ZoomTypes> emptyList = Collections.emptyList();
646
- RaceMapZoomSettings clearedZoomSettings = new RaceMapZoomSettings(emptyList, settings.getZoomSettings().isZoomToSelectedCompetitors());
647
- settings = new RaceMapSettings(settings, clearedZoomSettings);
648
- }
649
- // TODO bug489 when in wind-up mode, avoid zooming out too far; perhaps zoom back in if zoomed out too far
650
- }
651
- });
652
- map.addDragEndHandler(new DragEndMapHandler() {
653
- @Override
654
- public void onEvent(DragEndMapEvent event) {
655
- // stop automatic zoom after a manual drag event
656
- autoZoomIn = false;
657
- autoZoomOut = false;
658
- final List<RaceMapZoomSettings.ZoomTypes> emptyList = Collections.emptyList();
659
- RaceMapZoomSettings clearedZoomSettings = new RaceMapZoomSettings(emptyList, settings.getZoomSettings().isZoomToSelectedCompetitors());
660
- settings = new RaceMapSettings(settings, clearedZoomSettings);
661
- }
662
- });
663
- map.addIdleHandler(new IdleMapHandler() {
664
- @Override
665
- public void onEvent(IdleMapEvent event) {
666
- // the "idle"-event is raised at the end of map-animations
667
- if (autoZoomIn) {
668
- // finalize zoom-in that was started with panTo() in zoomMapToNewBounds()
669
- map.setZoom(autoZoomLevel);
670
- autoZoomIn = false;
671
- }
672
- if (autoZoomOut) {
673
- // finalize zoom-out that was started with setZoom() in zoomMapToNewBounds()
674
- map.panTo(autoZoomLatLngBounds.getCenter());
675
- autoZoomOut = false;
676
- }
677
- }
678
- });
679
- map.addBoundsChangeHandler(new BoundsChangeMapHandler() {
680
- @Override
681
- public void onEvent(BoundsChangeMapEvent event) {
682
- int newZoomLevel = map.getZoom();
683
- if (!isAutoZoomInProgress() && (newZoomLevel != currentZoomLevel)) {
684
- removeTransitions();
685
- }
686
- if ((streamletOverlay != null) && !map.getBounds().equals(currentMapBounds)) {
687
- streamletOverlay.onBoundsChanged(newZoomLevel != currentZoomLevel);
688
- }
689
- if ((simulationOverlay != null) && !map.getBounds().equals(currentMapBounds)) {
690
- simulationOverlay.onBoundsChanged(newZoomLevel != currentZoomLevel);
691
- }
692
- currentMapBounds = map.getBounds();
693
- currentZoomLevel = newZoomLevel;
694
- headerPanel.getElement().getStyle().setWidth(map.getOffsetWidth(), Unit.PX);
695
- }
696
- });
697
-
698
- // If there was a time change before the API was loaded, reset the time
699
- if (lastTimeChangeBeforeInitialization != null) {
700
- timeChanged(lastTimeChangeBeforeInitialization, null);
701
- lastTimeChangeBeforeInitialization = null;
702
- }
703
- // Initialize streamlet canvas for wind visualization; it shouldn't be doing anything unless it's visible
704
- streamletOverlay = new WindStreamletsRaceboardOverlay(getMap(), /* zIndex */ 0,
705
- timer, raceIdentifier, sailingService, asyncActionsExecutor, stringMessages, coordinateSystem);
706
- streamletOverlay.addToMap();
707
- if (settings.isShowWindStreamletOverlay()) {
708
- streamletOverlay.setColors(settings.isShowWindStreamletColors());
709
- streamletOverlay.setVisible(true);
710
- }
711
-
712
- if (isSimulationEnabled) {
713
- // determine availability of polar diagram
714
- setHasPolar();
715
- // initialize simulation canvas
716
- simulationOverlay = new RaceSimulationOverlay(getMap(), /* zIndex */ 0, raceIdentifier, sailingService, stringMessages, asyncActionsExecutor, coordinateSystem);
717
- simulationOverlay.addToMap();
718
- showSimulationOverlay(settings.isShowSimulationOverlay());
719
- }
720
- if (showHeaderPanel) {
721
- createHeaderPanel(map);
722
- }
723
- if (showMapControls) {
724
- createSettingsButton(map);
725
- }
726
- // Data has been initialized
727
- RaceMap.this.isMapInitialized = true;
728
- RaceMap.this.redraw();
729
- trueNorthIndicatorPanel.redraw();
730
- showAdditionalControls(map);
731
- RaceMap.this.managedInfoWindow = new ManagedInfoWindow(map);
732
- }
625
+ @Override
626
+ public void run() {
627
+ MapOptions mapOptions = getMapOptions(showMapControls, /* wind up */ false);
628
+ map = new MapWidget(mapOptions);
629
+ rootPanel.add(map, 0, 0);
630
+ if (showHeaderPanel) {
631
+ Image sapLogo = createSAPLogo();
632
+ rootPanel.add(sapLogo);
633
+ }
634
+
635
+ map.setControls(ControlPosition.LEFT_TOP, topLeftControlsWrapperPanel);
636
+ adjustLeftControlsIndent();
637
+
638
+ RaceMap.this.raceMapImageManager.loadMapIcons(map);
639
+ map.setSize("100%", "100%");
640
+ map.addZoomChangeHandler(new ZoomChangeMapHandler() {
641
+ @Override
642
+ public void onEvent(ZoomChangeMapEvent event) {
643
+ if (!autoZoomIn && !autoZoomOut && !orientationChangeInProgress) {
644
+ // stop automatic zoom after a manual zoom event; automatic zoom in zoomMapToNewBounds will
645
+ // restore old settings
646
+ final List<RaceMapZoomSettings.ZoomTypes> emptyList = Collections.emptyList();
647
+ RaceMapZoomSettings clearedZoomSettings = new RaceMapZoomSettings(emptyList,
648
+ settings.getZoomSettings().isZoomToSelectedCompetitors());
649
+ settings = new RaceMapSettings(settings, clearedZoomSettings);
650
+ }
651
+ // TODO bug489 when in wind-up mode, avoid zooming out too far; perhaps zoom back in if zoomed
652
+ // out too far
653
+ }
654
+ });
655
+ map.addDragEndHandler(new DragEndMapHandler() {
656
+ @Override
657
+ public void onEvent(DragEndMapEvent event) {
658
+ // stop automatic zoom after a manual drag event
659
+ autoZoomIn = false;
660
+ autoZoomOut = false;
661
+ final List<RaceMapZoomSettings.ZoomTypes> emptyList = Collections.emptyList();
662
+ RaceMapZoomSettings clearedZoomSettings = new RaceMapZoomSettings(emptyList,
663
+ settings.getZoomSettings().isZoomToSelectedCompetitors());
664
+ settings = new RaceMapSettings(settings, clearedZoomSettings);
665
+ }
666
+ });
667
+ map.addIdleHandler(new IdleMapHandler() {
668
+ @Override
669
+ public void onEvent(IdleMapEvent event) {
670
+ // the "idle"-event is raised at the end of map-animations
671
+ if (autoZoomIn) {
672
+ // finalize zoom-in that was started with panTo() in zoomMapToNewBounds()
673
+ map.setZoom(autoZoomLevel);
674
+ autoZoomIn = false;
675
+ }
676
+ if (autoZoomOut) {
677
+ // finalize zoom-out that was started with setZoom() in zoomMapToNewBounds()
678
+ map.panTo(autoZoomLatLngBounds.getCenter());
679
+ autoZoomOut = false;
680
+ }
681
+ redraw();
682
+ }
683
+ });
684
+ map.addBoundsChangeHandler(new BoundsChangeMapHandler() {
685
+ @Override
686
+ public void onEvent(BoundsChangeMapEvent event) {
687
+ int newZoomLevel = map.getZoom();
688
+ if (!isAutoZoomInProgress() && (newZoomLevel != currentZoomLevel)) {
689
+ removeTransitions();
690
+ }
691
+ if ((streamletOverlay != null) && !map.getBounds().equals(currentMapBounds)) {
692
+ streamletOverlay.onBoundsChanged(newZoomLevel != currentZoomLevel);
693
+ }
694
+ if ((simulationOverlay != null) && !map.getBounds().equals(currentMapBounds)) {
695
+ simulationOverlay.onBoundsChanged(newZoomLevel != currentZoomLevel);
696
+ }
697
+ currentMapBounds = map.getBounds();
698
+ currentZoomLevel = newZoomLevel;
699
+ headerPanel.getElement().getStyle().setWidth(map.getOffsetWidth(), Unit.PX);
700
+ }
701
+ });
702
+
703
+ // If there was a time change before the API was loaded, reset the time
704
+ if (lastTimeChangeBeforeInitialization != null) {
705
+ timeChanged(lastTimeChangeBeforeInitialization, null);
706
+ lastTimeChangeBeforeInitialization = null;
707
+ }
708
+ // Initialize streamlet canvas for wind visualization; it shouldn't be doing anything unless it's
709
+ // visible
710
+ streamletOverlay = new WindStreamletsRaceboardOverlay(getMap(), /* zIndex */ 0, timer, raceIdentifier,
711
+ sailingService, asyncActionsExecutor, stringMessages, coordinateSystem);
712
+ streamletOverlay.addToMap();
713
+ if (settings.isShowWindStreamletOverlay()) {
714
+ streamletOverlay.setColors(settings.isShowWindStreamletColors());
715
+ streamletOverlay.setVisible(true);
716
+ }
717
+
718
+ if (isSimulationEnabled) {
719
+ // determine availability of polar diagram
720
+ setHasPolar();
721
+ // initialize simulation canvas
722
+ simulationOverlay = new RaceSimulationOverlay(getMap(), /* zIndex */ 0, raceIdentifier,
723
+ sailingService, stringMessages, asyncActionsExecutor, coordinateSystem);
724
+ simulationOverlay.addToMap();
725
+ showSimulationOverlay(settings.isShowSimulationOverlay());
726
+ }
727
+ if (showHeaderPanel) {
728
+ createHeaderPanel(map);
729
+ }
730
+ if (showMapControls) {
731
+ createSettingsButton(map);
732
+ }
733
+ // Data has been initialized
734
+ RaceMap.this.isMapInitialized = true;
735
+ RaceMap.this.redraw();
736
+ trueNorthIndicatorPanel.redraw();
737
+ showAdditionalControls(map);
738
+ RaceMap.this.managedInfoWindow = new ManagedInfoWindow(map);
739
+ }
733 740
};
734
- LoadApi.go(onLoad, loadLibraries, sensor, GoogleMapAPIKey.V3_PARAMS);
741
+ LoadApi.go(onLoad, loadLibraries, sensor, GoogleMapAPIKey.V3_PARAMS);
735 742
}
736 743
737 744
/**
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTableData.java
... ...
@@ -12,6 +12,7 @@ import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
12 12
class ManeuverTableData {
13 13
14 14
private final String competitorName;
15
+ private final String competitorColor;
15 16
private final Date timePoint;
16 17
private final Date timePointBefore;
17 18
private final ManeuverType maneuverType;
... ...
@@ -24,8 +25,9 @@ class ManeuverTableData {
24 25
private final double directionChange;
25 26
private final boolean markPassing;
26 27
27
- ManeuverTableData(final CompetitorDTO competitor, final ManeuverDTO maneuver) {
28
+ ManeuverTableData(final CompetitorDTO competitor, final String competitorColor, final ManeuverDTO maneuver) {
28 29
this.competitorName = competitor.getName();
30
+ this.competitorColor = competitorColor;
29 31
this.timePoint = maneuver.getTimePoint();
30 32
this.timePointBefore = maneuver.getTimePointBefore();
31 33
this.maneuverType = maneuver.getType();
... ...
@@ -43,6 +45,10 @@ class ManeuverTableData {
43 45
return competitorName;
44 46
}
45 47
48
+ public String getCompetitorColor() {
49
+ return competitorColor;
50
+ }
51
+
46 52
public Date getTimePoint() {
47 53
return timePoint;
48 54
}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/maneuver/ManeuverTablePanel.java
... ...
@@ -38,8 +38,8 @@ import com.sap.sailing.domain.common.security.Permission;
38 38
import com.sap.sailing.domain.common.security.SailingPermissionsForRoleProvider;
39 39
import com.sap.sailing.gwt.ui.actions.GetManeuversForCompetitorsAction;
40 40
import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener;
41
-import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider;
42 41
import com.sap.sailing.gwt.ui.client.ManeuverTypeFormatter;
42
+import com.sap.sailing.gwt.ui.client.RaceCompetitorSelectionProvider;
43 43
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
44 44
import com.sap.sailing.gwt.ui.client.StringMessages;
45 45
import com.sap.sailing.gwt.ui.client.shared.controls.AbstractSortableColumnWithMinMax;
... ...
@@ -47,6 +47,7 @@ import com.sap.sailing.gwt.ui.client.shared.controls.SortableColumn;
47 47
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel.LeaderBoardStyle;
48 48
import com.sap.sailing.gwt.ui.leaderboard.SortedCellTableWithStylableHeaders;
49 49
import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
50
+import com.sap.sse.common.Color;
50 51
import com.sap.sse.common.TimeRange;
51 52
import com.sap.sse.common.Util;
52 53
import com.sap.sse.common.filter.Filter;
... ...
@@ -75,7 +76,8 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
75 76
private final ManeuverTablePanelResources resources = GWT.create(ManeuverTablePanelResources.class);
76 77
77 78
private final StringMessages stringMessages;
78
- private final CompetitorSelectionProvider competitorSelectionModel;
79
+ private final RegattaAndRaceIdentifier raceIdentifier;
80
+ private final RaceCompetitorSelectionProvider competitorSelectionModel;
79 81
80 82
private final SimplePanel contentPanel = new SimplePanel();
81 83
private final Label importantMessageLabel = new Label();
... ...
@@ -89,7 +91,7 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
89 91
public ManeuverTablePanel(final Component<?> parent, ComponentContext<?> context,
90 92
final SailingServiceAsync sailingService, final AsyncActionsExecutor asyncActionsExecutor,
91 93
final RegattaAndRaceIdentifier raceIdentifier, final StringMessages stringMessages,
92
- final CompetitorSelectionProvider competitorSelectionModel, final ErrorReporter errorReporter,
94
+ final RaceCompetitorSelectionProvider competitorSelectionModel, final ErrorReporter errorReporter,
93 95
final Timer timer, final ManeuverTableSettings initialSettings,
94 96
final TimeRangeWithZoomModel timeRangeWithZoomProvider, final LeaderBoardStyle style,
95 97
final UserService userService) {
... ...
@@ -106,10 +108,11 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
106 108
userStatusChangeHandler.onUserStatusChange(userService.getCurrentUser(), /* preAuthenticated */ true);
107 109
this.resources.css().ensureInjected();
108 110
this.settings = initialSettings;
111
+ this.raceIdentifier = raceIdentifier;
109 112
this.competitorSelectionModel = competitorSelectionModel;
110 113
this.stringMessages = stringMessages;
111 114
this.competitorDataProvider = new CachedManeuverTableDataProvider(timeRangeWithZoomProvider, timer,
112
- raceIdentifier, sailingService, asyncActionsExecutor);
115
+ sailingService, asyncActionsExecutor);
113 116
this.competitorSelectionModel.addCompetitorSelectionChangeListener(this);
114 117
timer.addTimeListener(this);
115 118
final FlowPanel rootPanel = new FlowPanel();
... ...
@@ -263,14 +266,23 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
263 266
return column;
264 267
}
265 268
266
- private SortableColumn<ManeuverTableData, String> createCompetitorColumn() {
269
+ private SortableColumn<ManeuverTableData, ManeuverTableData> createCompetitorColumn() {
267 270
InvertibleComparator<ManeuverTableData> comparator = new InvertibleComparatorAdapter<ManeuverTableData>() {
268 271
@Override
269 272
public int compare(ManeuverTableData o1, ManeuverTableData o2) {
270 273
return o1.getCompetitorName().compareTo(o2.getCompetitorName());
271 274
}
272 275
};
273
- return new SortableColumn<ManeuverTableData, String>(new TextCell(), SortingOrder.ASCENDING) {
276
+ return new SortableColumn<ManeuverTableData, ManeuverTableData>(new AbstractCell<ManeuverTableData>() {
277
+ @Override
278
+ public void render(Context context, ManeuverTableData data, SafeHtmlBuilder sb) {
279
+ final String color = data.getCompetitorColor();
280
+ final String divStyle = color == null ? "border: none;" : "border-bottom: 2px solid " + color + ";";
281
+ sb.appendHtmlConstant("<div style=\"" + divStyle + "\">");
282
+ sb.appendEscaped(data.getCompetitorName());
283
+ sb.appendHtmlConstant("</div>");
284
+ }
285
+ }, SortingOrder.ASCENDING) {
274 286
@Override
275 287
public InvertibleComparator<ManeuverTableData> getComparator() {
276 288
return comparator;
... ...
@@ -282,8 +294,8 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
282 294
}
283 295
284 296
@Override
285
- public String getValue(ManeuverTableData object) {
286
- return object.getCompetitorName();
297
+ public ManeuverTableData getValue(ManeuverTableData object) {
298
+ return object;
287 299
}
288 300
};
289 301
}
... ...
@@ -321,7 +333,8 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
321 333
for (final Entry<CompetitorDTO, Iterable<ManeuverDTO>> entry : cachedData.entrySet()) {
322 334
for (ManeuverDTO maneuver : entry.getValue()) {
323 335
if (settings.getSelectedManeuverTypes().contains(maneuver.getType())) {
324
- data.add(new ManeuverTableData(entry.getKey(), maneuver));
336
+ final Color competitorColor = competitorSelectionModel.getColor(entry.getKey(), raceIdentifier);
337
+ data.add(new ManeuverTableData(entry.getKey(), competitorColor.getAsHtml(), maneuver));
325 338
}
326 339
}
327 340
}
... ...
@@ -429,15 +442,12 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
429 442
430 443
private class CachedManeuverTableDataProvider extends CachedRaceDataProvider<CompetitorDTO, ManeuverDTO> {
431 444
private final AsyncActionsExecutor asyncActionsExecutor;
432
- private final RegattaAndRaceIdentifier raceIdentifier;
433 445
private final SailingServiceAsync sailingService;
434 446
435 447
private CachedManeuverTableDataProvider(final TimeRangeProvider timeRangeProvider, final Timer timer,
436
- final RegattaAndRaceIdentifier raceIdentifier, final SailingServiceAsync sailingService,
437
- final AsyncActionsExecutor asyncActionsExecutor) {
448
+ final SailingServiceAsync sailingService, final AsyncActionsExecutor asyncActionsExecutor) {
438 449
super(timeRangeProvider, timer, m -> m.getTimePoint(), LOADING_OFFSET_TO_NEXT_MANEUVER_PROVIDER, true);
439 450
this.asyncActionsExecutor = asyncActionsExecutor;
440
- this.raceIdentifier = raceIdentifier;
441 451
this.sailingService = sailingService;
442 452
}
443 453
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/WinningLanesMode.java
... ...
@@ -49,12 +49,10 @@ public class WinningLanesMode extends RaceBoardModeWithPerRaceCompetitors {
49 49
raceDetailsToShow.add(DetailType.RACE_TIME_TRAVELED);
50 50
final SingleRaceLeaderboardSettings additiveSettings = LeaderboardSettingsFactory.getInstance().createNewSettingsWithCustomRaceDetails(raceDetailsToShow);
51 51
((RaceBoardComponentContext) leaderboardPanel.getComponentContext()).addModesPatching(leaderboardPanel, additiveSettings, new OnSettingsReloadedCallback<SingleRaceLeaderboardSettings>() {
52
-
53 52
@Override
54 53
public void onSettingsReloaded(SingleRaceLeaderboardSettings patchedSettings) {
55 54
leaderboardPanel.updateSettings(patchedSettings);
56 55
}
57
-
58 56
});
59 57
}
60 58
... ...
@@ -79,14 +77,11 @@ public class WinningLanesMode extends RaceBoardModeWithPerRaceCompetitors {
79 77
defaultSettings.isShowEstimatedDuration(),
80 78
defaultSettings.getStartCountDownFontSizeScaling(),
81 79
defaultSettings.isShowManeuverLossVisualization());
82
-
83 80
((RaceBoardComponentContext) raceMap.getComponentContext()).addModesPatching(raceMap, additiveSettings, new OnSettingsReloadedCallback<RaceMapSettings>() {
84
-
85 81
@Override
86 82
public void onSettingsReloaded(RaceMapSettings patchedSettings) {
87 83
raceMap.updateSettings(patchedSettings);
88 84
}
89
-
90 85
});
91 86
}
92 87
... ...
@@ -129,17 +124,16 @@ public class WinningLanesMode extends RaceBoardModeWithPerRaceCompetitors {
129 124
stopReceivingLeaderboard();
130 125
adjustLeaderboardSettings();
131 126
}
132
- if (adjustedLeaderboardSettings && tailLength != null) {
133
- adjustMapSettings();
134
- }
135 127
if (getLeaderboardForSpecificTimePoint() == null && tailLength != null && getLeaderboard() != null && getRaceColumn() != null) {
136 128
loadLeaderboardForSpecificTimePoint(getLeaderboard().name, getRaceColumn().getName(), getTimer().getTime());
137 129
}
138 130
if (!adjustedCompetitorSelection && getLeaderboardForSpecificTimePoint() != null && getCompetitorsInRace() != null) {
139 131
stopReceivingCompetitorsInRace();
140 132
adjustedCompetitorSelection = true;
133
+ updateCompetitorSelection();
134
+ }
135
+ if (adjustedLeaderboardSettings && tailLength != null && adjustedCompetitorSelection) {
136
+ adjustMapSettings();
141 137
}
142
- updateCompetitorSelection();
143 138
}
144
-
145 139
}
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/MediaServiceImpl.java
... ...
@@ -17,6 +17,7 @@ import java.net.URL;
17 17
import java.net.URLConnection;
18 18
import java.net.URLEncoder;
19 19
import java.nio.channels.Channels;
20
+import java.nio.channels.ReadableByteChannel;
20 21
import java.nio.charset.StandardCharsets;
21 22
import java.nio.file.Files;
22 23
import java.text.DateFormat;
... ...
@@ -221,13 +222,22 @@ public class MediaServiceImpl extends RemoteServiceServlet implements MediaServi
221 222
222 223
private VideoMetadataDTO checkMetadataByFullFileDownload(URL input)
223 224
throws ParserConfigurationException, SAXException, IOException {
224
- try (IsoFile isof = new IsoFile(Channels.newChannel(input.openStream()))) {
225
- boolean canDownload = true;
226
- Date recordStartedTimer = determineRecordingStart(isof);
227
- Duration duration = determineDuration(isof);
228
- boolean spherical = determine360(isof);
229
- removeTempFiles(isof);
230
- return new VideoMetadataDTO(canDownload, duration, spherical, recordStartedTimer, "");
225
+ final File tmp = File.createTempFile("upload", "metadataCheck");
226
+ try {
227
+ final ReadableByteChannel rbc = Channels.newChannel(input.openStream());
228
+ try (FileOutputStream fos = new FileOutputStream(tmp)) {
229
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
230
+ try (IsoFile isof = new IsoFile(tmp)) {
231
+ final boolean canDownload = true;
232
+ final Date recordStartedTimer = determineRecordingStart(isof);
233
+ final Duration duration = determineDuration(isof);
234
+ final boolean spherical = determine360(isof);
235
+ removeTempFiles(isof);
236
+ return new VideoMetadataDTO(canDownload, duration, spherical, recordStartedTimer, "");
237
+ }
238
+ }
239
+ } finally {
240
+ Files.delete(tmp.toPath());
231 241
}
232 242
}
233 243
... ...
@@ -276,8 +286,9 @@ public class MediaServiceImpl extends RemoteServiceServlet implements MediaServi
276 286
Field field = box.getClass().getDeclaredField("dataFile");
277 287
field.setAccessible(true);
278 288
File data = (File) field.get(box);
279
- data.delete();
280
- } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
289
+ Files.delete(data.toPath());
290
+ } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException
291
+ | IOException e) {
281 292
logger.log(Level.WARNING, "Could not delete mp4 temp files", e);
282 293
}
283 294
}
java/com.sap.sailing.polars.datamining.shared/.project
... ...
@@ -21,12 +21,12 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
24
+ <name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
25 25
<arguments>
26 26
</arguments>
27 27
</buildCommand>
28 28
<buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
29
+ <name>com.gwtplugins.gwt.eclipse.core.gwtProjectValidator</name>
30 30
<arguments>
31 31
</arguments>
32 32
</buildCommand>
... ...
@@ -34,6 +34,6 @@
34 34
<natures>
35 35
<nature>org.eclipse.pde.PluginNature</nature>
36 36
<nature>org.eclipse.jdt.core.javanature</nature>
37
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
37
+ <nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
38 38
</natures>
39 39
</projectDescription>
java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/components/BackendPolarsBoatClassRetrievalProcessor.java
... ...
@@ -1,9 +1,11 @@
1 1
package com.sap.sailing.polars.datamining.components;
2 2
3 3
import java.util.Collection;
4
+import java.util.HashSet;
5
+import java.util.Set;
4 6
import java.util.concurrent.ExecutorService;
5
-import java.util.stream.Collectors;
6 7
8
+import com.sap.sailing.domain.base.BoatClass;
7 9
import com.sap.sailing.domain.polars.PolarDataService;
8 10
import com.sap.sailing.polars.datamining.data.HasBackendPolarBoatClassContext;
9 11
import com.sap.sailing.polars.datamining.data.impl.BoatClassWithBackendPolarContext;
... ...
@@ -20,11 +22,15 @@ public class BackendPolarsBoatClassRetrievalProcessor extends AbstractRetrievalP
20 22
21 23
@Override
22 24
protected Iterable<HasBackendPolarBoatClassContext> retrieveData(RacingEventService element) {
25
+ Set<HasBackendPolarBoatClassContext> data = new HashSet<>();
23 26
PolarDataService polarDataService = element.getPolarDataService();
24
- return polarDataService.getAllBoatClassesWithPolarSheetsAvailable()
25
- .stream()
26
- .map(bc -> new BoatClassWithBackendPolarContext(bc, polarDataService))
27
- .collect(Collectors.toSet());
27
+ for (BoatClass boatClass : polarDataService.getAllBoatClassesWithPolarSheetsAvailable()) {
28
+ if (isAborted()) {
29
+ break;
30
+ }
31
+ data.add(new BoatClassWithBackendPolarContext(boatClass, polarDataService));
32
+ }
33
+ return data;
28 34
}
29 35
30 36
}
java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/components/PolarCompetitorRetrievalProcessor.java
... ...
@@ -25,6 +25,9 @@ public class PolarCompetitorRetrievalProcessor extends AbstractRetrievalProcesso
25 25
TrackedRace trackedRace = element.getTrackedRace();
26 26
Set<HasCompetitorPolarContext> competitorWithContext = new HashSet<>();
27 27
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
28
+ if (isAborted()) {
29
+ break;
30
+ }
28 31
competitorWithContext.add(new CompetitorWithPolarContext(competitor, trackedRace, element.getLeg(), element));
29 32
}
30 33
return competitorWithContext;
java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/components/PolarFleetRetrievalProcessor.java
... ...
@@ -25,6 +25,9 @@ public class PolarFleetRetrievalProcessor extends AbstractRetrievalProcessor<Has
25 25
Set<HasFleetPolarContext> fleetWithContext = new HashSet<>();
26 26
RaceColumn raceColumn = element.getRaceColumn();
27 27
for (Fleet fleet : raceColumn.getFleets()) {
28
+ if (isAborted()) {
29
+ break;
30
+ }
28 31
fleetWithContext.add(new FleetWithPolarContext(fleet, raceColumn, element));
29 32
}
30 33
return fleetWithContext;
java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/components/PolarGPSFixRetrievalProcessor.java
... ...
@@ -59,6 +59,9 @@ public class PolarGPSFixRetrievalProcessor extends AbstractRetrievalProcessor<Ha
59 59
try {
60 60
Iterable<GPSFixMoving> fixes = track.getFixes(startTime, true, finishTime, false);
61 61
for (GPSFixMoving fix : fixes) {
62
+ if (isAborted()) {
63
+ break;
64
+ }
62 65
WindWithConfidence<Pair<Position, TimePoint>> wind = trackedRace.getWindWithConfidence(
63 66
fix.getPosition(),
64 67
fix.getTimePoint(),
java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/components/PolarLeaderboardGroupRetrievalProcessor.java
... ...
@@ -1,9 +1,11 @@
1 1
package com.sap.sailing.polars.datamining.components;
2 2
3 3
import java.util.Collection;
4
+import java.util.HashSet;
5
+import java.util.Set;
4 6
import java.util.concurrent.ExecutorService;
5
-import java.util.stream.Collectors;
6 7
8
+import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
7 9
import com.sap.sailing.polars.datamining.data.HasLeaderboardGroupPolarContext;
8 10
import com.sap.sailing.polars.datamining.data.impl.LeaderboardGroupWithPolarContext;
9 11
import com.sap.sailing.server.RacingEventService;
... ...
@@ -19,11 +21,14 @@ public class PolarLeaderboardGroupRetrievalProcessor extends AbstractRetrievalPr
19 21
20 22
@Override
21 23
protected Iterable<HasLeaderboardGroupPolarContext> retrieveData(RacingEventService element) {
22
- return element.getLeaderboardGroups()
23
- .values()
24
- .stream()
25
- .map(lg -> new LeaderboardGroupWithPolarContext(lg))
26
- .collect(Collectors.toSet());
24
+ Set<HasLeaderboardGroupPolarContext> data = new HashSet<>();
25
+ for (LeaderboardGroup leaderboardGroup : element.getLeaderboardGroups().values()) {
26
+ if (isAborted()) {
27
+ break;
28
+ }
29
+ data.add(new LeaderboardGroupWithPolarContext(leaderboardGroup));
30
+ }
31
+ return data;
27 32
}
28 33
29 34
}
java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/components/PolarLeaderboardRetrievalProcessor.java
... ...
@@ -23,6 +23,9 @@ public class PolarLeaderboardRetrievalProcessor extends AbstractRetrievalProcess
23 23
protected Iterable<HasLeaderboardPolarContext> retrieveData(HasLeaderboardGroupPolarContext element) {
24 24
Set<HasLeaderboardPolarContext> leaderboardsWithContext = new HashSet<>();
25 25
for (Leaderboard leaderboard : element.getLeaderboardGroup().getLeaderboards()) {
26
+ if (isAborted()) {
27
+ break;
28
+ }
26 29
leaderboardsWithContext.add(new LeaderboardWithPolarContext(leaderboard, element));
27 30
}
28 31
return leaderboardsWithContext;
java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/components/PolarLegRetrievalProcessor.java
... ...
@@ -35,6 +35,9 @@ public class PolarLegRetrievalProcessor extends AbstractRetrievalProcessor<HasFl
35 35
if (raceDefinition != null) {
36 36
Course course = raceDefinition.getCourse();
37 37
for (Leg leg : course.getLegs()) {
38
+ if (isAborted()) {
39
+ break;
40
+ }
38 41
legWithContext.add(new LegWithPolarContext(leg, trackedRace, element));
39 42
}
40 43
}
java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/components/PolarRaceColumnRetrievalProcessor.java
... ...
@@ -25,6 +25,9 @@ public class PolarRaceColumnRetrievalProcessor extends AbstractRetrievalProcesso
25 25
Set<HasRaceColumnPolarContext> raceColumnWithContext = new HashSet<>();
26 26
Leaderboard leaderboard = element.getLeaderboard();
27 27
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
28
+ if (isAborted()) {
29
+ break;
30
+ }
28 31
raceColumnWithContext.add(new RaceColumnWithPolarContext(raceColumn, element));
29 32
}
30 33
return raceColumnWithContext;
java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/components/aggregators/PolarBackendDataAggregationProcessor.java
... ...
@@ -100,10 +100,17 @@ public class PolarBackendDataAggregationProcessor extends AbstractParallelGroupe
100 100
} catch (NotEnoughDataHasBeenAddedException e) {
101 101
hasDownwindAngleData = false;
102 102
}
103
+
103 104
for (int angleInDeg = 0; angleInDeg < 360; angleInDeg++) {
105
+ if (isAborted()) {
106
+ break;
107
+ }
104 108
int convertedAngle = angleInDeg > 180 ? angleInDeg - 360 : angleInDeg ;
105 109
try {
106 110
for (int x = 0; x < 30; x++) {
111
+ if (isAborted()) {
112
+ break;
113
+ }
107 114
SpeedWithConfidence<Void> speed = polarDataService.getSpeed(boatClass, new KnotSpeedImpl(x), new DegreeBearingImpl(convertedAngle));
108 115
if (speed.getConfidence() > 0.1) {
109 116
hasDataForAngle[angleInDeg] = true;
... ...
@@ -127,6 +134,9 @@ public class PolarBackendDataAggregationProcessor extends AbstractParallelGroupe
127 134
128 135
private void setArrayValuesForFunction(PolynomialFunction function, double[] yOverWindSpeed) {
129 136
for (int x = 0; x < 30; x++) {
137
+ if (isAborted()) {
138
+ break;
139
+ }
130 140
yOverWindSpeed[x] = function.value(x);
131 141
}
132 142
}
java/com.sap.sailing.polars/src/com/sap/sailing/polars/impl/PolarDataServiceImpl.java
... ...
@@ -170,8 +170,10 @@ public class PolarDataServiceImpl implements ReplicablePolarService, ClearStateT
170 170
if (closestTwsTwa == null) {
171 171
result = new Pair<>(0.0, null);
172 172
} else {
173
- double minDiffDeg = Math.abs(Math.abs(Math.abs(closestTwsTwa.getObject().getBearing().getDegrees() * 2)
174
- - Math.abs(courseChangeDeg)));
173
+ double targetManeuverAngle = getManeuverAngleInDegreesFromTwa(
174
+ closestTwsTwa.getObject().getBearing().getDegrees(), maneuverType);
175
+ double minDiffDeg = Math.abs(Math.abs(targetManeuverAngle)
176
+ - Math.abs(courseChangeDeg));
175 177
result = new Pair<>(1. / (1. + (minDiffDeg / 10.) * (minDiffDeg / 10.)), closestTwsTwa);
176 178
}
177 179
return result;
... ...
@@ -189,7 +191,7 @@ public class PolarDataServiceImpl implements ReplicablePolarService, ClearStateT
189 191
: courseChangeDeg >= 0 ? Tack.STARBOARD : Tack.PORT)) {
190 192
double targetManeuverAngle = getManeuverAngleInDegreesFromTwa(
191 193
trueWindSpeedAndAngle.getObject().getBearing().getDegrees(), type);
192
- double diff = Math.abs(targetManeuverAngle) - Math.abs(courseChangeDeg);
194
+ double diff = Math.abs(Math.abs(targetManeuverAngle) - Math.abs(courseChangeDeg));
193 195
if (diff < minDiff) {
194 196
minDiff = diff;
195 197
closestTwsTwa = trueWindSpeedAndAngle;
java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataMiner.java
... ...
@@ -288,7 +288,7 @@ public class PolarDataMiner {
288 288
} else if (legType.equals(LegType.DOWNWIND)) {
289 289
CubicEquation downWindEquation = new CubicEquation(0.0003, -0.0373, 1.5213, -2.1309
290 290
- speedOverGround.getKnots());
291
- int angle = 30 * tackFactor;
291
+ int angle = 150 * tackFactor;
292 292
solveAndAddResults(resultSet, downWindEquation, angle);
293 293
}
294 294
return resultSet;
java/com.sap.sailing.selenium.test/.classpath
... ...
@@ -5,6 +5,5 @@
5 5
<classpathentry kind="src" path="src"/>
6 6
<classpathentry kind="src" path="resources"/>
7 7
<classpathentry exported="true" kind="lib" path="lib/cglib-nodep-2.2.3.jar"/>
8
- <classpathentry kind="lib" path="/org.openqa.selenium.osgi/lib/commons-exec-1.1.jar"/>
9 8
<classpathentry kind="output" path="bin"/>
10 9
</classpath>
java/com.sap.sailing.selenium.test/META-INF/MANIFEST.MF
... ...
@@ -7,7 +7,7 @@ Bundle-Vendor: SAP
7 7
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
8 8
Require-Bundle: org.hamcrest;bundle-version="1.1.0",
9 9
org.junit;bundle-version="4.8.2",
10
- org.openqa.selenium.osgi;bundle-version="2.40.0",
10
+ org.openqa.selenium.osgi;bundle-version="3.13.0",
11 11
com.sap.sse.mongodb;bundle-version="1.0.0",
12 12
org.mongodb.mongo-java-driver;bundle-version="2.13.0",
13 13
com.sap.sailing.domain.common,
java/com.sap.sailing.selenium.test/ci-test-environment.xml
... ...
@@ -44,12 +44,43 @@
44 44
<name>webdriver.enable.native.events </name>
45 45
<value>true</value>
46 46
</system-property>
47
- <!--
47
+ <!--
48
+ You need chromedriver to be able to run Selenium tests on Chrome/Chromium.
49
+ This is the path to chromedriver, not Chrome.
50
+ The chromedriver download is linked on the official selenium download page:
51
+ https://www.seleniumhq.org/download/
52
+ -->
53
+ <!--
54
+ <system-property>
55
+ <name>webdriver.chrome.driver</name>
56
+ <value>/path/to/chromedriver</value>
57
+ </system-property>
58
+ -->
59
+
60
+ <!--
61
+ You need geckodriver to be able to run Selenium tests on Firefox.
62
+ This is the path to geckodriver, not Firefox.
63
+ The geckodriver download is linked on the official selenium download page:
64
+ https://www.seleniumhq.org/download/
65
+ -->
66
+ <!--
67
+ <system-property>
68
+ <name>webdriver.gecko.driver</name>
69
+ <value>/path/to/geckodriver</value>
70
+ </system-property>
71
+ -->
72
+ <!--
73
+ geckodriver automatically finds an installed version of Firefox.
74
+ If no Firefox is installed on the system or another version should be used,
75
+ the property "webdriver.firefox.bin" may be set to specify the path.
76
+ The default on Windows is "C:\Program Files\Mozilla Firefox\firefox.exe"
77
+ -->
78
+ <!--
48 79
<system-property>
49 80
<name>webdriver.firefox.bin</name>
50
- <value>[path to]\firefox.exe</value>
81
+ <value>path/to/firefox</value>
51 82
</system-property>
52
- -->
83
+ -->
53 84
</system-properties>
54 85
55 86
<!--
... ...
@@ -61,18 +92,28 @@
61 92
pages mentioned above.
62 93
-->
63 94
<!-- -->
95
+ <!--
64 96
<driver-definition class="org.openqa.selenium.firefox.FirefoxDriver">
65
- <!--
97
+
66 98
<capabilities>
67 99
<capability>
68 100
<name>version</name>
69 101
<value>14.0.0</value>
70 102
</capability>
71 103
</capabilities>
72
- -->
73 104
</driver-definition>
105
+ -->
106
+ <!-- TODO: should we use headless Firefox instead of Xvfb on Hudson? -->
107
+ <!--
108
+ <driver-definition class="com.sap.sailing.selenium.core.HeadlessFirefoxDriver">
109
+ </driver-definition>
110
+ -->
74 111
75 112
<!--
76 113
<driver-definition class="org.openqa.selenium.chrome.ChromeDriver" />
77 114
-->
115
+
116
+ <driver-definition class="com.sap.sailing.selenium.core.HeadlessChromeDriver">
117
+ </driver-definition>
118
+
78 119
</test-environment>
java/com.sap.sailing.selenium.test/com.sap.sailing.selenium.test (No Proxy, GWT Codesvr).launch
... ...
@@ -14,13 +14,7 @@
14 14
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
15 15
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
16 16
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
17
-<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
18
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8&quot; javaProject=&quot;com.sap.sailing.selenium.test&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
19
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.selenium.test&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
20
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.openqa.selenium.osgi/lib/commons-exec-1.1.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
21
-</listAttribute>
22
-<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
23 17
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
24 18
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.selenium.test"/>
25
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Dselenium.test.environment.configuration=local-test-environment.xml -Dgwt.codesvr=127.0.0.1:9997 -Dwebdriver.firefox.profile=Selenium"/>
19
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Dselenium.test.environment.configuration=local-test-environment.xml -Dgwt.codesvr=127.0.0.1:9876"/>
26 20
</launchConfiguration>
java/com.sap.sailing.selenium.test/com.sap.sailing.selenium.test (Proxy, GWT Codesvr).launch
... ...
@@ -12,5 +12,5 @@
12 12
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
13 13
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
14 14
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.selenium.test"/>
15
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Dselenium.test.environment.configuration=local-test-environment.xml -Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -Dgwt.codesvr=127.0.0.1:9997 -Dwebdriver.firefox.profile=Selenium"/>
15
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Dselenium.test.environment.configuration=local-test-environment.xml -Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -Dgwt.codesvr=127.0.0.1:9876"/>
16 16
</launchConfiguration>
java/com.sap.sailing.selenium.test/local-test-environment.xml
... ...
@@ -28,22 +28,65 @@
28 28
- http://code.google.com/p/selenium/wiki/SafariDriver
29 29
- http://code.google.com/p/selenium/wiki/RemoteWebDriverServer
30 30
31
- NOTE: For the Chrome and the InternetExplorer driver an additional "server", which acts as a bridge between the
31
+ NOTE: For the Chrome, Firefox and InternetExplorer driver an additional "server", which acts as a bridge between the
32 32
browser and the driver, is needed.
33 33
-->
34 34
<system-properties>
35
+ <!--
36
+ You need chromedriver to be able to run Selenium tests on Chrome/Chromium.
37
+ This is the path to chromedriver, not Chrome.
38
+ The chromedriver download is linked on the official selenium download page:
39
+ https://www.seleniumhq.org/download/
40
+ -->
35 41
<system-property>
36 42
<name>webdriver.chrome.driver</name>
37 43
<value>C:\apps\ChromeSeleniumDriver\chromedriver.exe</value>
38 44
</system-property>
45
+ <!--
46
+ You need geckodriver to be able to run Selenium tests on Firefox.
47
+ This is the path to geckodriver, not Firefox.
48
+ The geckodriver download is linked on the official selenium download page:
49
+ https://www.seleniumhq.org/download/
50
+ -->
51
+ <system-property>
52
+ <name>webdriver.gecko.driver</name>
53
+ <value>/path/to/geckodriver.exe</value>
54
+ </system-property>
55
+ <!--
56
+ geckodriver automatically finds an installed version of Firefox.
57
+ If no Firefox is installed on the system or another version should be used,
58
+ the property "webdriver.firefox.bin" may be set to specify the path.
59
+ The default on Windows is "C:\Program Files\Mozilla Firefox\firefox.exe"
60
+ -->
61
+ <!--
39 62
<system-property>
40 63
<name>webdriver.firefox.bin</name>
41
- <!-- Default binary location on Windows: -->
42
- <value>c:\Program Files (x86)\Mozilla Firefox 24\firefox.exe</value>
43
- <!-- -->
44
- <!-- Default binary location on Linux: -->
45
- <!-- <value>/usr/bin/firefox</value> -->
64
+ <value>/path/to/firefox.exe</value>
65
+ </system-property>
66
+ -->
67
+ <!--
68
+ You need IEDriverServer.exe to successfully run selenium tests using IE 11.
69
+ The download is listed on the official Selenium download page:
70
+ https://www.seleniumhq.org/download/
71
+ This property needs to point to the downloaded and unzipped IEDriverServer.exe, not the ie.exe!
72
+
73
+ With IE 10/11, only the 32Bit version works by the time of writing.
74
+
75
+ In addition, versions 3.11 to 3.13 are known bad because these often fail with a
76
+ org.openqa.selenium.ElementClickInterceptedException in case of modal GWT dialogs are shown.
77
+ This is probably related to the following bug: https://github.com/SeleniumHQ/selenium/issues/5935
78
+ If you see suspicous ElementClickInterceptedExceptions, use IEDriverServer version 3.10:
79
+ https://selenium-release.storage.googleapis.com/index.html?path=3.10/
80
+
81
+ Some further configuration steps may be required depending on the OS and IE version:
82
+ https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver#required-configuration
83
+ -->
84
+ <!--
85
+ <system-property>
86
+ <name>webdriver.ie.driver</name>
87
+ <value>C:\path\to\IEDriverServer.exe</value>
46 88
</system-property>
89
+ -->
47 90
</system-properties>
48 91
49 92
... ...
@@ -61,4 +104,16 @@
61 104
<driver-definition class="org.openqa.selenium.chrome.ChromeDriver">
62 105
</driver-definition>
63 106
-->
107
+ <!-- <driver-definition class="org.openqa.selenium.ie.InternetExplorerDriver">
108
+ <capabilities>
109
+ <capability>
110
+ <name>ignoreZoomSetting</name>
111
+ <value>true</value>
112
+ </capability>
113
+ </capabilities>
114
+ </driver-definition> -->
115
+ <!-- <driver-definition class="com.sap.sailing.selenium.core.HeadlessFirefoxDriver">
116
+ </driver-definition> -->
117
+ <!-- <driver-definition class="com.sap.sailing.selenium.core.HeadlessChromeDriver">
118
+ </driver-definition> -->
64 119
</test-environment>
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/ElementSearchCondition.java
... ...
@@ -1,8 +1,8 @@
1 1
package com.sap.sailing.selenium.core;
2 2
3
-import org.openqa.selenium.SearchContext;
3
+import java.util.function.Function;
4 4
5
-import com.google.common.base.Function;
5
+import org.openqa.selenium.SearchContext;
6 6
7 7
/**
8 8
* <p>Models a condition that might reasonably be expected to eventually evaluate to something that is neither
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/HeadlessChromeDriver.java
... ...
@@ -0,0 +1,26 @@
1
+package com.sap.sailing.selenium.core;
2
+
3
+import org.openqa.selenium.Capabilities;
4
+import org.openqa.selenium.chrome.ChromeDriver;
5
+import org.openqa.selenium.chrome.ChromeDriverService;
6
+import org.openqa.selenium.chrome.ChromeOptions;
7
+
8
+/**
9
+ *Specific {@link ChromeDriver} that is configured to start Chrome in headless mode. In theory, you do not need a
10
+ * specific subclass of {@link ChromeDriver} but we currently can't apply specific command line options using XML based
11
+ * configuration using {@link TestEnvironmentConfiguration}. So this is currently just a simple workaround but not a
12
+ * long-term solution.
13
+ */
14
+public class HeadlessChromeDriver extends ChromeDriver {
15
+
16
+ public HeadlessChromeDriver(Capabilities capabilities) {
17
+ super(ChromeDriverService.createDefaultService(), constructChromeOptions(capabilities));
18
+ }
19
+
20
+ private static ChromeOptions constructChromeOptions(Capabilities capabilities) {
21
+ final ChromeOptions chromeOptions = new ChromeOptions();
22
+ chromeOptions.merge(capabilities);
23
+ chromeOptions.addArguments("--headless", "--window-size=1440,900");
24
+ return chromeOptions;
25
+ }
26
+}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/HeadlessFirefoxDriver.java
... ...
@@ -0,0 +1,32 @@
1
+package com.sap.sailing.selenium.core;
2
+
3
+import java.util.Objects;
4
+
5
+import org.openqa.selenium.Capabilities;
6
+import org.openqa.selenium.firefox.FirefoxBinary;
7
+import org.openqa.selenium.firefox.FirefoxDriver;
8
+import org.openqa.selenium.firefox.FirefoxOptions;
9
+
10
+/**
11
+ * Specific {@link FirefoxDriver} that is configured to start Firefox in headless mode. In theory, you do not need a
12
+ * specific subclass of {@link FirefoxDriver} but we currently can't apply specific command line options using XML based
13
+ * configuration using {@link TestEnvironmentConfiguration}. So this is currently just a simple workaround but not a
14
+ * long-term solution.
15
+ */
16
+public class HeadlessFirefoxDriver extends FirefoxDriver {
17
+
18
+ public HeadlessFirefoxDriver(Capabilities desiredCapabilities) {
19
+ super(constructFirefoxOptions(desiredCapabilities));
20
+
21
+ }
22
+
23
+ private static FirefoxOptions constructFirefoxOptions(Capabilities desiredCapabilities) {
24
+ final FirefoxOptions firefoxOptions = new FirefoxOptions(Objects.requireNonNull(desiredCapabilities, "No capabilities seen"));
25
+ FirefoxBinary firefoxBinary = new FirefoxBinary();
26
+ // Window size is currently being ignored in headless mode
27
+ // Documentation says it should work: https://developer.mozilla.org/en-US/Firefox/Headless_mode
28
+ firefoxBinary.addCommandLineOptions("-headless"/*, "--window-size=1440,900"*/);
29
+ firefoxOptions.setBinary(firefoxBinary);
30
+ return firefoxOptions;
31
+ }
32
+}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/SeleniumElementLocator.java
... ...
@@ -1,8 +1,9 @@
1 1
package com.sap.sailing.selenium.core;
2 2
3 3
import java.lang.reflect.Field;
4
+import java.time.Duration;
4 5
import java.util.List;
5
-import java.util.concurrent.TimeUnit;
6
+import java.util.function.Function;
6 7
7 8
import org.openqa.selenium.By;
8 9
import org.openqa.selenium.NoSuchElementException;
... ...
@@ -11,8 +12,6 @@ import org.openqa.selenium.WebElement;
11 12
import org.openqa.selenium.support.pagefactory.ElementLocator;
12 13
import org.openqa.selenium.support.ui.FluentWait;
13 14
14
-import com.google.common.base.Function;
15
-
16 15
/**
17 16
* <p>An element locator, which will lazily locate and wait for an element or an element list to appear, by polling the
18 17
* UI on a regular basis. It is possible to define the maximum amount of time to wait for the element or the list of
... ...
@@ -66,8 +65,8 @@ public class SeleniumElementLocator implements ElementLocator {
66 65
this.context = context;
67 66
68 67
this.wait = new FluentWait<>(this.context);
69
- this.wait.withTimeout(timeOutSeconds, TimeUnit.SECONDS);
70
- this.wait.pollingEvery(intervalMillis, TimeUnit.MILLISECONDS);
68
+ this.wait.withTimeout(Duration.ofSeconds(timeOutSeconds));
69
+ this.wait.pollingEvery(Duration.ofMillis(intervalMillis));
71 70
this.wait.ignoring(NoSuchElementException.class);
72 71
73 72
Annotations annotations = new Annotations(field);
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/SeleniumFieldDecorator.java
... ...
@@ -9,8 +9,7 @@ import java.lang.reflect.Type;
9 9
import java.util.List;
10 10
11 11
import org.openqa.selenium.WebElement;
12
-
13
-import org.openqa.selenium.internal.Locatable;
12
+import org.openqa.selenium.interactions.internal.Locatable;
14 13
import org.openqa.selenium.internal.WrapsElement;
15 14
16 15
import org.openqa.selenium.support.pagefactory.ElementLocator;
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/WindowManager.java
... ...
@@ -1,10 +1,11 @@
1 1
package com.sap.sailing.selenium.core;
2 2
3 3
import java.util.Set;
4
+import java.util.function.BiConsumer;
4 5
6
+import org.openqa.selenium.Dimension;
5 7
import org.openqa.selenium.JavascriptExecutor;
6 8
import org.openqa.selenium.WebDriver;
7
-import org.openqa.selenium.WebDriver.TargetLocator;
8 9
9 10
/**
10 11
* <p></p>
... ...
@@ -25,20 +26,8 @@ public class WindowManager {
25 26
*/
26 27
public WindowManager(WebDriver driver) {
27 28
this.driver = driver;
28
- }
29
-
30
- /**
31
- * <p></p>
32
- *
33
- * @param url
34
- */
35
- public void switchTo(String url) {
36
- WebDriverWindow window = findWindow(url);
37
-
38
- if(window == null)
39
- throw new RuntimeException("Window not found");
40 29
41
- window.switchToWindow();
30
+ setWindowMaximized();
42 31
}
43 32
44 33
/**
... ...
@@ -47,60 +36,24 @@ public class WindowManager {
47 36
* @return
48 37
*
49 38
*/
50
- public WebDriverWindow getCurrentWindow() {
39
+ private WebDriverWindow getCurrentWindow() {
51 40
return new WebDriverWindow(this.driver, this.driver.getWindowHandle());
52 41
}
53 42
54 43
/**
55 44
* <p></p>
56 45
*
57
- * <p>Note: If no window is found with the specified URL, </p>
58
- *
59
- * @param url
60
- *
61 46
* @return
62
- *
63 47
*/
64
- public WebDriverWindow findWindow(String url) {
65
- if(url == null)
66
- throw new IllegalArgumentException();
67
-
68
- TargetLocator locator = this.driver.switchTo();
69
-
70
- for(String handle : this.driver.getWindowHandles()) {
71
- locator.window(handle);
72
-
73
- if(url.equals(this.driver.getCurrentUrl()))
74
- return new WebDriverWindow(this.driver, handle);
75
- }
76
-
77
- return null;
78
- }
79
-
80
- /**
81
- * <p></p>
82
- *
83
- * @return
84
- */
85
- public WebDriverWindow openNewWindow() {
48
+ private WebDriverWindow openNewWindow() {
86 49
return openNewWindow(false);
87 50
}
88 51
89
- public WebDriverWindow openNewWindow(boolean focus) {
52
+ private WebDriverWindow openNewWindow(boolean focus) {
90 53
return openNewWindow("", focus);
91 54
}
92 55
93
- /**
94
- * <p></p>
95
- *
96
- * @param url
97
- * @return
98
- */
99
- public WebDriverWindow openNewWindow(String url) {
100
- return openNewWindow(url, false);
101
- }
102
-
103
- public WebDriverWindow openNewWindow(String url, boolean focus) {
56
+ private WebDriverWindow openNewWindow(String url, boolean focus) {
104 57
WebDriverWindow window = new WebDriverWindow(this.driver, createWindow(url));
105 58
106 59
if(focus) {
... ...
@@ -134,4 +87,37 @@ public class WindowManager {
134 87
135 88
return null;
136 89
}
90
+
91
+ public void withExtraWindow(BiConsumer<WebDriverWindow, WebDriverWindow> defaultAndExtraWindow) {
92
+ final WebDriverWindow defaultWindow = getCurrentWindow();
93
+ final WebDriverWindow extraWindow = openNewWindow();
94
+ extraWindow.switchToWindow();
95
+ setWindowMaximized();
96
+ defaultWindow.switchToWindow();
97
+ try {
98
+ defaultAndExtraWindow.accept(defaultWindow, extraWindow);
99
+ } finally {
100
+ try {
101
+ extraWindow.close();
102
+ } catch (Exception e) {
103
+ // This call may fail depending on the WebDriver being used
104
+ }
105
+ defaultWindow.switchToWindow();
106
+ }
107
+ }
108
+
109
+ private void setWindowMaximized() {
110
+ try {
111
+ driver.manage().window().maximize();
112
+ } catch (Exception e) {
113
+ // Depending on the combination of OS and WebDriver implementation this may fail
114
+ // e.g. chrome with xvfb can't do this successfully.
115
+ try {
116
+ // Trying to set a proper screen size as fallback that should usable with all modern screens
117
+ driver.manage().window().setSize(new Dimension(1440, 900));
118
+ } catch (Exception exc) {
119
+ // In this case we just can't change the window
120
+ }
121
+ }
122
+ }
137 123
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/HostPage.java
... ...
@@ -3,6 +3,7 @@ package com.sap.sailing.selenium.pages;
3 3
import java.net.URI;
4 4
import java.net.URISyntaxException;
5 5
6
+import org.openqa.selenium.JavascriptExecutor;
6 7
import org.openqa.selenium.WebDriver;
7 8
8 9
/**
... ...
@@ -18,9 +19,9 @@ public abstract class HostPage extends PageObject {
18 19
protected static final String NO_CODE_SERVER_PARAMTER_VALUE = ""; //$NON-NLS-1$
19 20
20 21
/**
21
- * </p>The default timeout of 60 seconds for the initialization of the page object.</p>
22
+ * </p>The default timeout of 120 seconds for the initialization of the page object.</p>
22 23
*/
23
- protected static final int DEFAULT_PAGE_LOAD_TIMEOUT = 120;
24
+ protected static final int DEFAULT_PAGE_LOAD_TIMEOUT_IN_SECONDS = 120;
24 25
25 26
public static final String getGWTCodeServerAndLocale() {
26 27
StringBuilder queryBuilder = new StringBuilder("locale=en");
... ...
@@ -64,13 +65,12 @@ public abstract class HostPage extends PageObject {
64 65
*/
65 66
@Override
66 67
protected void initElements() {
67
- waitForAjaxRequests(getPageLoadTimeOut(), 5);
68
-
68
+ waitForAjaxRequests(getPageLoadTimeOutInSeconds(), 5 /* seconds */);
69 69
super.initElements();
70 70
}
71 71
72
- protected int getPageLoadTimeOut() {
73
- return DEFAULT_PAGE_LOAD_TIMEOUT;
72
+ protected int getPageLoadTimeOutInSeconds() {
73
+ return DEFAULT_PAGE_LOAD_TIMEOUT_IN_SECONDS;
74 74
}
75 75
76 76
protected interface HostPageSupplier<T extends HostPage> {
... ...
@@ -80,4 +80,8 @@ public abstract class HostPage extends PageObject {
80 80
public String getCurrentUrl() {
81 81
return driver.getCurrentUrl();
82 82
}
83
+
84
+ protected void scrollToTop() {
85
+ ((JavascriptExecutor) driver).executeScript("window.scrollTo(0, 0);");
86
+ }
83 87
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/PageObject.java
... ...
@@ -1,18 +1,19 @@
1 1
package com.sap.sailing.selenium.pages;
2 2
3 3
import java.text.MessageFormat;
4
+import java.time.Duration;
4 5
import java.util.Arrays;
5 6
import java.util.Collection;
6 7
import java.util.Collections;
7 8
import java.util.List;
8
-import java.util.concurrent.TimeUnit;
9 9
import java.util.function.BooleanSupplier;
10
+import java.util.function.Function;
10 11
import java.util.logging.Level;
11 12
import java.util.logging.Logger;
12 13
13 14
import org.openqa.selenium.Alert;
14 15
import org.openqa.selenium.By;
15
-import org.openqa.selenium.NoAlertPresentException;
16
+import org.openqa.selenium.JavascriptExecutor;
16 17
import org.openqa.selenium.SearchContext;
17 18
import org.openqa.selenium.WebDriver;
18 19
import org.openqa.selenium.WebElement;
... ...
@@ -21,8 +22,6 @@ import org.openqa.selenium.support.ui.ExpectedConditions;
21 22
import org.openqa.selenium.support.ui.FluentWait;
22 23
import org.openqa.selenium.support.ui.WebDriverWait;
23 24
24
-import com.google.common.base.Function;
25
-import com.google.common.base.Predicate;
26 25
import com.sap.sailing.selenium.core.AjaxCallsComplete;
27 26
import com.sap.sailing.selenium.core.AjaxCallsExecuted;
28 27
import com.sap.sailing.selenium.core.BySeleniumId;
... ...
@@ -60,7 +59,7 @@ public class PageObject {
60 59
61 60
public static final int DEFAULT_WAIT_TIMEOUT_SECONDS = 120;
62 61
63
- public static final int DEFAULT_POLLING_INTERVAL = 5;
62
+ public static final int DEFAULT_POLLING_INTERVAL = 1;
64 63
65 64
private static final MessageFormat TAB_PANEL_EXPRESSION = new MessageFormat(
66 65
".//div[contains(@class, \"gwt-TabBarItem\")]/div[text()=\"{0}\"]/..");
... ...
@@ -132,15 +131,15 @@ public class PageObject {
132 131
*
133 132
* @param input
134 133
*
135
- * @param timeout
134
+ * @param timeoutInSeconds
136 135
*
137
- * @param polling
136
+ * @param pollingEverySoManySeconds
138 137
*
139 138
* @return
140 139
*
141 140
*/
142
- public static <T> FluentWait<T> createFluentWait(T input, int timeout, int polling) {
143
- return createFluentWait(input, timeout, polling, Collections.<Class<? extends Throwable>>emptyList());
141
+ public static <T> FluentWait<T> createFluentWait(T input, int timeoutInSeconds, int pollingEverySoManySeconds) {
142
+ return createFluentWait(input, timeoutInSeconds, pollingEverySoManySeconds, Collections.<Class<? extends Throwable>>emptyList());
144 143
}
145 144
146 145
/**
... ...
@@ -168,20 +167,20 @@ public class PageObject {
168 167
*
169 168
* @param input
170 169
*
171
- * @param timeout
170
+ * @param timeoutInSeconds
172 171
*
173
- * @param polling
172
+ * @param pollingEverySoManySeconds
174 173
*
175 174
* @param exceptions
176 175
*
177 176
* @return
178 177
*
179 178
*/
180
- public static <T> FluentWait<T> createFluentWait(T input, int timeout, int polling,
179
+ public static <T> FluentWait<T> createFluentWait(T input, int timeoutInSeconds, int pollingEverySoManySeconds,
181 180
Collection<Class<? extends Throwable>> exceptions) {
182 181
FluentWait<T> wait = new FluentWait<>(input);
183
- wait.withTimeout(timeout, TimeUnit.SECONDS);
184
- wait.pollingEvery(polling, TimeUnit.SECONDS);
182
+ wait.withTimeout(Duration.ofSeconds(timeoutInSeconds));
183
+ wait.pollingEvery(Duration.ofSeconds(pollingEverySoManySeconds));
185 184
wait.ignoreAll(exceptions);
186 185
187 186
return wait;
... ...
@@ -223,7 +222,7 @@ public class PageObject {
223 222
224 223
/**
225 224
* <p>Initialize the page object. The default implementation use a factory to lazily initialize the elements
226
- * (annotated fields) of the page object using the timeout duration returned by {@link #getPageLoadTimeOut()}.
225
+ * (annotated fields) of the page object using the timeout duration returned by {@link #getPageLoadTimeOutInSeconds()}.
227 226
* To get a field lazily initialized you have to annotate the field either with {@link FindBy} or with
228 227
* {@link FindBys}. If the element never changes (that is, that the same instance in the DOM can always be used)
229 228
* it is also possible to use a cache for the lookup by using the annotation {@code CacheLookup} in addition.</p>
... ...
@@ -431,15 +430,15 @@ public class PageObject {
431 430
* and polling interval. In reality, the interval may be greater as the cost of actually evaluating the condition
432 431
* is not factored in.</p>
433 432
*
434
- * @param timeout
435
- * The timeout duration for the waiting.
436
- * @param polling
437
- * The interval in which the check should be performed.
433
+ * @param timeoutInSeconds
434
+ * The timeout duration for the waiting in seconds.
435
+ * @param pollingEverySoManySeconds
436
+ * The interval in seconds in which the check should be performed.
438 437
* @throws org.openqa.selenium.TimeoutException
439 438
* if the timeout expires.
440 439
*/
441
- protected void waitForAjaxRequests(int timeout, int polling) {
442
- waitForAjaxRequests(AjaxCallsComplete.CATEGORY_GLOBAL, timeout, polling);
440
+ protected void waitForAjaxRequests(int timeoutInSeconds, int pollingEverySoManySeconds) {
441
+ waitForAjaxRequests(AjaxCallsComplete.CATEGORY_GLOBAL, timeoutInSeconds, pollingEverySoManySeconds);
443 442
}
444 443
445 444
/**
... ...
@@ -449,15 +448,15 @@ public class PageObject {
449 448
*
450 449
* @param category
451 450
* The category of Ajax requests to wait for.
452
- * @param timeout
453
- * The timeout duration for the waiting.
454
- * @param polling
455
- * The interval in which the check should be performed.
451
+ * @param timeoutInSeconds
452
+ * The timeout duration for the waiting in seconds.
453
+ * @param pollingEverySoManySeconds
454
+ * The interval in seconds in which the check should be performed.
456 455
* @throws org.openqa.selenium.TimeoutException
457 456
* if the timeout expires.
458 457
*/
459
- protected void waitForAjaxRequests(String category, int timeout, int polling) {
460
- FluentWait<WebDriver> wait = createFluentWait(this.driver, timeout, polling);
458
+ protected void waitForAjaxRequests(String category, int timeoutInSeconds, int pollingEverySoManySeconds) {
459
+ FluentWait<WebDriver> wait = createFluentWait(this.driver, timeoutInSeconds, pollingEverySoManySeconds);
461 460
462 461
wait.until(new AjaxCallsComplete(category));
463 462
}
... ...
@@ -484,7 +483,7 @@ public class PageObject {
484 483
webDriverWait.until(ExpectedConditions.presenceOfElementLocated(new BySeleniumId(seleniumId)));
485 484
}
486 485
487
- protected void waitUntil(Predicate<WebDriver> predicate) {
486
+ protected void waitUntil(Function<WebDriver, Boolean> predicate) {
488 487
WebDriverWait webDriverWait = new WebDriverWait(driver, DEFAULT_LOOKUP_TIMEOUT);
489 488
webDriverWait.until(predicate);
490 489
}
... ...
@@ -579,57 +578,67 @@ public class PageObject {
579 578
/**
580 579
* Waits for an alert box to appear and accepts the alert. If no alert shows up, an Exception is thrown.
581 580
*/
582
- protected void waitForAlertAndAccept() throws InterruptedException {
581
+ protected void waitForAlertAndAccept() {
583 582
waitForAlertAndAccept(DEFAULT_WAIT_TIMEOUT_SECONDS);
584 583
}
585 584
586 585
/**
587 586
* Waits for an alert box to appear and accepts the alert. If no alert shows up, an Exception is thrown.
588 587
*/
589
- protected void waitForAlertAndAccept(int timeoutInSeconds) throws InterruptedException {
590
- int i = 0;
591
- while (i < timeoutInSeconds) {
592
- i++;
593
- try {
594
- Alert alert = driver.switchTo().alert();
595
- alert.accept();
596
- return;
597
- } catch (NoAlertPresentException e) {
598
- Thread.sleep(1000);
599
- }
600
- }
601
- throw new NoAlertPresentException();
588
+ protected void waitForAlertAndAccept(int timeoutInSeconds) {
589
+ final Alert expectedAlert = new WebDriverWait(driver, timeoutInSeconds).until(ExpectedConditions.alertIsPresent());
590
+ expectedAlert.accept();
602 591
}
603 592
604 593
/**
605
- * Waits for an notification to appear and dismisses the notification by clicking on it. If no notification shows up, an Exception is thrown.
594
+ * Waits for a notification to appear and dismisses the notification by clicking on it. If no notification shows up, an Exception is thrown.
606 595
*/
607
- protected void waitForNotificationAndDismiss() throws InterruptedException {
608
- waitForNotificationAndDismiss(DEFAULT_WAIT_TIMEOUT_SECONDS);
596
+ protected void waitForNotificationAndDismiss() {
597
+ waitForNotificationAndDismiss(DEFAULT_WAIT_TIMEOUT_SECONDS, null);
598
+ }
599
+
600
+ /**
601
+ * Waits for a specific notification to appear and dismisses the notification by clicking on it. If no notification shows up, an Exception is thrown.
602
+ */
603
+ protected void waitForNotificationAndDismiss(String expectedNotificationMessage) {
604
+ waitForNotificationAndDismiss(DEFAULT_WAIT_TIMEOUT_SECONDS, expectedNotificationMessage);
609 605
}
610 606
611 607
/**
612 608
* Waits for an notification to appear and dismisses the notification by clicking on it. If no notification shows up, an Exception is thrown.
613 609
*/
614
- protected void waitForNotificationAndDismiss(int timeoutInSeconds) throws InterruptedException {
615
- int i = 0;
616
- while (i < timeoutInSeconds) {
617
- i++;
618
- try {
619
- List<WebElement> notifications = driver.findElements(By.id("notificationBar"));
620
- if (notifications.size() > 0) {
621
- notifications.get(0).findElements(By.cssSelector("*"))
622
- .forEach(notification -> notification.click());
623
- ;
624
- return;
625
- } else {
626
- throw new NoAlertPresentException();
610
+ protected void waitForNotificationAndDismiss(int timeoutInSeconds, String expectedNotificationMessage) {
611
+ WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
612
+ wait.until(new Function<WebDriver, Boolean>() {
613
+
614
+ @Override
615
+ public Boolean apply(WebDriver t) {
616
+ boolean clickedNotifications = false;
617
+ try {
618
+ List<WebElement> notificationBar = driver.findElements(By.id("notificationBar"));
619
+ if (!notificationBar.isEmpty()) {
620
+ // we got the enclosing panel
621
+ List<WebElement> notifications = notificationBar.get(0).findElements(By.cssSelector("*"));
622
+ if (!notifications.isEmpty()) {
623
+ for (WebElement messageElement : notifications) {
624
+ if (expectedNotificationMessage == null
625
+ || messageElement.getText().contains(expectedNotificationMessage)) {
626
+ messageElement.click();
627
+ clickedNotifications = true;
628
+ }
629
+ }
630
+ }
631
+ }
632
+ } catch (Exception e) {
633
+ // This call can fail temporarily while notifications are being updated
627 634
}
628
- } catch (NoAlertPresentException e) {
629
- Thread.sleep(1000);
635
+ return clickedNotifications;
630 636
}
631
- }
632
- throw new NoAlertPresentException();
637
+ });
638
+ }
639
+
640
+ protected void scrollToView(WebElement webElement) {
641
+ ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(false);", webElement);
633 642
}
634 643
635 644
public boolean isElementEntirelyVisible(WebElement element) {
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/ActionsHelper.java
... ...
@@ -1,5 +1,7 @@
1 1
package com.sap.sailing.selenium.pages.adminconsole;
2 2
3
+import java.util.function.Function;
4
+
3 5
import org.openqa.selenium.Alert;
4 6
import org.openqa.selenium.By;
5 7
import org.openqa.selenium.NoAlertPresentException;
... ...
@@ -9,7 +11,6 @@ import org.openqa.selenium.WebDriver.TargetLocator;
9 11
import org.openqa.selenium.WebElement;
10 12
import org.openqa.selenium.support.ui.FluentWait;
11 13
12
-import com.google.common.base.Function;
13 14
import com.sap.sailing.selenium.pages.PageObject;
14 15
15 16
public class ActionsHelper {
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/igtimi/IgtimiAccountsManagementPanelPO.java
... ...
@@ -41,6 +41,6 @@ public class IgtimiAccountsManagementPanelPO extends PageArea {
41 41
addIgtimiAccountDialog.setPassword(password);
42 42
addIgtimiAccountDialog.pressOk();
43 43
44
- waitForNotificationAndDismiss(10);
44
+ waitForNotificationAndDismiss();
45 45
}
46 46
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/RegattaDetailsCompositePO.java
... ...
@@ -1,15 +1,16 @@
1 1
package com.sap.sailing.selenium.pages.adminconsole.regatta;
2 2
3
+import java.util.Arrays;
4
+import java.util.Collections;
5
+import java.util.List;
6
+
3 7
import org.openqa.selenium.WebDriver;
4 8
import org.openqa.selenium.WebElement;
5 9
6 10
import com.sap.sailing.selenium.core.BySeleniumId;
7 11
import com.sap.sailing.selenium.core.FindBy;
8
-
9 12
import com.sap.sailing.selenium.pages.PageArea;
10
-
11 13
import com.sap.sailing.selenium.pages.adminconsole.ActionsHelper;
12
-
13 14
import com.sap.sailing.selenium.pages.gwt.CellTablePO;
14 15
import com.sap.sailing.selenium.pages.gwt.DataEntryPO;
15 16
import com.sap.sailing.selenium.pages.gwt.GenericCellTablePO;
... ...
@@ -85,4 +86,17 @@ public class RegattaDetailsCompositePO extends PageArea {
85 86
private CellTablePO<DataEntryPO> getSeriesTable() {
86 87
return new GenericCellTablePO<>(this.driver, this.seriesTable, DataEntryPO.class);
87 88
}
89
+
90
+ public List<String> getRaceNames(String seriesName) {
91
+ final DataEntryPO seriesEntry = findSeries(seriesName);
92
+ final String racesColumnContent = seriesEntry.getColumnContent("Races");
93
+ if (racesColumnContent != null && ! racesColumnContent.isEmpty()) {
94
+ return Arrays.asList(racesColumnContent.split(", "));
95
+ }
96
+ return Collections.emptyList();
97
+ }
98
+
99
+ public void waitForRacesOfSeries(final String series, final List<String> races) {
100
+ waitUntil(() -> getRaceNames(series).equals(races));
101
+ }
88 102
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/RegattaStructureManagementPanelPO.java
... ...
@@ -1,7 +1,10 @@
1 1
package com.sap.sailing.selenium.pages.adminconsole.regatta;
2 2
3
+import java.util.function.Function;
4
+
3 5
import org.openqa.selenium.WebDriver;
4 6
import org.openqa.selenium.WebElement;
7
+import org.openqa.selenium.support.ui.WebDriverWait;
5 8
6 9
import com.sap.sailing.selenium.core.BySeleniumId;
7 10
import com.sap.sailing.selenium.core.FindBy;
... ...
@@ -64,7 +67,7 @@ public class RegattaStructureManagementPanelPO extends PageArea {
64 67
}
65 68
66 69
private DefaultRegattaLeaderboardCreateDialogPO createDefaultRegattaLeaderboard() {
67
- WebElement dialog = findElementBySeleniumId(this.driver, "CreateDefaultRegattaLeaderboardDialog"); //$NON-NLS-1$
70
+ final WebElement dialog = waitForElementBySeleniumId(this.driver, "CreateDefaultRegattaLeaderboardDialog", 10); //$NON-NLS-1$
68 71
return new DefaultRegattaLeaderboardCreateDialogPO(this.driver, dialog);
69 72
}
70 73
... ...
@@ -80,9 +83,14 @@ public class RegattaStructureManagementPanelPO extends PageArea {
80 83
}
81 84
82 85
public RegattaDetailsCompositePO getRegattaDetails() {
83
- if (this.regattaDetails.isDisplayed()) {
84
- return new RegattaDetailsCompositePO(this.driver, this.regattaDetails);
85
- }
86
- return null;
86
+ return new WebDriverWait(driver, DEFAULT_WAIT_TIMEOUT_SECONDS).until(new Function<WebDriver, RegattaDetailsCompositePO>() {
87
+ @Override
88
+ public RegattaDetailsCompositePO apply(WebDriver t) {
89
+ if (regattaDetails.isDisplayed()) {
90
+ return new RegattaDetailsCompositePO(driver, regattaDetails);
91
+ }
92
+ return null;
93
+ }
94
+ });
87 95
}
88 96
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/SeriesEditDialogPO.java
... ...
@@ -6,6 +6,7 @@ import java.util.List;
6 6
import org.openqa.selenium.By;
7 7
import org.openqa.selenium.WebDriver;
8 8
import org.openqa.selenium.WebElement;
9
+import org.openqa.selenium.interactions.Actions;
9 10
import org.openqa.selenium.support.ui.Select;
10 11
11 12
import com.sap.sailing.selenium.core.BySeleniumId;
... ...
@@ -121,9 +122,12 @@ public class SeriesEditDialogPO extends DataEntryDialogPO {
121 122
for(WebElement editorRow : getRaceNameEditors()) {
122 123
WebElement valueTextBox = findElementBySeleniumId(editorRow, "ValueTextBox");
123 124
124
- if(races.contains(valueTextBox.getAttribute("value"))) {
125
+ if (races.contains(valueTextBox.getAttribute("value"))) {
125 126
WebElement removeButton = findElementBySeleniumId(editorRow, "RemoveButton");
126
- removeButton.click();
127
+ // A simple "removeButton.click();" does not work on GeckoDriver here.
128
+ // This only presses the button down but a click isn't detected.
129
+ // It seems that the mouseup event isn't correctly fired, why we use this workaround.
130
+ new Actions(driver).sendKeys(removeButton, "\13").perform();
127 131
}
128 132
}
129 133
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesListPO.java
... ...
@@ -6,13 +6,13 @@ import java.util.Collections;
6 6
import java.util.Iterator;
7 7
import java.util.List;
8 8
import java.util.Objects;
9
+import java.util.function.Function;
9 10
10 11
import org.openqa.selenium.TimeoutException;
11 12
import org.openqa.selenium.WebDriver;
12 13
import org.openqa.selenium.WebElement;
13 14
import org.openqa.selenium.support.ui.FluentWait;
14 15
15
-import com.google.common.base.Function;
16 16
import com.sap.sailing.domain.common.BoatClassMasterdata;
17 17
import com.sap.sailing.selenium.core.BySeleniumId;
18 18
import com.sap.sailing.selenium.core.FindBy;
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tractrac/TracTracEventManagementPanelPO.java
... ...
@@ -1,16 +1,17 @@
1 1
package com.sap.sailing.selenium.pages.adminconsole.tractrac;
2 2
3 3
import java.util.ArrayList;
4
+import java.util.Collection;
5
+import java.util.Collections;
6
+import java.util.HashSet;
4 7
import java.util.LinkedList;
5 8
import java.util.List;
6 9
import java.util.Objects;
10
+import java.util.Set;
7 11
8
-import org.openqa.selenium.Alert;
9 12
import org.openqa.selenium.By;
10 13
import org.openqa.selenium.WebDriver;
11 14
import org.openqa.selenium.WebElement;
12
-import org.openqa.selenium.support.ui.ExpectedCondition;
13
-import org.openqa.selenium.support.ui.ExpectedConditions;
14 15
import org.openqa.selenium.support.ui.Select;
15 16
16 17
import com.sap.sailing.domain.common.BoatClassMasterdata;
... ...
@@ -45,7 +46,7 @@ public class TracTracEventManagementPanelPO extends PageArea {
45 46
46 47
@Override
47 48
public int hashCode() {
48
- return Objects.hash(this.boatClass, this.eventName, this.raceName);
49
+ return Objects.hash(BoatClassMasterdata.resolveBoatClass(this.boatClass), this.eventName, this.raceName);
49 50
}
50 51
51 52
@Override
... ...
@@ -228,44 +229,53 @@ public class TracTracEventManagementPanelPO extends PageArea {
228 229
}
229 230
230 231
public void startTrackingForRace(TrackableRaceDescriptor race) {
231
- //startTrackingForRaces(Arrays.asList(race));
232
- CellTablePO<DataEntryPO> table = getTrackableRacesTable();
233
- DataEntryPO entryToSelect = null;
234
- for (DataEntryPO entry : table.getEntries()) {
235
- TrackableRaceDescriptor entryDiscribtor = new TrackableRaceDescriptor(entry.getColumnContent("Event"),
236
- entry.getColumnContent("Race"), entry.getColumnContent("Boat Class"));
237
- if (race.equals(entryDiscribtor)) {
238
- entryToSelect = entry;
239
- break;
240
- }
241
- }
242
- table.selectEntry(entryToSelect);
243
- startTrackingAndWaitForAjaxRequests();
232
+ startTrackingForRacesInternal(Collections.singletonList(race), null, false);
244 233
}
245 234
246
- public void startTrackingForRaces(List<TrackableRaceDescriptor> races) {
247
- List<TrackableRaceDescriptor> racesToProcess = new ArrayList<>(races);
248
- CellTablePO<DataEntryPO> table = getTrackableRacesTable();
235
+ public void startTrackingForRacesAndAcceptDefaultRegattaWarning(TrackableRaceDescriptor race) {
236
+ startTrackingForRacesInternal(Collections.singletonList(race), null, true);
237
+ }
238
+
239
+ public void startTrackingForRaceAndAwaitBoatClassError(TrackableRaceDescriptor race, String expectedBoatClass) {
240
+ startTrackingForRacesInternal(Collections.singletonList(race), expectedBoatClass, false);
241
+ }
242
+
243
+ public void startTrackingForRaces(Collection<TrackableRaceDescriptor> races) {
244
+ startTrackingForRacesInternal(races, null, false);
245
+ }
246
+
247
+ private void startTrackingForRacesInternal(Collection<TrackableRaceDescriptor> races,
248
+ String expectedBoatClassErrorOrNull, boolean awaitDefaultRegattaAlert) {
249
+ final Set<TrackableRaceDescriptor> racesToProcess = new HashSet<>(races);
250
+ final CellTablePO<DataEntryPO> table = getTrackableRacesTable();
249 251
table.selectEntries(e -> racesToProcess.remove(new TrackableRaceDescriptor(e.getColumnContent("Event"),
250
- e.getColumnContent("Race"), e.getColumnContent("Boat Class"))));
251
- if(!racesToProcess.isEmpty()) {
252
+ e.getColumnContent("Race"), e.getColumnContent("Boat Class"))), racesToProcess::isEmpty);
253
+ if (!racesToProcess.isEmpty()) {
252 254
throw new IllegalStateException("Not all given races where selected");
253 255
}
254
- startTrackingAndWaitForAjaxRequests();
256
+ startTrackingForSelectedRaces(expectedBoatClassErrorOrNull, awaitDefaultRegattaAlert);
255 257
}
256 258
257 259
public void startTrackingForAllRaces() {
258 260
getTrackableRacesTable().selectAllEntries();
259
- startTrackingAndWaitForAjaxRequests();
261
+ startTrackingForSelectedRaces(null, false);
260 262
}
261 263
262
- private void startTrackingAndWaitForAjaxRequests() {
263
- this.startTrackingButton.click();
264
- ExpectedCondition<Alert> condition = ExpectedConditions.alertIsPresent();
265
- if (condition.apply(this.driver) == null) {
264
+ private void startTrackingForSelectedRaces(String expectedBoatClassErrorOrNull, boolean awaitDefaultRegattaAlert) {
265
+ this.startTracking();
266
+
267
+ if (awaitDefaultRegattaAlert) {
268
+ waitForAlertAndAccept();
269
+ } else if (expectedBoatClassErrorOrNull == null) {
266 270
waitForAjaxRequests();
271
+ } else {
272
+ waitForSelectedRacesContainDifferentBoatClassesError(expectedBoatClassErrorOrNull);
267 273
}
268 274
}
275
+
276
+ private void startTracking() {
277
+ this.startTrackingButton.click();
278
+ }
269 279
270 280
public TrackedRacesListPO getTrackedRacesList() {
271 281
return new TrackedRacesListPO(this.driver, this.trackedRacesListComposite);
... ...
@@ -281,4 +291,11 @@ public class TracTracEventManagementPanelPO extends PageArea {
281 291
if(input.isSelected() != selected)
282 292
input.click();
283 293
}
294
+
295
+ private void waitForSelectedRacesContainDifferentBoatClassesError(String boatClass) {
296
+ String message = String.format("The selected races contain boat classes which are not the same as "
297
+ + "the boat class '%s' of the selected regatta.", boatClass);
298
+
299
+ waitForNotificationAndDismiss(message);
300
+ }
284 301
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/wind/WindPanelPO.java
... ...
@@ -1,11 +1,12 @@
1 1
package com.sap.sailing.selenium.pages.adminconsole.wind;
2 2
3
+import java.util.function.Function;
4
+
3 5
import org.openqa.selenium.TimeoutException;
4 6
import org.openqa.selenium.WebDriver;
5 7
import org.openqa.selenium.WebElement;
6 8
import org.openqa.selenium.support.ui.FluentWait;
7 9
8
-import com.google.common.base.Function;
9 10
import com.sap.sailing.selenium.core.BySeleniumId;
10 11
import com.sap.sailing.selenium.core.FindBy;
11 12
import com.sap.sailing.selenium.pages.PageArea;
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/autoplay/AutoPlayConfiguration.java
... ...
@@ -2,9 +2,7 @@ package com.sap.sailing.selenium.pages.autoplay;
2 2
3 3
import org.openqa.selenium.WebDriver;
4 4
import org.openqa.selenium.WebElement;
5
-import org.openqa.selenium.support.ui.WebDriverWait;
6 5
7
-import com.google.common.base.Predicate;
8 6
import com.sap.sailing.selenium.core.BySeleniumId;
9 7
import com.sap.sailing.selenium.core.FindBy;
10 8
import com.sap.sailing.selenium.pages.PageArea;
... ...
@@ -31,15 +29,8 @@ public class AutoPlayConfiguration extends PageArea {
31 29
ListBoxPO.create(driver, configurationSelectionBox).selectOptionByLabel(mode);
32 30
ListBoxPO.create(driver, eventSelectionBox).selectOptionByLabel(event);
33 31
ListBoxPO.create(driver, leaderboardSelectionBox).selectOptionByLabel(leaderboard);
34
- WebDriverWait wait = new WebDriverWait(driver, 10);
35 32
//wait till the page processed the changes
36
- wait.until(new Predicate<WebDriver>() {
37
-
38
- @Override
39
- public boolean apply(WebDriver arg0) {
40
- return getConfiguredUrl() != null && !getConfiguredUrl().isEmpty();
41
- }
42
- });
33
+ waitUntil(() -> getConfiguredUrl() != null && !getConfiguredUrl().isEmpty());
43 34
}
44 35
45 36
public String getConfiguredUrl() {
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/autoplay/AutoPlayUpcomingView.java
... ...
@@ -1,13 +1,13 @@
1 1
package com.sap.sailing.selenium.pages.autoplay;
2 2
3 3
import java.util.List;
4
+import java.util.function.Function;
4 5
5 6
import org.openqa.selenium.StaleElementReferenceException;
6 7
import org.openqa.selenium.WebDriver;
7 8
import org.openqa.selenium.WebElement;
8 9
import org.openqa.selenium.support.ui.WebDriverWait;
9 10
10
-import com.google.common.base.Function;
11 11
import com.sap.sailing.selenium.pages.PageArea;
12 12
13 13
public class AutoPlayUpcomingView extends PageArea {
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/DataEntryDialogPO.java
... ...
@@ -1,10 +1,14 @@
1 1
package com.sap.sailing.selenium.pages.common;
2 2
3
+import java.util.function.BooleanSupplier;
4
+
3 5
import org.openqa.selenium.Alert;
6
+import org.openqa.selenium.JavascriptExecutor;
7
+import org.openqa.selenium.StaleElementReferenceException;
4 8
import org.openqa.selenium.WebDriver;
5 9
import org.openqa.selenium.WebElement;
6
-import org.openqa.selenium.support.ui.ExpectedCondition;
7 10
import org.openqa.selenium.support.ui.ExpectedConditions;
11
+import org.openqa.selenium.support.ui.WebDriverWait;
8 12
9 13
import com.sap.sailing.selenium.core.BySeleniumId;
10 14
import com.sap.sailing.selenium.core.FindBy;
... ...
@@ -25,6 +29,9 @@ public abstract class DataEntryDialogPO extends PageArea {
25 29
26 30
protected DataEntryDialogPO(WebDriver driver, WebElement element) {
27 31
super(driver, element);
32
+
33
+ // This ensures that we wait until the dialog is opened and not just attached to the DOM
34
+ waitUntil(element::isDisplayed);
28 35
}
29 36
30 37
@Override
... ...
@@ -52,23 +59,41 @@ public abstract class DataEntryDialogPO extends PageArea {
52 59
}
53 60
54 61
public void pressOk() {
55
- pressOk(false);
62
+ pressOk(false, true);
56 63
}
57 64
58
- public void pressOk(boolean accept) {
59
- this.okButton.click();
65
+ public void pressOk(boolean acceptAlert, boolean waitForAjaxRequests) {
66
+ // This generically triggers revalidation in dialogs to ensure that the ok button gets enabled
67
+ ((JavascriptExecutor) driver).executeScript("!!document.activeElement ? document.activeElement.blur() : 0");
60 68
61
- ExpectedCondition<Alert> condition = ExpectedConditions.alertIsPresent();
62
- Alert alert = condition.apply(this.driver);
69
+ scrollToView(this.okButton);
70
+ // Browsers may use smooth scrolling
71
+ waitUntil(() -> isElementEntirelyVisible(this.okButton) && this.okButton.isEnabled());
72
+ this.okButton.click();
63 73
64
- if(alert != null && accept) {
74
+ if (acceptAlert) {
75
+ final Alert alert = new WebDriverWait(driver, DEFAULT_WAIT_TIMEOUT_SECONDS)
76
+ .until(ExpectedConditions.alertIsPresent());
65 77
alert.accept();
66 78
}
67 79
68
- if(alert == null || accept) {
80
+ if (waitForAjaxRequests) {
69 81
// Wait, since we do a callback usually
70 82
waitForAjaxRequests();
71 83
}
84
+
85
+ // This waits until the dialog is physically closed to make sure further don't fail because the dialog still covers other elements
86
+ waitUntil(new BooleanSupplier() {
87
+ @Override
88
+ public boolean getAsBoolean() {
89
+ try {
90
+ return !((WebElement) context).isDisplayed();
91
+ } catch (StaleElementReferenceException e) {
92
+ // When the element was removed from the DOM, it isn't displayed anymore
93
+ return true;
94
+ }
95
+ }
96
+ });
72 97
}
73 98
74 99
public void pressCancel() {
... ...
@@ -78,15 +103,7 @@ public abstract class DataEntryDialogPO extends PageArea {
78 103
public void pressMakeDefault() {
79 104
WebElement element = findElementBySeleniumId(ID_MAKE_DEFAULT_BUTTON);
80 105
element.click();
81
- ExpectedCondition<Alert> condition = ExpectedConditions.alertIsPresent();
82
- Alert alert = condition.apply(this.driver);
83
-
84
- if(alert != null) {
85
- alert.accept();
86
- } else {
87
- waitForAjaxRequests();
88
- }
89
-
106
+ waitForNotificationAndDismiss();
90 107
}
91 108
92 109
public boolean isMakeDefaultButtonVisible() {
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/CellTablePO.java
... ...
@@ -4,6 +4,7 @@ import java.util.ArrayList;
4 4
import java.util.Iterator;
5 5
import java.util.List;
6 6
import java.util.Objects;
7
+import java.util.function.BooleanSupplier;
7 8
import java.util.function.Predicate;
8 9
import java.util.function.Supplier;
9 10
import java.util.stream.Stream;
... ...
@@ -11,9 +12,7 @@ import java.util.stream.Stream;
11 12
import org.openqa.selenium.By;
12 13
import org.openqa.selenium.WebDriver;
13 14
import org.openqa.selenium.WebElement;
14
-import org.openqa.selenium.support.ui.WebDriverWait;
15 15
16
-import com.google.common.base.Function;
17 16
import com.sap.sailing.selenium.pages.PageArea;
18 17
import com.sap.sailing.selenium.pages.common.CSSConstants;
19 18
... ...
@@ -260,13 +259,16 @@ public abstract class CellTablePO<T extends DataEntryPO> extends PageArea {
260 259
*
261 260
* <p>Note: If an entry is not contained in the table it will not be selected.</p>
262 261
*/
263
- public void selectEntries(Predicate<T> toSelectPredicate) {
262
+ public void selectEntries(Predicate<T> toSelectPredicate, BooleanSupplier canAbort) {
264 263
for (T entry : getEntries()) {
265 264
if(toSelectPredicate.test(entry)) {
266 265
entry.appendToSelection();
267 266
} else {
268 267
entry.deselect();
269 268
}
269
+ if (canAbort.getAsBoolean()) {
270
+ break;
271
+ }
270 272
}
271 273
}
272 274
... ...
@@ -276,7 +278,7 @@ public abstract class CellTablePO<T extends DataEntryPO> extends PageArea {
276 278
* <p>Note: If an entry is not contained in the table it will not be selected.</p>
277 279
*/
278 280
public void selectAllEntries() {
279
- selectEntries(e -> true);
281
+ selectEntries(e -> true, Boolean.FALSE::booleanValue);
280 282
}
281 283
282 284
/**
... ...
@@ -347,11 +349,6 @@ public abstract class CellTablePO<T extends DataEntryPO> extends PageArea {
347 349
}
348 350
349 351
public void waitForTableToShowData() {
350
- new WebDriverWait(driver, 30).until(new Function<WebDriver, Boolean>() {
351
- @Override
352
- public Boolean apply(WebDriver driver) {
353
- return !getRows().isEmpty();
354
- }
355
- });
352
+ waitUntil(() -> !getRows().isEmpty());
356 353
}
357 354
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/DataEntryPO.java
... ...
@@ -4,16 +4,12 @@ import java.util.List;
4 4
5 5
import org.openqa.selenium.By;
6 6
import org.openqa.selenium.By.ByXPath;
7
+import org.openqa.selenium.Dimension;
7 8
import org.openqa.selenium.Keys;
8 9
import org.openqa.selenium.WebElement;
9 10
import org.openqa.selenium.interactions.Action;
10 11
import org.openqa.selenium.interactions.Actions;
11 12
import org.openqa.selenium.interactions.CompositeAction;
12
-import org.openqa.selenium.interactions.HasInputDevices;
13
-import org.openqa.selenium.interactions.KeyDownAction;
14
-import org.openqa.selenium.interactions.KeyUpAction;
15
-import org.openqa.selenium.interactions.Keyboard;
16
-import org.openqa.selenium.interactions.Mouse;
17 13
18 14
import com.sap.sailing.selenium.core.FindBy;
19 15
import com.sap.sailing.selenium.pages.common.AttributeHelper;
... ...
@@ -82,11 +78,33 @@ public class DataEntryPO extends CellTableRowPO {
82 78
}
83 79
84 80
protected Action getSelectAction() {
85
- Actions actions = new Actions(this.driver);
86
- actions.moveToElement(getElementForSelect(), 1, 1);
81
+ final Actions actions = new Actions(this.driver);
82
+ final WebElement elementForSelect = getElementForSelect();
83
+ moveToUpperLeftCorner(actions, elementForSelect);
87 84
actions.click();
88 85
89
- return actions.build();
86
+ final CompositeAction compositeAction = new CompositeAction();
87
+ compositeAction.addAction(new Action() {
88
+ @Override
89
+ public void perform() {
90
+ scrollToView(elementForSelect);
91
+ }
92
+ });
93
+ compositeAction.addAction(actions.build());
94
+ return compositeAction;
95
+ }
96
+
97
+ /**
98
+ * It seems that the JavaDoc of {@link Actions#moveToElement(WebElement, int, int)} is not consistent to the
99
+ * WebDriver specification. The specification says the int params are relative to the center of the element, while
100
+ * the JavaDoc says it's relative to the upper-left corner. GeckoDriver implements the specification. This method
101
+ * ensures consistent behavior no matter if the implementation is a legacy one or one that conforms to the
102
+ * specification.
103
+ */
104
+ private void moveToUpperLeftCorner(Actions actions, WebElement webElement) {
105
+ actions.moveToElement(webElement);
106
+ final Dimension size = webElement.getSize();
107
+ actions.moveByOffset(-size.width / 2 + 1, -size.height / 2 + 1);
90 108
}
91 109
92 110
/**
... ...
@@ -110,35 +128,49 @@ public class DataEntryPO extends CellTableRowPO {
110 128
111 129
protected Action getModifiedSelectAction() {
112 130
Actions actions = new Actions(this.driver);
131
+ final WebElement elementToSelect;
132
+ final boolean controlClick;
113 133
if (table.getColumnHeaders().get(0).equals("\u2713")) {
114 134
// it's a checkbox column
115
- actions.moveToElement(this.columns.isEmpty() ? getWebElement() : this.columns.get(0));
116
- actions.click();
135
+ elementToSelect = this.columns.isEmpty() ? getWebElement() : this.columns.get(0);
136
+ controlClick = false;
117 137
} else {
138
+ elementToSelect = getElementForSelect();
139
+ controlClick = true;
140
+ }
141
+ if (controlClick) {
118 142
actions.keyDown(Keys.CONTROL);
119
- actions.moveToElement(getElementForSelect(), 1, 1);
120
- actions.click();
143
+ }
144
+ moveToUpperLeftCorner(actions, elementToSelect);
145
+ actions.moveToElement(elementToSelect, 1, 1);
146
+ actions.click();
147
+ if (controlClick) {
121 148
actions.keyUp(Keys.CONTROL);
122 149
}
123
- return actions.build();
150
+ final CompositeAction compositeAction = new CompositeAction();
151
+ compositeAction.addAction(new Action() {
152
+ @Override
153
+ public void perform() {
154
+ scrollToView(elementToSelect);
155
+ }
156
+ });
157
+ compositeAction.addAction(actions.build());
158
+ return compositeAction;
124 159
}
125 160
126 161
protected CompositeAction getModifiedCompositeActionAction() {
127
- HasInputDevices devices = (HasInputDevices) this.driver;
128
-
129
- final Mouse mouse = devices.getMouse();
130
- final Keyboard keyboard = devices.getKeyboard();
131
-
132 162
return new CompositeAction() {
133 163
@Override
134 164
public void perform() {
135
- Action pressControl = new KeyDownAction(keyboard, mouse, Keys.CONTROL);
136
- pressControl.perform();
165
+ Actions actions = new Actions(driver);
166
+ actions.keyDown(Keys.CONTROL);
167
+ actions.perform();
137 168
138 169
super.perform();
139 170
140
- Action releaseControl = new KeyUpAction(keyboard, mouse, Keys.CONTROL);
141
- releaseControl.perform();
171
+ actions = new Actions(driver);
172
+ actions.keyUp(Keys.CONTROL);
173
+ actions.perform();
142 174
}
143 175
};
144 176
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/DateAndTimeInputPO.java
... ...
@@ -4,11 +4,11 @@ import java.text.DateFormat;
4 4
import java.text.SimpleDateFormat;
5 5
import java.util.Date;
6 6
7
+import org.openqa.selenium.JavascriptExecutor;
7 8
import org.openqa.selenium.WebDriver;
8 9
import org.openqa.selenium.WebElement;
9 10
10 11
import com.sap.sailing.selenium.core.BySeleniumId;
11
-import com.sap.sailing.selenium.core.FindBy;
12 12
import com.sap.sailing.selenium.pages.PageArea;
13 13
14 14
public class DateAndTimeInputPO extends PageArea {
... ...
@@ -16,15 +16,17 @@ public class DateAndTimeInputPO extends PageArea {
16 16
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("MMM d, y");
17 17
private static final DateFormat TIME_FORMAT_MINUTES = new SimpleDateFormat("h:mm a");
18 18
private static final DateFormat TIME_FORMAT_SECONDS = new SimpleDateFormat("h:mm:ss a");
19
+ private static final DateFormat ISO_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
20
+ private static final DateFormat ISO_TIME_FORMAT_MINUTES = new SimpleDateFormat("HH:mm");
21
+ private static final DateFormat ISO_TIME_FORMAT_SECONDS = new SimpleDateFormat("HH:mm:ss");
22
+ private static final DateFormat ISO_DATE_TIME_FORMAT_MINUTES = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
23
+ private static final DateFormat ISO_DATE_TIME_FORMAT_SECONDS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
19 24
20
- @FindBy(how = BySeleniumId.class, using = "dateInput")
21
- private WebElement dateInput;
22
-
23
- @FindBy(how = BySeleniumId.class, using = "timeInput")
24
- private WebElement timeInput;
25
+ private final WebElement element;
25 26
26 27
private DateAndTimeInputPO(WebDriver driver, WebElement element) {
27 28
super(driver, element);
29
+ this.element = element;
28 30
}
29 31
30 32
/**
... ...
@@ -39,8 +41,27 @@ public class DateAndTimeInputPO extends PageArea {
39 41
* @see WebElement#sendKeys(CharSequence...)
40 42
*/
41 43
public void setValue(Date date, boolean enterSeconds) {
42
- this.setValue(dateInput, date, DATE_FORMAT);
43
- this.setValue(timeInput, date, enterSeconds ? TIME_FORMAT_SECONDS : TIME_FORMAT_MINUTES);
44
+ if (isFieldOfType(element, "datetime-local")) {
45
+ this.setValueNative(element, date, enterSeconds ? ISO_DATE_TIME_FORMAT_SECONDS : ISO_DATE_TIME_FORMAT_MINUTES);
46
+ } else {
47
+ final WebElement dateInput = element.findElement(new BySeleniumId("dateInput"));
48
+ final WebElement timeInput = element.findElement(new BySeleniumId("timeInput"));
49
+ if (isFieldOfType(dateInput, "date")) {
50
+ this.setValueNative(dateInput, date, ISO_DATE_FORMAT);
51
+ } else {
52
+ this.setValue(dateInput, date, DATE_FORMAT);
53
+ }
54
+
55
+ if (isFieldOfType(timeInput, "time")) {
56
+ this.setValueNative(timeInput, date, enterSeconds ? ISO_TIME_FORMAT_SECONDS : ISO_TIME_FORMAT_MINUTES);
57
+ } else {
58
+ this.setValue(timeInput, date, enterSeconds ? TIME_FORMAT_SECONDS : TIME_FORMAT_MINUTES);
59
+ }
60
+ }
61
+ }
62
+
63
+ private boolean isFieldOfType(WebElement inputToCheck, String type) {
64
+ return type.equals(inputToCheck.getAttribute("type"));
44 65
}
45 66
46 67
private void setValue(WebElement input, Date date, DateFormat format) {
... ...
@@ -49,6 +70,12 @@ public class DateAndTimeInputPO extends PageArea {
49 70
input.sendKeys(value);
50 71
input.sendKeys("\t"); // ensure popup closing!
51 72
}
73
+
74
+ private void setValueNative(WebElement input, Date date, DateFormat format) {
75
+ final String value = format.format(date);
76
+ final JavascriptExecutor javascriptExecutor = ((JavascriptExecutor) driver);
77
+ javascriptExecutor.executeScript("arguments[0].value = arguments[1];", input, value);
78
+ }
52 79
53 80
public static DateAndTimeInputPO create(WebDriver driver, WebElement element) {
54 81
return new DateAndTimeInputPO(driver, element);
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardPage.java
... ...
@@ -129,6 +129,7 @@ public class LeaderboardPage extends HostPage {
129 129
}
130 130
131 131
public LeaderboardSettingsDialogPO getLeaderboardSettings() {
132
+ scrollToTop();
132 133
this.leaderboardSettingsButton.click();
133 134
return new LeaderboardSettingsDialogPO(this.driver,
134 135
findElementBySeleniumId(this.driver, "LeaderboardSettingsDialog"));
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/raceboard/RaceBoardPage.java
... ...
@@ -3,9 +3,11 @@ package com.sap.sailing.selenium.pages.raceboard;
3 3
import java.io.UnsupportedEncodingException;
4 4
import java.net.URLEncoder;
5 5
import java.util.function.BooleanSupplier;
6
+import java.util.function.Function;
6 7
7 8
import org.openqa.selenium.WebDriver;
8 9
import org.openqa.selenium.WebElement;
10
+import org.openqa.selenium.support.ui.WebDriverWait;
9 11
10 12
import com.sap.sailing.selenium.core.BySeleniumId;
11 13
import com.sap.sailing.selenium.core.FindBy;
... ...
@@ -20,6 +22,7 @@ public class RaceBoardPage extends HostPageWithAuthentication {
20 22
21 23
@FindBy(how = BySeleniumId.class, using = "raceMapSettingsButton")
22 24
private WebElement raceMapSettingsButton;
25
+ private boolean doneInit;
23 26
24 27
/**
25 28
* Navigates to the given home URL and provides the corresponding {@link PageObject}.
... ...
@@ -42,20 +45,60 @@ public class RaceBoardPage extends HostPageWithAuthentication {
42 45
private RaceBoardPage(WebDriver driver) {
43 46
super(driver);
44 47
}
48
+
49
+ @Override
50
+ protected void waitForAjaxRequests(int timeout, int polling) {
51
+ // since the raceboard continually loads new data, we cannot wait for it to finish initially
52
+ if (doneInit) {
53
+ super.waitForAjaxRequests(timeout, polling);
54
+ }
55
+ }
56
+
57
+ @Override
58
+ protected void initElements() {
59
+ super.initElements();
60
+ doneInit = true;
61
+
62
+ // wait untill initial rendering of racemap & compilation ect, as default ajax based wait won't work here
63
+ WebDriverWait webDriverWait = new WebDriverWait(driver, 300);
64
+ webDriverWait.until(new Function<WebDriver, Boolean>() {
65
+ @Override
66
+ public Boolean apply(WebDriver t) {
67
+ try {
68
+ return raceMapSettingsButton.isDisplayed() && raceMapSettingsButton.getLocation().y > 100;
69
+ } catch (Exception e) {
70
+ // RaceMap cause multiple reflows and the element may temporarily not be in the viewport
71
+ return false;
72
+ }
73
+ }
74
+ });
75
+ }
76
+
45 77
public MapSettingsPO openMapSettings() {
78
+ waitUntil(new BooleanSupplier() {
79
+ @Override
80
+ public boolean getAsBoolean() {
81
+ try {
82
+ return raceMapSettingsButton.isDisplayed() && raceMapSettingsButton.getLocation().y > 100;
83
+ } catch (Exception e) {
84
+ // RaceMap cause multiple reflows and the element may temporarily not be in the viewport
85
+ return false;
86
+ }
87
+ }
88
+ });
46 89
raceMapSettingsButton.click();
47 90
waitUntil(new BooleanSupplier() {
48
-
49 91
@Override
50 92
public boolean getAsBoolean() {
51 93
WebElement settingsDialog = null;
52 94
try {
53 95
settingsDialog = findElementBySeleniumId("raceMapSettings");
96
+ boolean exists = settingsDialog != null;
97
+ // exists, and was actually rendered (to apply the values)
98
+ return (exists && settingsDialog.isDisplayed());
54 99
} catch(Exception e) {
55 100
}
56
- boolean exists = settingsDialog != null;
57
- // exists, and was actually rendered (to apply the values)
58
- return (exists && settingsDialog.getSize().height > 50);
101
+ return false;
59 102
}
60 103
});
61 104
return new MapSettingsPO(driver, findElementBySeleniumId("raceMapSettings"));
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/AbstractSeleniumTest.java
... ...
@@ -18,20 +18,23 @@ import org.junit.Rule;
18 18
import org.junit.rules.TestWatchman;
19 19
import org.junit.runner.RunWith;
20 20
import org.junit.runners.model.FrameworkMethod;
21
+import org.openqa.selenium.By;
21 22
import org.openqa.selenium.Cookie;
22
-import org.openqa.selenium.JavascriptExecutor;
23
+import org.openqa.selenium.Keys;
23 24
import org.openqa.selenium.OutputType;
24 25
import org.openqa.selenium.TakesScreenshot;
25 26
import org.openqa.selenium.WebDriver;
27
+import org.openqa.selenium.html5.WebStorage;
26 28
import org.openqa.selenium.remote.Augmenter;
27 29
import org.openqa.selenium.remote.RemoteWebDriver;
28 30
29
-import com.sap.sse.common.Duration;
30
-import com.sap.sse.common.impl.MillisecondsTimePoint;
31 31
import com.sap.sailing.selenium.core.Managed;
32 32
import com.sap.sailing.selenium.core.SeleniumRunner;
33 33
import com.sap.sailing.selenium.core.TestEnvironment;
34 34
import com.sap.sailing.selenium.core.WindowManager;
35
+import com.sap.sailing.selenium.pages.PageObject;
36
+import com.sap.sse.common.Duration;
37
+import com.sap.sse.common.impl.MillisecondsTimePoint;
35 38
36 39
/**
37 40
* <p>Abstract base class for unit tests with Selenium. This class is already annotated as required to get executed
... ...
@@ -83,16 +86,37 @@ public abstract class AbstractSeleniumTest {
83 86
} catch (IOException exception) {
84 87
throw new RuntimeException(exception);
85 88
}
86
- // clear local storage
89
+
90
+ // To be able to access LocalStorage we need to load a page having the target origin
87 91
getWebDriver().get(contextRoot);
88
- ((JavascriptExecutor)getWebDriver()).executeScript("window.localStorage.clear();");
92
+
93
+ // clear local storage
94
+ final WebStorage webStorage = (WebStorage)getWebDriver();
95
+ webStorage.getLocalStorage().clear();
96
+
97
+ // extending the timeout of notifications to 100s to prevent timing failures
98
+ webStorage.getLocalStorage().setItem("sse.notification.customTimeOutInSeconds",
99
+ Integer.toString(PageObject.DEFAULT_WAIT_TIMEOUT_SECONDS));
100
+
101
+ try {
102
+ // In IE 11 we sometimes see the problem that IE somehow automatically changes the zoom level to 75%.
103
+ // Selenium tests with InternetExplorerDriver fail if the zoom level is not set to 100% due to the fact that coordinates determined aren't correct.
104
+ // With this we enforce a zoom level of 100% before running a test.
105
+ // To make this work correctly you also need to set InternetExplorerDriver.IGNORE_ZOOM_SETTING to true (this should be pre-configured in local-test-environment.xml when activating IE driver)
106
+ getWebDriver().findElement(By.tagName("html")).sendKeys(Keys.chord(Keys.CONTROL, "0"));
107
+ } catch (Exception e) {
108
+ }
89 109
}
90 110
91 111
protected void setUpAuthenticatedSession() {
112
+ // To be able to set a cookie we need to load a page having the target origin
113
+ getWebDriver().get(getContextRoot());
114
+
92 115
logger.info("Authenticating session...");
93 116
Cookie sessionCookie = authenticate(getContextRoot());
94 117
getWebDriver().get(getContextRoot() + "index.html"); // initialize web driver so setting a cookie for the local domain is possible
95
- getWebDriver().manage().addCookie(sessionCookie);
118
+ final Cookie cookieWithoutDomain = new Cookie(sessionCookie.getName(), sessionCookie.getValue(), null, sessionCookie.getPath(), sessionCookie.getExpiry(), sessionCookie.isSecure(), sessionCookie.isHttpOnly());
119
+ getWebDriver().manage().addCookie(cookieWithoutDomain);
96 120
logger.info("...obtained session cookie "+sessionCookie);
97 121
}
98 122
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestRefreshableSelectionModel.java
... ...
@@ -13,8 +13,6 @@ import org.openqa.selenium.WebDriver;
13 13
import org.openqa.selenium.support.ui.ExpectedCondition;
14 14
import org.openqa.selenium.support.ui.WebDriverWait;
15 15
16
-import com.sap.sailing.selenium.core.WebDriverWindow;
17
-import com.sap.sailing.selenium.core.WindowManager;
18 16
import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage;
19 17
import com.sap.sailing.selenium.pages.adminconsole.connectors.SmartphoneTrackingEventManagementPanelPO;
20 18
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfigurationPanelPO;
... ...
@@ -36,10 +34,6 @@ import com.sap.sailing.selenium.pages.gwt.DataEntryPO;
36 34
import com.sap.sailing.selenium.test.AbstractSeleniumTest;
37 35
38 36
public class TestRefreshableSelectionModel extends AbstractSeleniumTest {
39
- private static WindowManager manager;
40
- private static WebDriverWindow windowForEdit;
41
- private static WebDriverWindow windowForSelection;
42
-
43 37
// TestMaintenanceOfSelectionAfterDataChanges
44 38
private CompetitorEntry competitorEntry;
45 39
private CompetitorEntry competitorEntryToSelect;
... ...
@@ -66,9 +60,6 @@ public class TestRefreshableSelectionModel extends AbstractSeleniumTest {
66 60
@Before
67 61
public void setUp() {
68 62
clearState(getContextRoot());
69
- manager = this.environment.getWindowManager();
70
- windowForEdit = manager.getCurrentWindow();
71
- windowForSelection = manager.openNewWindow();
72 63
super.setUp();
73 64
}
74 65
... ...
@@ -80,85 +71,87 @@ public class TestRefreshableSelectionModel extends AbstractSeleniumTest {
80 71
81 72
@Test
82 73
public void testMaintenanceOfSelectionAfterDataChanges() {
83
- windowForEdit.switchToWindow();
84
- final TrackedRacesCompetitorsPanelPO competitorsPanel = goToCompetitorsPanel();
85
-
86
- for (int i = 0; i < 2; i++) {
74
+ this.environment.getWindowManager().withExtraWindow((windowForSelection, windowForEdit) -> {
75
+ windowForEdit.switchToWindow();
76
+ final TrackedRacesCompetitorsPanelPO competitorsPanel = goToCompetitorsPanel();
77
+
78
+ for (int i = 0; i < 2; i++) {
79
+ TrackedRacesCompetitorEditDialogPO dialog = competitorsPanel.pushAddCompetitorButton();
80
+ dialog.setNameTextBox("" + System.currentTimeMillis());
81
+ dialog.setShortNameTextBox("" + System.currentTimeMillis());
82
+ dialog.pressOk();
83
+ }
84
+
87 85
TrackedRacesCompetitorEditDialogPO dialog = competitorsPanel.pushAddCompetitorButton();
88
- dialog.setNameTextBox("" + System.currentTimeMillis());
89
- dialog.setShortNameTextBox("" + System.currentTimeMillis());
86
+ final String name = "" + System.currentTimeMillis();
87
+ dialog.setNameTextBox(name);
88
+ final String shortName = "" + System.currentTimeMillis();
89
+ dialog.setShortNameTextBox(shortName);
90 90
dialog.pressOk();
91
- }
92
-
93
- TrackedRacesCompetitorEditDialogPO dialog = competitorsPanel.pushAddCompetitorButton();
94
- final String name = "" + System.currentTimeMillis();
95
- dialog.setNameTextBox(name);
96
- final String shortName = "" + System.currentTimeMillis();
97
- dialog.setShortNameTextBox(shortName);
98
- dialog.pressOk();
99
-
100
- boolean found = false;
101
- for (final CompetitorEntry it : competitorsPanel.getCompetitorTable().getEntries()) {
102
- String itName = it.getName();
103
- if (itName.equals(name)) {
104
- found = true;
105
- competitorEntry = it;
106
- break;
91
+
92
+ boolean found = false;
93
+ for (final CompetitorEntry it : competitorsPanel.getCompetitorTable().getEntries()) {
94
+ String itName = it.getName();
95
+ if (itName.equals(name)) {
96
+ found = true;
97
+ competitorEntry = it;
98
+ break;
99
+ }
107 100
}
108
- }
109
- assertTrue(found);
110
-
111
- windowForSelection.switchToWindow();
112
- TrackedRacesCompetitorsPanelPO competitorPanelForSelection = goToCompetitorsPanel();
113
- found = false;
114
- for (final CompetitorEntry it : competitorPanelForSelection.getCompetitorTable().getEntries()) {
115
- String itName = it.getName();
116
- if (itName.equals(name)) {
117
- found = true;
118
- competitorEntryToSelect = it;
119
- break;
101
+ assertTrue(found);
102
+
103
+ windowForSelection.switchToWindow();
104
+ TrackedRacesCompetitorsPanelPO competitorPanelForSelection = goToCompetitorsPanel();
105
+ found = false;
106
+ for (final CompetitorEntry it : competitorPanelForSelection.getCompetitorTable().getEntries()) {
107
+ String itName = it.getName();
108
+ if (itName.equals(name)) {
109
+ found = true;
110
+ competitorEntryToSelect = it;
111
+ break;
112
+ }
120 113
}
121
- }
122
- assertTrue(found);
123
- competitorPanelForSelection.getCompetitorTable().selectEntry(competitorEntryToSelect);
124
-
125
- assertEquals(1, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().size());
126
- assertEquals(name, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().get(0).getName());
127
- assertEquals(shortName, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().get(0).getShortName());
128
- // change competitor
129
- windowForEdit.switchToWindow();
130
- dialog = competitorEntry.clickEditButton();
131
- final String changedName = "" + System.currentTimeMillis();
132
- dialog.setNameTextBox(changedName);
133
- final String changedShortName = "" + System.currentTimeMillis();
134
- dialog.setShortNameTextBox(changedShortName);
135
- dialog.pressOk();
136
-
137
- // assert selection
138
- windowForSelection.switchToWindow();
139
-
140
- competitorPanelForSelection.pushRefreshButton();
141
- WebDriverWait waitTimer = new WebDriverWait(competitorPanelForSelection.driver, 10);
142
- ExpectedCondition<Boolean> condition = new ExpectedCondition<Boolean>() {
143
- @Override
144
- public Boolean apply(WebDriver arg0) {
145
- return competitorPanelForSelection.getCompetitorTable().getSelectedEntries().size() == 1;
146
- }
147
- };
148
- waitTimer.until(condition);
149
-
150
- assertEquals(1, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().size());
151
- for (final CompetitorEntry it : competitorPanelForSelection.getCompetitorTable().getEntries()) {
152
- String itName = it.getName();
153
- if (itName.equals(changedName)) {
154
- found = true;
155
- competitorEntryToSelect = it;
156
- break;
114
+ assertTrue(found);
115
+ competitorPanelForSelection.getCompetitorTable().selectEntry(competitorEntryToSelect);
116
+
117
+ assertEquals(1, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().size());
118
+ assertEquals(name, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().get(0).getName());
119
+ assertEquals(shortName, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().get(0).getShortName());
120
+ // change competitor
121
+ windowForEdit.switchToWindow();
122
+ dialog = competitorEntry.clickEditButton();
123
+ final String changedName = "" + System.currentTimeMillis();
124
+ dialog.setNameTextBox(changedName);
125
+ final String changedShortName = "" + System.currentTimeMillis();
126
+ dialog.setShortNameTextBox(changedShortName);
127
+ dialog.pressOk();
128
+
129
+ // assert selection
130
+ windowForSelection.switchToWindow();
131
+
132
+ competitorPanelForSelection.pushRefreshButton();
133
+ WebDriverWait waitTimer = new WebDriverWait(competitorPanelForSelection.driver, 10);
134
+ ExpectedCondition<Boolean> condition = new ExpectedCondition<Boolean>() {
135
+ @Override
136
+ public Boolean apply(WebDriver arg0) {
137
+ return competitorPanelForSelection.getCompetitorTable().getSelectedEntries().size() == 1;
138
+ }
139
+ };
140
+ waitTimer.until(condition);
141
+
142
+ assertEquals(1, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().size());
143
+ for (final CompetitorEntry it : competitorPanelForSelection.getCompetitorTable().getEntries()) {
144
+ String itName = it.getName();
145
+ if (itName.equals(changedName)) {
146
+ found = true;
147
+ competitorEntryToSelect = it;
148
+ break;
149
+ }
157 150
}
158
- }
159
- assertTrue(found);
160
- assertEquals(changedName, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().get(0).getName());
161
- assertEquals(changedShortName, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().get(0).getShortName());
151
+ assertTrue(found);
152
+ assertEquals(changedName, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().get(0).getName());
153
+ assertEquals(changedShortName, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().get(0).getShortName());
154
+ });
162 155
}
163 156
164 157
private void setUpTestRefreshOfDependingUIElements() {
... ...
@@ -201,62 +194,63 @@ public class TestRefreshableSelectionModel extends AbstractSeleniumTest {
201 194
202 195
@Test
203 196
public void testRefreshOfDependingUIElements() {
204
- windowForSelection.switchToWindow();
205
- setUpTestRefreshOfDependingUIElements();
206
- AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
207
- SmartphoneTrackingEventManagementPanelPO smartphoneTrackingPanel = adminConsole.goToSmartphoneTrackingPanel();
208
- CellTablePO<DataEntryPO> leaderboards = smartphoneTrackingPanel.getLeaderboardTable();
209
- // select leaderboard
210
- DataEntryPO entryToSelect = null;
211
- for(DataEntryPO entry : leaderboards.getEntries()) {
212
- if(entry.getColumnContent("Name").equals(LEADERBOARD)) {
213
- entryToSelect = entry;
214
- break;
197
+ this.environment.getWindowManager().withExtraWindow((windowForSelection, windowForEdit) -> {
198
+ windowForSelection.switchToWindow();
199
+ setUpTestRefreshOfDependingUIElements();
200
+ AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
201
+ SmartphoneTrackingEventManagementPanelPO smartphoneTrackingPanel = adminConsole.goToSmartphoneTrackingPanel();
202
+ CellTablePO<DataEntryPO> leaderboards = smartphoneTrackingPanel.getLeaderboardTable();
203
+ // select leaderboard
204
+ DataEntryPO entryToSelect = null;
205
+ for(DataEntryPO entry : leaderboards.getEntries()) {
206
+ if(entry.getColumnContent("Name").equals(LEADERBOARD)) {
207
+ entryToSelect = entry;
208
+ break;
209
+ }
215 210
}
216
- }
217
- assertNotNull(entryToSelect);
218
- leaderboards.selectEntry(entryToSelect);
219
-
220
- RaceColumnTableWrapperPO raceColumnTableWrapper = smartphoneTrackingPanel.getRaceColumnTableWrapper();
221
- CellTablePO<DataEntryPO> raceColumnTable = raceColumnTableWrapper.getRaceColumnTable();
222
- final int anzRaceColumns = raceColumnTable.getEntries().size();
223
- assertEquals(5, anzRaceColumns);
224
-
225
- // Open a second window & setup second window
226
- windowForEdit.switchToWindow();
227
-
228
- AdminConsolePage adminConsoleForEdit = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
229
- RegattaStructureManagementPanelPO regattaStructure = adminConsoleForEdit.goToRegattaStructure();
230
-
231
- RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta);
232
- SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME);
233
- seriesDialog.addRaces(6, 7);
234
- seriesDialog.pressOk();
235
-
236
- windowForSelection.switchToWindow();
237
- adminConsole.goToTracTracEvents();
238
- smartphoneTrackingPanel = adminConsole.goToSmartphoneTrackingPanel();
239
- leaderboards = smartphoneTrackingPanel.getLeaderboardTable();
240
- // select leaderboard
241
- entryToSelect = null;
242
- for(DataEntryPO entry : leaderboards.getEntries()) {
243
- if(entry.getColumnContent("Name").equals(LEADERBOARD)) {
244
- entryToSelect = entry;
245
- break;
211
+ assertNotNull(entryToSelect);
212
+ leaderboards.selectEntry(entryToSelect);
213
+
214
+ RaceColumnTableWrapperPO raceColumnTableWrapper = smartphoneTrackingPanel.getRaceColumnTableWrapper();
215
+ CellTablePO<DataEntryPO> raceColumnTable = raceColumnTableWrapper.getRaceColumnTable();
216
+ final int anzRaceColumns = raceColumnTable.getEntries().size();
217
+ assertEquals(5, anzRaceColumns);
218
+
219
+ // Open a second window & setup second window
220
+ windowForEdit.switchToWindow();
221
+
222
+ AdminConsolePage adminConsoleForEdit = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
223
+ RegattaStructureManagementPanelPO regattaStructure = adminConsoleForEdit.goToRegattaStructure();
224
+
225
+ RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta);
226
+ SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME);
227
+ seriesDialog.addRaces(6, 7);
228
+ seriesDialog.pressOk();
229
+
230
+ windowForSelection.switchToWindow();
231
+ adminConsole.goToTracTracEvents();
232
+ smartphoneTrackingPanel = adminConsole.goToSmartphoneTrackingPanel();
233
+ leaderboards = smartphoneTrackingPanel.getLeaderboardTable();
234
+ // select leaderboard
235
+ entryToSelect = null;
236
+ for(DataEntryPO entry : leaderboards.getEntries()) {
237
+ if(entry.getColumnContent("Name").equals(LEADERBOARD)) {
238
+ entryToSelect = entry;
239
+ break;
240
+ }
246 241
}
247
- }
248
- assertNotNull(entryToSelect);
249
- leaderboards.selectEntry(entryToSelect);
250
-
251
- raceColumnTableWrapper = smartphoneTrackingPanel.getRaceColumnTableWrapper();
252
- raceColumnTable = raceColumnTableWrapper.getRaceColumnTable();
253
- final int newAnzRaceColumns = raceColumnTable.getEntries().size();
254
- assertEquals(7, newAnzRaceColumns);
242
+ assertNotNull(entryToSelect);
243
+ leaderboards.selectEntry(entryToSelect);
244
+
245
+ raceColumnTableWrapper = smartphoneTrackingPanel.getRaceColumnTableWrapper();
246
+ raceColumnTable = raceColumnTableWrapper.getRaceColumnTable();
247
+ final int newAnzRaceColumns = raceColumnTable.getEntries().size();
248
+ assertEquals(7, newAnzRaceColumns);
249
+ });
255 250
}
256 251
257 252
@Test
258 253
public void testMaintenanceOfSelectionAfterFilteringTrackedracesOnLeaderboardConfigPanel() {
259
- windowForSelection.switchToWindow();
260 254
setUpTestRefreshOfDependingUIElements();
261 255
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
262 256
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
... ...
@@ -267,12 +261,7 @@ public class TestRefreshableSelectionModel extends AbstractSeleniumTest {
267 261
tracTracEvents.listTrackableRaces(IDM_5O5_2013_JSON_URL);
268 262
tracTracEvents.setReggataForTracking(this.regatta);
269 263
tracTracEvents.setTrackSettings(false, false, false);
270
- // TODO: There exists a bug in Selenium with key modifiers (Issue 3734 and 6817), so we can't use multi
271
- // selection (Firefox on Windows)
272
- //tracTracEvents.startTrackingForRaces(this.trackableRaces);
273
- for(int i =0; i<2;i++) {
274
- tracTracEvents.startTrackingForRace(trackableRaces.get(i));
275
- }
264
+ tracTracEvents.startTrackingForRaces(this.trackableRaces);
276 265
277 266
leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
278 267
LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString());
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestSmartphoneTrackingEventManagementPanel.java
... ...
@@ -15,9 +15,9 @@ import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfig
15 15
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO;
16 16
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO.RaceDescriptor;
17 17
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaDetailsCompositePO;
18
+import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor;
18 19
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaStructureManagementPanelPO;
19 20
import com.sap.sailing.selenium.pages.adminconsole.regatta.SeriesEditDialogPO;
20
-import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor;
21 21
import com.sap.sailing.selenium.pages.adminconsole.tracking.RaceColumnTableWrapperPO;
22 22
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO;
23 23
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.TrackedRaceDescriptor;
... ...
@@ -132,11 +132,6 @@ public class TestSmartphoneTrackingEventManagementPanel extends AbstractSelenium
132 132
tracTracEvents.listTrackableRaces(IDM_5O5_2013_JSON_URL);
133 133
tracTracEvents.setReggataForTracking(this.regatta);
134 134
tracTracEvents.setTrackSettings(false, false, false);
135
- // TODO: There exists a bug in Selenium with key modifiers (Issue 3734 and 6817), so we can't use multi
136
- // selection (Firefox on Windows)
137
- //tracTracEvents.startTrackingForRaces(this.trackableRaces);
138
- for(TrackableRaceDescriptor race : this.trackableRaces) {
139
- tracTracEvents.startTrackingForRace(race);
140
- }
135
+ tracTracEvents.startTrackingForRaces(this.trackableRaces);
141 136
}
142 137
}
... ...
\ No newline at end of file
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestStartAndStopTrackingForTracTracEvents.java
... ...
@@ -1,16 +1,10 @@
1 1
package com.sap.sailing.selenium.test.adminconsole;
2 2
3
-import static org.hamcrest.Matchers.containsString;
4 3
import static org.hamcrest.Matchers.equalTo;
5 4
import static org.junit.Assert.assertThat;
6
-import static org.junit.Assert.assertTrue;
7 5
8 6
import org.junit.Before;
9 7
import org.junit.Test;
10
-import org.openqa.selenium.Alert;
11
-import org.openqa.selenium.By;
12
-import org.openqa.selenium.WebDriver.TargetLocator;
13
-import org.openqa.selenium.WebElement;
14 8
15 9
import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage;
16 10
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor;
... ...
@@ -90,14 +84,7 @@ public class TestStartAndStopTrackingForTracTracEvents extends AbstractSeleniumT
90 84
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
91 85
tracTracEvents.setReggataForTracking(DEFAULT_REGATTA);
92 86
tracTracEvents.setTrackSettings(false, false, false);
93
- tracTracEvents.startTrackingForRace(this.trackableRace);
94
-
95
- TargetLocator locator = getWebDriver().switchTo();
96
- Alert alert = locator.alert();
97
- String text = alert.getText();
98
- alert.dismiss();
99
- String message = "There is at least one regatta for the selected boat classes.";
100
- assertThat(text, containsString(message));
87
+ tracTracEvents.startTrackingForRacesAndAcceptDefaultRegattaWarning(this.trackableRace);
101 88
}
102 89
103 90
@Test
... ...
@@ -112,17 +99,6 @@ public class TestStartAndStopTrackingForTracTracEvents extends AbstractSeleniumT
112 99
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
113 100
tracTracEvents.setReggataForTracking(idm2013Descriptor);
114 101
tracTracEvents.setTrackSettings(false, false, false);
115
- tracTracEvents.startTrackingForRace(this.trackableRace);
116
-
117
- String message = String.format("The selected races contain boat classes which are not the same as "
118
- + "the boat class '%s' of the selected regatta.", IDM_2013_BOAT_CLASS);
119
- for (WebElement element : getWebDriver().findElement(By.id("notificationBar")).findElements(By.cssSelector("*"))) {
120
- if (element.getText().contains(message)) {
121
- element.click();
122
- assertTrue(true);
123
- return;
124
- }
125
- }
126
- assertTrue("Could not find error notification.", false);
102
+ tracTracEvents.startTrackingForRaceAndAwaitBoatClassError(this.trackableRace, IDM_2013_BOAT_CLASS);
127 103
}
128 104
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/autoplay/TestAutoPlay.java
... ...
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertTrue;
6 6
7 7
import java.util.Date;
8 8
import java.util.List;
9
+import java.util.function.Function;
9 10
10 11
import javax.xml.bind.DatatypeConverter;
11 12
... ...
@@ -15,7 +16,6 @@ import org.junit.Test;
15 16
import org.openqa.selenium.WebDriver;
16 17
import org.openqa.selenium.support.ui.WebDriverWait;
17 18
18
-import com.google.common.base.Function;
19 19
import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage;
20 20
import com.sap.sailing.selenium.pages.adminconsole.event.EventConfigurationPanelPO;
21 21
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfigurationPanelPO;
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java
... ...
@@ -11,8 +11,6 @@ import org.junit.Before;
11 11
import org.junit.Ignore;
12 12
import org.junit.Test;
13 13
14
-import com.sap.sailing.selenium.core.WebDriverWindow;
15
-import com.sap.sailing.selenium.core.WindowManager;
16 14
import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage;
17 15
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfigurationPanelPO;
18 16
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO;
... ...
@@ -73,117 +71,113 @@ public class TestLeaderboardConfiguration extends AbstractSeleniumTest {
73 71
74 72
@Test
75 73
public void testDynamicRaceLinking() {
76
- // Open a second window which we use for the leaderboard later
77
- WindowManager manager = this.environment.getWindowManager();
78
- WebDriverWindow leaderboardWindow = manager.getCurrentWindow();
79
- WebDriverWindow adminConsoleWindow = manager.openNewWindow();
80
-
81
- // Open the leaderboard and check for "empty" leaderboard
82
- LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false);
83
- LeaderboardTablePO table = leaderboard.getLeaderboardTable();
84
- List<String> races = table.getRaceNames();
85
-
86
- assertThat(races.size(), equalTo(5));
87
- assertThat(table.getEntries().size(), equalTo(28)); // the regatta already has the races linked; regatta leaderboard obtains competitors from regatta
88
- adminConsoleWindow.switchToWindow();
89
- AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
90
- LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
91
- LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString());
92
-
93
- Integer[] expectedPointsForFindelJens = new Integer[] {2, 18, 12, 4, 7};
94
- Integer[] expectedRankForFindelJens = new Integer[] {2, 9, 11, 7, 6}; // Bogacki with no score in R1 expected to end up at end of leaderboard
95
-
96
- // Link the races and check the leaderboard again
97
- for (int i = 0; i < 5; i++) {
98
- leaderboardDetails.linkRace(this.leaderboardRaces.get(i), this.trackedRaces.get(i));
99
- leaderboardWindow.switchToWindow();
100
- leaderboard.refresh();
101
- List<LeaderboardEntry> allEntries = table.getEntries();
102
- LeaderboardEntry findelJens = table.getEntry("8875");
103
- Integer points = findelJens.getPointsForRace(String.format("D%s", i + 1));
104
- Integer rank = findelJens.getTotalRank();
105
- // Assertions
106
- assertThat("Number of competitors does not match",
107
- allEntries.size(), equalTo(28));
108
- assertThat("Points for race 'D" + (i + 1) + "' do not match for competitor '8875' (Findel, Jens)",
109
- points, equalTo(expectedPointsForFindelJens[i]));
110
- assertThat("Total rank after " + (i + 1) + " race(s) does not match for competitor '8875' (Findel, Jens)",
111
- rank, equalTo(expectedRankForFindelJens[i]));
74
+ this.environment.getWindowManager().withExtraWindow((leaderboardWindow, adminConsoleWindow) -> {
75
+ // Open the leaderboard and check for "empty" leaderboard
76
+ LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false);
77
+ LeaderboardTablePO table = leaderboard.getLeaderboardTable();
78
+ List<String> races = table.getRaceNames();
79
+
80
+ assertThat(races.size(), equalTo(5));
81
+ assertThat(table.getEntries().size(), equalTo(28)); // the regatta already has the races linked; regatta leaderboard obtains competitors from regatta
112 82
adminConsoleWindow.switchToWindow();
113
- }
83
+ AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
84
+ LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
85
+ LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString());
86
+
87
+ Integer[] expectedPointsForFindelJens = new Integer[] {2, 18, 12, 4, 7};
88
+ Integer[] expectedRankForFindelJens = new Integer[] {2, 9, 11, 7, 6}; // Bogacki with no score in R1 expected to end up at end of leaderboard
89
+
90
+ // Link the races and check the leaderboard again
91
+ for (int i = 0; i < 5; i++) {
92
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(i), this.trackedRaces.get(i));
93
+ leaderboardWindow.switchToWindow();
94
+ leaderboard.refresh();
95
+ List<LeaderboardEntry> allEntries = table.getEntries();
96
+ LeaderboardEntry findelJens = table.getEntry("8875");
97
+ Integer points = findelJens.getPointsForRace(String.format("D%s", i + 1));
98
+ Integer rank = findelJens.getTotalRank();
99
+ // Assertions
100
+ assertThat("Number of competitors does not match",
101
+ allEntries.size(), equalTo(28));
102
+ assertThat("Points for race 'D" + (i + 1) + "' do not match for competitor '8875' (Findel, Jens)",
103
+ points, equalTo(expectedPointsForFindelJens[i]));
104
+ assertThat("Total rank after " + (i + 1) + " race(s) does not match for competitor '8875' (Findel, Jens)",
105
+ rank, equalTo(expectedRankForFindelJens[i]));
106
+ adminConsoleWindow.switchToWindow();
107
+ }
108
+ });
114 109
}
115 110
116 111
@Test
117 112
public void testDynamicRaceDeletion() {
118
- WindowManager manager = this.environment.getWindowManager();
119
- WebDriverWindow adminConsoleWindow = manager.getCurrentWindow();
120
- WebDriverWindow leaderboardWindow = manager.openNewWindow();
121
- // Go to the administration console and link all 5 races
122
- AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
123
- LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
124
- LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString());
125
- leaderboardDetails.linkRace(this.leaderboardRaces.get(0), this.trackedRaces.get(0));
126
- leaderboardDetails.linkRace(this.leaderboardRaces.get(1), this.trackedRaces.get(1));
127
- leaderboardDetails.linkRace(this.leaderboardRaces.get(2), this.trackedRaces.get(2));
128
- leaderboardDetails.linkRace(this.leaderboardRaces.get(3), this.trackedRaces.get(3));
129
- leaderboardDetails.linkRace(this.leaderboardRaces.get(4), this.trackedRaces.get(4));
130
- // Open the leaderboard in our second window
131
- leaderboardWindow.switchToWindow();
132
- LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false);
133
- LeaderboardTablePO table = leaderboard.getLeaderboardTable();
134
- // Go back to the administration console and delete third race
135
- adminConsoleWindow.switchToWindow();
136
- RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
137
- RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta);
138
- SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME);
139
- seriesDialog.deleteRace("D3");
140
- seriesDialog.pressOk(true);
141
- // Now we can check the result with our expectation
142
- leaderboardWindow.switchToWindow();
143
- leaderboard.refresh();
144
- assertThat("Race names do not match after deletion of race 'D3'",
145
- table.getRaceNames(), equalTo(Arrays.asList("D1", "D2", "D4", "D5")));
113
+ this.environment.getWindowManager().withExtraWindow((adminConsoleWindow, leaderboardWindow) -> {
114
+ // Go to the administration console and link all 5 races
115
+ AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
116
+ LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
117
+ LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString());
118
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(0), this.trackedRaces.get(0));
119
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(1), this.trackedRaces.get(1));
120
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(2), this.trackedRaces.get(2));
121
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(3), this.trackedRaces.get(3));
122
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(4), this.trackedRaces.get(4));
123
+ // Open the leaderboard in our second window
124
+ leaderboardWindow.switchToWindow();
125
+ LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false);
126
+ LeaderboardTablePO table = leaderboard.getLeaderboardTable();
127
+ // Go back to the administration console and delete third race
128
+ adminConsoleWindow.switchToWindow();
129
+ RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
130
+ RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta);
131
+ SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME);
132
+ seriesDialog.deleteRace("D3");
133
+ seriesDialog.pressOk(true, false);
134
+ final List<String> expectedRaces = Arrays.asList("D1", "D2", "D4", "D5");
135
+ regattaDetails.waitForRacesOfSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME, expectedRaces);
136
+ // Now we can check the result with our expectation
137
+ leaderboardWindow.switchToWindow();
138
+ leaderboard.refresh();
139
+ assertThat("Race names do not match after deletion of race 'D3'", table.getRaceNames(),
140
+ equalTo(expectedRaces));
141
+ });
146 142
}
147 143
148 144
@Ignore("This test belongs to bug 1892 and currently fails. It is currently enabled on branch bug1892.")
149 145
@Test
150 146
public void testDynamicRenamingOfRace() {
151
- WindowManager manager = this.environment.getWindowManager();
152
- WebDriverWindow adminConsoleWindow = manager.getCurrentWindow();
153
- WebDriverWindow leaderboardWindow = manager.openNewWindow();
154
-
155
- // Go to the administration console and link all 5 races
156
- AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
157
- LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
158
- LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString());
159
-
160
- leaderboardDetails.linkRace(this.leaderboardRaces.get(0), this.trackedRaces.get(0));
161
- leaderboardDetails.linkRace(this.leaderboardRaces.get(1), this.trackedRaces.get(1));
162
- leaderboardDetails.linkRace(this.leaderboardRaces.get(2), this.trackedRaces.get(2));
163
- leaderboardDetails.linkRace(this.leaderboardRaces.get(3), this.trackedRaces.get(3));
164
- leaderboardDetails.linkRace(this.leaderboardRaces.get(4), this.trackedRaces.get(4));
165
-
166
- // Open the leaderboard in our second window
167
- leaderboardWindow.switchToWindow();
168
-
169
- LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false);
170
- LeaderboardTablePO table = leaderboard.getLeaderboardTable();
171
-
172
- // Go back to the administration console and rename the first race
173
- adminConsoleWindow.switchToWindow();
174
-
175
- RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
176
- RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta);
177
- SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME);
178
- seriesDialog.renameRace("D1", "Q");
179
- seriesDialog.pressOk(true);
180
-
181
- // Now we can check the result with our expectation
182
- leaderboardWindow.switchToWindow();
183
- leaderboard.refresh();
184
- List<String> races = table.getRaceNames();
185
- assertThat("Race names do not match after renaming race 'D1' to 'Q'",
186
- races, equalTo(Arrays.asList("Q", "D2", "D3", "D4", "D5")));
147
+ this.environment.getWindowManager().withExtraWindow((adminConsoleWindow, leaderboardWindow) -> {
148
+ // Go to the administration console and link all 5 races
149
+ AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
150
+ LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
151
+ LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString());
152
+
153
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(0), this.trackedRaces.get(0));
154
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(1), this.trackedRaces.get(1));
155
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(2), this.trackedRaces.get(2));
156
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(3), this.trackedRaces.get(3));
157
+ leaderboardDetails.linkRace(this.leaderboardRaces.get(4), this.trackedRaces.get(4));
158
+
159
+ // Open the leaderboard in our second window
160
+ leaderboardWindow.switchToWindow();
161
+
162
+ LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false);
163
+ LeaderboardTablePO table = leaderboard.getLeaderboardTable();
164
+
165
+ // Go back to the administration console and rename the first race
166
+ adminConsoleWindow.switchToWindow();
167
+
168
+ RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
169
+ RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta);
170
+ SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME);
171
+ seriesDialog.renameRace("D1", "Q");
172
+ seriesDialog.pressOk(true, false);
173
+
174
+ // Now we can check the result with our expectation
175
+ leaderboardWindow.switchToWindow();
176
+ leaderboard.refresh();
177
+ List<String> races = table.getRaceNames();
178
+ assertThat("Race names do not match after renaming race 'D1' to 'Q'",
179
+ races, equalTo(Arrays.asList("Q", "D2", "D3", "D4", "D5")));
180
+ });
187 181
}
188 182
189 183
private void configureLeaderboard() {
... ...
@@ -209,20 +203,10 @@ public class TestLeaderboardConfiguration extends AbstractSeleniumTest {
209 203
tracTracEvents.listTrackableRaces(IDM_5O5_2013_JSON_URL);
210 204
tracTracEvents.setReggataForTracking(this.regatta);
211 205
tracTracEvents.setTrackSettings(false, false, false);
212
- // TODO: There exists a bug in Selenium with key modifiers (Issue 3734 and 6817), so we can't use multi
213
- // selection (Firefox on Windows)
214
- //tracTracEvents.startTrackingForRaces(this.trackableRaces);
215
- for(TrackableRaceDescriptor race : this.trackableRaces) {
216
- tracTracEvents.startTrackingForRace(race);
217
- }
206
+ tracTracEvents.startTrackingForRaces(trackableRaces);
218 207
219 208
TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList();
220 209
trackedRacesList.waitForTrackedRaces(this.trackedRaces, Status.FINISHED); // TracAPI puts REPLAY races into FINISHED mode when done loading
221
- // TODO: There exists a bug in Selenium with key modifiers (Issue 3734 and 6817), so we can't use multi
222
- // selection (Firefox on Windows)
223
- //trackedRacesList.stopTracking(this.trackedRaces);
224
- for (TrackedRaceDescriptor race : this.trackedRaces) {
225
- trackedRacesList.stopTracking(race);
226
- }
210
+ trackedRacesList.stopTracking(this.trackedRaces);
227 211
}
228 212
}
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestSwitchingOffStartOfRaceInference.java
... ...
@@ -11,8 +11,6 @@ import java.util.List;
11 11
import org.junit.Before;
12 12
import org.junit.Test;
13 13
14
-import com.sap.sailing.selenium.core.WebDriverWindow;
15
-import com.sap.sailing.selenium.core.WindowManager;
16 14
import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage;
17 15
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfigurationPanelPO;
18 16
import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO;
... ...
@@ -62,33 +60,31 @@ public class TestSwitchingOffStartOfRaceInference extends AbstractSeleniumTest {
62 60
63 61
@Test
64 62
public void testCorrectDisplayOfRaceColumnWithAndWithoutStartTimeInference() {
65
- WindowManager manager = this.environment.getWindowManager();
66
- WebDriverWindow adminConsoleWindow = manager.getCurrentWindow();
67
- WebDriverWindow leaderboardWindow = manager.openNewWindow();
68
- leaderboardWindow.switchToWindow();
69
- LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, /* race details */ false);
70
- LeaderboardTablePO leaderboardTable = leaderboard.getLeaderboardTable();
71
- List<String> races = leaderboardTable.getRaceNames();
72
- assertThat("Expected only D3", races, equalTo(Arrays.asList("D3")));
73
- int d3ColumnIndex = leaderboardTable.getColumnIndex("D3");
74
- for (LeaderboardEntry e : leaderboardTable.getEntries()) {
75
- String raceColumnContent = e.getColumnContent(d3ColumnIndex);
76
- assertTrue(Integer.parseInt(raceColumnContent) > 0); // all competitors have a positive score in R3
77
- }
78
- adminConsoleWindow.switchToWindow();
79
- // Go to the administration console and unset the "useStartTimeInference" flag
80
- RegattaStructureManagementPanelPO regattaManagementPanel = adminConsole.goToRegattaStructure();
81
- RegattaListCompositePO regattaList = regattaManagementPanel.getRegattaList();
82
- RegattaEditDialogPO regattaEditDialog = regattaList.editRegatta(regatta);
83
- regattaEditDialog.setUseStartTimeInference(false);
84
- regattaEditDialog.pressOk();
85
- leaderboardWindow.switchToWindow();
86
- leaderboard.refresh();
87
- for (LeaderboardEntry e : leaderboardTable.getEntries()) {
88
- String raceColumnContent = e.getColumnContent(d3ColumnIndex);
89
- assertEquals("", raceColumnContent); // all competitors have an empty score because there is no start time anymore
90
- }
91
- leaderboardWindow.close();
63
+ this.environment.getWindowManager().withExtraWindow((adminConsoleWindow, leaderboardWindow) -> {
64
+ leaderboardWindow.switchToWindow();
65
+ LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, /* race details */ false);
66
+ LeaderboardTablePO leaderboardTable = leaderboard.getLeaderboardTable();
67
+ List<String> races = leaderboardTable.getRaceNames();
68
+ assertThat("Expected only D3", races, equalTo(Arrays.asList("D3")));
69
+ int d3ColumnIndex = leaderboardTable.getColumnIndex("D3");
70
+ for (LeaderboardEntry e : leaderboardTable.getEntries()) {
71
+ String raceColumnContent = e.getColumnContent(d3ColumnIndex);
72
+ assertTrue(Integer.parseInt(raceColumnContent) > 0); // all competitors have a positive score in R3
73
+ }
74
+ adminConsoleWindow.switchToWindow();
75
+ // Go to the administration console and unset the "useStartTimeInference" flag
76
+ RegattaStructureManagementPanelPO regattaManagementPanel = adminConsole.goToRegattaStructure();
77
+ RegattaListCompositePO regattaList = regattaManagementPanel.getRegattaList();
78
+ RegattaEditDialogPO regattaEditDialog = regattaList.editRegatta(regatta);
79
+ regattaEditDialog.setUseStartTimeInference(false);
80
+ regattaEditDialog.pressOk();
81
+ leaderboardWindow.switchToWindow();
82
+ leaderboard.refresh();
83
+ for (LeaderboardEntry e : leaderboardTable.getEntries()) {
84
+ String raceColumnContent = e.getColumnContent(d3ColumnIndex);
85
+ assertEquals("", raceColumnContent); // all competitors have an empty score because there is no start time anymore
86
+ }
87
+ });
92 88
}
93 89
94 90
private AdminConsolePage configureRegattaAndLeaderboard() {
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/raceboard/SettingsTest.java
... ...
@@ -77,7 +77,6 @@ public class SettingsTest extends AbstractSeleniumTest {
77 77
// Modes settings were formerly patched on the user defaults but are now patched on top of the system defaults.
78 78
// In addition, there are now different settigns keys per mode so that settigns for one mode do not have an effect on other modes.
79 79
// To verify this, there are new tests below but these do not test ReceBoard's embedded Leaderboard.
80
- // FIXME uncomment leaderboard test code when selenium infrastructure gets an upgrade
81 80
/**
82 81
* Verifies the settings storage of the raceboard. Checks the precedences of url, context specific settings, mode
83 82
* settings and global settings.
... ...
@@ -95,35 +94,29 @@ public class SettingsTest extends AbstractSeleniumTest {
95 94
RaceBoardPage raceboard = RaceBoardPage.goToRaceboardUrl(getWebDriver(), getContextRoot(), BMW_CUP_REGATTA,
96 95
BMW_CUP_REGATTA, String.format(BMW_RACE, 1), "PLAYER");
97 96
98
- //FIXME uncomment the leaderboard code when selenium on remote build server displays the raceboard properly
99
-
100
-// DetailCheckboxInfo[] detailsToSelect = new DetailCheckboxInfo[] {
101
-// // Overall details
102
-//
103
-// // Race details
104
-// DetailCheckboxInfo.RACE_GAP_TO_LEADER,
105
-// DetailCheckboxInfo.RACE_CURRENT_SPEED_OVER_GROUND,
106
-// DetailCheckboxInfo.DISPLAY_LEGS,
107
-//
108
-// // Race Start Analysis
109
-//
110
-// // Leg Details
111
-// DetailCheckboxInfo.AVERAGE_SPEED_OVER_GROUND, DetailCheckboxInfo.DISTANCE, DetailCheckboxInfo.RANK_GAIN,
112
-//
113
-// // Maneuvers
114
-// DetailCheckboxInfo.TACK, DetailCheckboxInfo.JIBE,
115
-// DetailCheckboxInfo.PENALTY_CIRCLE
116
-//
117
-// };
118
-//
119
-// LeaderboardSettingsDialogPO leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog();
120
-// LeaderboardSettingsPanelPO leaderboardSettingsPanelPO =
121
-// leaderboardSettingsDialog.getLeaderboardSettingsPanelPO();
122
-// DetailCheckboxInfo[] selectedDetails = leaderboardSettingsPanelPO.getSelectedDetails();
123
-// Assert.assertArrayEquals(detailsToSelect, selectedDetails);
124
-// leaderboardSettingsPanelPO.setRefreshInterval(2);
125
-// leaderboardSettingsDialog.pressMakeDefault();
126
-// leaderboardSettingsDialog.pressCancel();
97
+ DetailCheckboxInfo[] detailsToSelect = new DetailCheckboxInfo[] {
98
+ // Overall details
99
+
100
+ // Race details
101
+ DetailCheckboxInfo.RACE_GAP_TO_LEADER, DetailCheckboxInfo.RACE_CURRENT_SPEED_OVER_GROUND,
102
+ DetailCheckboxInfo.DISPLAY_LEGS,
103
+
104
+ // Leg Details
105
+ DetailCheckboxInfo.AVERAGE_SPEED_OVER_GROUND, DetailCheckboxInfo.DISTANCE, DetailCheckboxInfo.RANK_GAIN,
106
+
107
+ // Maneuvers
108
+ DetailCheckboxInfo.TACK, DetailCheckboxInfo.JIBE, DetailCheckboxInfo.PENALTY_CIRCLE
109
+
110
+ };
111
+
112
+ LeaderboardSettingsDialogPO leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog();
113
+ LeaderboardSettingsPanelPO leaderboardSettingsPanelPO = leaderboardSettingsDialog
114
+ .getLeaderboardSettingsPanelPO();
115
+ DetailCheckboxInfo[] selectedDetails = leaderboardSettingsPanelPO.getSelectedDetails();
116
+ Assert.assertArrayEquals(detailsToSelect, selectedDetails);
117
+ leaderboardSettingsPanelPO.setRefreshInterval(2);
118
+ leaderboardSettingsDialog.pressMakeDefault();
119
+ leaderboardSettingsDialog.pressCancel();
127 120
128 121
MapSettingsPO mapSettings = raceboard.openMapSettings();
129 122
// Verify initial mode settings
... ...
@@ -136,58 +129,38 @@ public class SettingsTest extends AbstractSeleniumTest {
136 129
raceboard = RaceBoardPage.goToRaceboardUrl(getWebDriver(), getContextRoot(), BMW_CUP_REGATTA, BMW_CUP_REGATTA,
137 130
String.format(BMW_RACE, 1), "WINNING_LANES");
138 131
139
-// detailsToSelect = new DetailCheckboxInfo[] {
140
-// // Overall details
141
-//
142
-// // Race details
143
-// DetailCheckboxInfo.RACE_GAP_TO_LEADER, //merged from user settings
144
-// DetailCheckboxInfo.RACE_DISTANCE,
145
-// DetailCheckboxInfo.RACE_TIME,
146
-// DetailCheckboxInfo.RACE_CURRENT_SPEED_OVER_GROUND, //merged from user settings
147
-// DetailCheckboxInfo.RACE_AVERAGE_ABSOLUTE_CROSS_TRACK_ERROR,
148
-// DetailCheckboxInfo.RACE_AVERAGE_SIGNED_CROSS_TRACK_ERROR,
149
-//
150
-// // Race Start Analysis
151
-//
152
-// // Leg Details
153
-// DetailCheckboxInfo.AVERAGE_SPEED_OVER_GROUND, DetailCheckboxInfo.DISTANCE, DetailCheckboxInfo.RANK_GAIN,
154
-//
155
-// // Maneuvers
156
-// DetailCheckboxInfo.TACK, DetailCheckboxInfo.JIBE,
157
-// DetailCheckboxInfo.PENALTY_CIRCLE
158
-//
159
-// };
160
-//
161
-//
162
-// leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog();
163
-// leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO();
164
-// selectedDetails = leaderboardSettingsPanelPO.getSelectedDetails();
165
-// Assert.assertArrayEquals(detailsToSelect, selectedDetails);
166
-//
167
-// detailsToSelect = new DetailCheckboxInfo[] {
168
-// // Overall details
169
-//
170
-// // Race details
171
-// DetailCheckboxInfo.RACE_GAP_TO_LEADER,
172
-// DetailCheckboxInfo.RACE_DISTANCE,
173
-// DetailCheckboxInfo.RACE_TIME,
174
-// DetailCheckboxInfo.RACE_CURRENT_SPEED_OVER_GROUND,
175
-// DetailCheckboxInfo.RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL, //new value
176
-// DetailCheckboxInfo.DISPLAY_LEGS, //new value which should override mode settings
177
-//
178
-// // Race Start Analysis
179
-//
180
-// // Leg Details
181
-// DetailCheckboxInfo.AVERAGE_SPEED_OVER_GROUND, DetailCheckboxInfo.DISTANCE, DetailCheckboxInfo.RANK_GAIN,
182
-//
183
-// // Maneuvers
184
-// DetailCheckboxInfo.TACK, DetailCheckboxInfo.JIBE,
185
-// DetailCheckboxInfo.PENALTY_CIRCLE
186
-//
187
-// };
188
-// leaderboardSettingsPanelPO.selectDetailsAndDeselectOther(detailsToSelect);
189
-// leaderboardSettingsPanelPO.setRefreshInterval(1);
190
-// leaderboardSettingsDialog.pressOk();
132
+ detailsToSelect = new DetailCheckboxInfo[] {
133
+ // Race details
134
+ DetailCheckboxInfo.RACE_DISTANCE, DetailCheckboxInfo.RACE_TIME,
135
+ DetailCheckboxInfo.RACE_AVERAGE_ABSOLUTE_CROSS_TRACK_ERROR,
136
+ DetailCheckboxInfo.RACE_AVERAGE_SIGNED_CROSS_TRACK_ERROR,
137
+ // Leg Details
138
+ DetailCheckboxInfo.AVERAGE_SPEED_OVER_GROUND, DetailCheckboxInfo.DISTANCE, DetailCheckboxInfo.RANK_GAIN,
139
+ // Maneuvers
140
+ DetailCheckboxInfo.TACK, DetailCheckboxInfo.JIBE, DetailCheckboxInfo.PENALTY_CIRCLE
141
+
142
+ };
143
+
144
+ leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog();
145
+ leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO();
146
+ selectedDetails = leaderboardSettingsPanelPO.getSelectedDetails();
147
+ Assert.assertArrayEquals(detailsToSelect, selectedDetails);
148
+
149
+ detailsToSelect = new DetailCheckboxInfo[] {
150
+ // Race details
151
+ DetailCheckboxInfo.RACE_GAP_TO_LEADER, DetailCheckboxInfo.RACE_DISTANCE, DetailCheckboxInfo.RACE_TIME,
152
+ DetailCheckboxInfo.RACE_CURRENT_SPEED_OVER_GROUND,
153
+ DetailCheckboxInfo.RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL,
154
+ DetailCheckboxInfo.DISPLAY_LEGS,
155
+ // Leg Details
156
+ DetailCheckboxInfo.AVERAGE_SPEED_OVER_GROUND, DetailCheckboxInfo.DISTANCE, DetailCheckboxInfo.RANK_GAIN,
157
+ // Maneuvers
158
+ DetailCheckboxInfo.TACK, DetailCheckboxInfo.JIBE, DetailCheckboxInfo.PENALTY_CIRCLE
159
+
160
+ };
161
+ leaderboardSettingsPanelPO.selectDetailsAndDeselectOther(detailsToSelect);
162
+ leaderboardSettingsPanelPO.setRefreshInterval(1);
163
+ leaderboardSettingsDialog.pressOk(false, false);
191 164
192 165
mapSettings = raceboard.openMapSettings();
193 166
// verify default mode settings override custom user settings
... ...
@@ -198,21 +171,22 @@ public class SettingsTest extends AbstractSeleniumTest {
198 171
Assert.assertFalse(mapSettings.isTransparentHoverlines());
199 172
mapSettings.setWindUp(false);
200 173
mapSettings.setTransparentHoverlines(false);
201
- mapSettings.pressOk();
174
+
175
+ mapSettings.pressOk(false, false);
202 176
203 177
raceboard = RaceBoardPage.goToRaceboardUrl(getWebDriver(), getContextRoot(), BMW_CUP_REGATTA, BMW_CUP_REGATTA,
204 178
String.format(BMW_RACE, 1), "WINNING_LANES");
205 179
206
-// leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog();
207
-// leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO();
208
-// selectedDetails = leaderboardSettingsPanelPO.getSelectedDetails();
209
-//
210
-// //verify highest precedence of document settings
211
-// Assert.assertArrayEquals(detailsToSelect, selectedDetails);
212
-// //verify that document settings are able to override custom user settings by a system default value
213
-// Assert.assertEquals(1, leaderboardSettingsPanelPO.getRefreshInterval());
214
-//
215
-// leaderboardSettingsDialog.pressCancel();
180
+ leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog();
181
+ leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO();
182
+ selectedDetails = leaderboardSettingsPanelPO.getSelectedDetails();
183
+
184
+ // verify highest precedence of document settings
185
+ Assert.assertArrayEquals(detailsToSelect, selectedDetails);
186
+ // verify that document settings are able to override custom user settings by a system default value
187
+ Assert.assertEquals(1, leaderboardSettingsPanelPO.getRefreshInterval());
188
+
189
+ leaderboardSettingsDialog.pressCancel();
216 190
217 191
mapSettings = raceboard.openMapSettings();
218 192
// Verify that mode settings are overridden by document settings
... ...
@@ -222,35 +196,29 @@ public class SettingsTest extends AbstractSeleniumTest {
222 196
223 197
//FIXME uncomment when START_ANALYSIS mode can be handled by remote CI server
224 198
// verify that custom document settings override mode settings of other modes
225
-// raceboard = RaceBoardPage.goToRaceboardUrl(getWebDriver(), getContextRoot(), BMW_CUP_REGATTA,
226
-// BMW_CUP_REGATTA,
227
-// String.format(BMW_RACE, 1), "START_ANALYSIS");
228
-// leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog();
229
-// leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO();
230
-// selectedDetails = leaderboardSettingsPanelPO.getSelectedDetails();
231
-//
232
-// detailsToSelect = new DetailCheckboxInfo[] {
233
-// DetailCheckboxInfo.RACE_GAP_TO_LEADER, //start analysis mode
234
-// DetailCheckboxInfo.RACE_CURRENT_SPEED_OVER_GROUND, //user settings
235
-// DetailCheckboxInfo.DISPLAY_LEGS, //document settings which override mode settings
236
-// DetailCheckboxInfo.RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL, //document settings
237
-// DetailCheckboxInfo.RACE_DISTANCE_TO_START_FIVE_SECONDS_BEFORE_START, //start analysis mode
238
-// DetailCheckboxInfo.RACE_SPEED_OVER_GROUND_FIVE_SECONDS_BEFORE_START, //start analysis mode
239
-// DetailCheckboxInfo.DISTANCE_TO_START_AT_RACE_START, //start analysis mode
240
-// DetailCheckboxInfo.SPEED_OVER_GROUND_AT_RACE_START, //start analysis mode
241
-// DetailCheckboxInfo.SPEED_OVER_GROUND_WHEN_STARTING, //start analysis mode
242
-// DetailCheckboxInfo.DISTANCE_TO_STARBOARD_END_OF_STARTLINE_WHEN_STARTING, //start analysis mode
243
-// DetailCheckboxInfo.START_TACK, //start analysis mode
244
-//
245
-// DetailCheckboxInfo.AVERAGE_SPEED_OVER_GROUND, DetailCheckboxInfo.DISTANCE, DetailCheckboxInfo.RANK_GAIN,
246
-//
247
-// DetailCheckboxInfo.TACK, DetailCheckboxInfo.JIBE, DetailCheckboxInfo.PENALTY_CIRCLE
248
-// };
249
-// Assert.assertArrayEquals(detailsToSelect, selectedDetails);
250
-// leaderboardSettingsDialog.pressCancel();
251
-//
252
-// mapSettings = raceboard.openMapSettings();
253
-// Assert.assertFalse(mapSettings.isWindUp());
199
+ raceboard = RaceBoardPage.goToRaceboardUrl(getWebDriver(), getContextRoot(), BMW_CUP_REGATTA, BMW_CUP_REGATTA,
200
+ String.format(BMW_RACE, 1), "START_ANALYSIS");
201
+ leaderboardSettingsDialog = raceboard.openLeaderboardSettingsDialog();
202
+ leaderboardSettingsPanelPO = leaderboardSettingsDialog.getLeaderboardSettingsPanelPO();
203
+ selectedDetails = leaderboardSettingsPanelPO.getSelectedDetails();
204
+
205
+ detailsToSelect = new DetailCheckboxInfo[] { DetailCheckboxInfo.RACE_GAP_TO_LEADER, // start analysis mode
206
+ DetailCheckboxInfo.RACE_DISTANCE_TO_START_FIVE_SECONDS_BEFORE_START, // start analysis mode
207
+ DetailCheckboxInfo.RACE_SPEED_OVER_GROUND_FIVE_SECONDS_BEFORE_START, // start analysis mode
208
+ DetailCheckboxInfo.DISTANCE_TO_START_AT_RACE_START, // start analysis mode
209
+ DetailCheckboxInfo.SPEED_OVER_GROUND_AT_RACE_START, // start analysis mode
210
+ DetailCheckboxInfo.SPEED_OVER_GROUND_WHEN_STARTING, // start analysis mode
211
+ DetailCheckboxInfo.DISTANCE_TO_STARBOARD_END_OF_STARTLINE_WHEN_STARTING, // start analysis mode
212
+ DetailCheckboxInfo.START_TACK, // start analysis mode
213
+
214
+ DetailCheckboxInfo.AVERAGE_SPEED_OVER_GROUND, DetailCheckboxInfo.DISTANCE, DetailCheckboxInfo.RANK_GAIN,
215
+
216
+ DetailCheckboxInfo.TACK, DetailCheckboxInfo.JIBE, DetailCheckboxInfo.PENALTY_CIRCLE };
217
+ Assert.assertArrayEquals(detailsToSelect, selectedDetails);
218
+ leaderboardSettingsDialog.pressCancel();
219
+
220
+ mapSettings = raceboard.openMapSettings();
221
+ Assert.assertTrue(mapSettings.isWindUp());
254 222
}
255 223
256 224
/**
... ...
@@ -687,7 +655,7 @@ public class SettingsTest extends AbstractSeleniumTest {
687 655
688 656
// open settings dialog of configurated leaderboard with default values
689 657
LeaderboardSettingsDialogPO leaderboardSettingsDialog = leaderboardPage.getLeaderboardSettings();
690
- LeaderboardSettingsPanelPO leaderboardSettingsPanel = leaderboardPage.getLeaderboardSettings()
658
+ LeaderboardSettingsPanelPO leaderboardSettingsPanel = leaderboardSettingsDialog
691 659
.getLeaderboardSettingsPanelPO();
692 660
693 661
// store default values for checks later
java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EstimationDataSerializationDeserializationTest.java
... ...
@@ -130,14 +130,14 @@ public class EstimationDataSerializationDeserializationTest {
130 130
Bearing relativeBearingToNextMarkAfterManeuver = new DegreeBearingImpl(10.01);
131 131
boolean markPassing = true;
132 132
Distance closestDistanceToMark = new MeterDistance(3.0);
133
- Double deviationFromTargetTackAngle = 23.30;
134
- Double deviationFromTargetJibeAngle = 22.30;
133
+ Double targetTackAngle = 23.30;
134
+ Double targetJibeAngle = 22.30;
135 135
136 136
CompleteManeuverCurveWithEstimationData toSerialize = new CompleteManeuverCurveWithEstimationDataImpl(
137 137
maneuverPosition, mainCurve, curve, wind, tackingCount, jibingCount,
138 138
maneuverStartsByRunningAwayFromWind, relativeBearingToNextMarkBeforeManeuver,
139
- relativeBearingToNextMarkAfterManeuver, markPassing, closestDistanceToMark,
140
- deviationFromTargetTackAngle, deviationFromTargetJibeAngle);
139
+ relativeBearingToNextMarkAfterManeuver, markPassing, closestDistanceToMark, targetTackAngle,
140
+ targetJibeAngle);
141 141
CompleteManeuverCurveWithEstimationDataJsonSerializer serializer = new CompleteManeuverCurveWithEstimationDataJsonSerializer(
142 142
new ManeuverMainCurveWithEstimationDataJsonSerializer(),
143 143
new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer(),
... ...
@@ -149,10 +149,8 @@ public class EstimationDataSerializationDeserializationTest {
149 149
new ManeuverWindJsonDeserializer(), new PositionJsonDeserializer());
150 150
CompleteManeuverCurveWithEstimationData deserialized = deserializer.deserialize(json);
151 151
152
- assertEquals(deviationFromTargetJibeAngle,
153
- deserialized.getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees());
154
- assertEquals(deviationFromTargetTackAngle,
155
- deserialized.getDeviationOfManeuverAngleFromTargetTackAngleInDegrees());
152
+ assertEquals(targetJibeAngle, deserialized.getTargetJibeAngleInDegrees());
153
+ assertEquals(targetTackAngle, deserialized.getTargetTackAngleInDegrees());
156 154
assertEquals(closestDistanceToMark, deserialized.getDistanceToClosestMark());
157 155
assertEquals(maneuverPosition, deserialized.getPosition());
158 156
assertEquals(tackingCount, deserialized.getTackingCount());
... ...
@@ -310,14 +308,14 @@ public class EstimationDataSerializationDeserializationTest {
310 308
boolean markPassing = false;
311 309
DegreePosition maneuverPosition = new DegreePosition(50.325246, 11.148556);
312 310
Distance closestDistanceToMark = null;
313
- Double deviationFromTargetTackAngle = null;
314
- Double deviationFromTargetJibeAngle = null;
311
+ Double targetTackAngle = null;
312
+ Double targetJibeAngle = null;
315 313
316 314
CompleteManeuverCurveWithEstimationData toSerialize = new CompleteManeuverCurveWithEstimationDataImpl(
317 315
maneuverPosition, mainCurve, curve, wind, tackingCount, jibingCount,
318 316
maneuverStartsByRunningAwayFromWind, relativeBearingToNextMarkBeforeManeuver,
319
- relativeBearingToNextMarkAfterManeuver, markPassing, closestDistanceToMark,
320
- deviationFromTargetTackAngle, deviationFromTargetJibeAngle);
317
+ relativeBearingToNextMarkAfterManeuver, markPassing, closestDistanceToMark, targetTackAngle,
318
+ targetJibeAngle);
321 319
CompleteManeuverCurveWithEstimationDataJsonSerializer serializer = new CompleteManeuverCurveWithEstimationDataJsonSerializer(
322 320
new ManeuverMainCurveWithEstimationDataJsonSerializer(),
323 321
new ManeuverCurveWithUnstableCourseAndSpeedWithEstimationDataJsonSerializer(),
... ...
@@ -329,10 +327,8 @@ public class EstimationDataSerializationDeserializationTest {
329 327
new ManeuverWindJsonDeserializer(), new PositionJsonDeserializer());
330 328
CompleteManeuverCurveWithEstimationData deserialized = deserializer.deserialize(json);
331 329
332
- assertEquals(deviationFromTargetJibeAngle,
333
- deserialized.getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees());
334
- assertEquals(deviationFromTargetTackAngle,
335
- deserialized.getDeviationOfManeuverAngleFromTargetTackAngleInDegrees());
330
+ assertEquals(targetJibeAngle, deserialized.getTargetJibeAngleInDegrees());
331
+ assertEquals(targetTackAngle, deserialized.getTargetTackAngleInDegrees());
336 332
assertEquals(closestDistanceToMark, deserialized.getDistanceToClosestMark());
337 333
assertEquals(maneuverPosition, deserialized.getPosition());
338 334
assertEquals(tackingCount, deserialized.getTackingCount());
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CompleteManeuverCurveWithEstimationDataJsonDeserializer.java
... ...
@@ -67,16 +67,15 @@ public class CompleteManeuverCurveWithEstimationDataJsonDeserializer
67 67
CompleteManeuverCurveWithEstimationDataJsonSerializer.RELATIVE_BEARING_TO_NEXT_MARK_AFTER_MANEUVER);
68 68
Double closestDistanceToMarkInMeters = (Double) object
69 69
.get(CompleteManeuverCurveWithEstimationDataJsonSerializer.CLOSEST_DISTANCE_TO_MARK);
70
- Double deviationFromTargetTackAngle = (Double) object
71
- .get(CompleteManeuverCurveWithEstimationDataJsonSerializer.DEVIATION_FROM_TARGET_TACK_ANGLE);
72
- Double deviationFromTargetJibeAngle = (Double) object
73
- .get(CompleteManeuverCurveWithEstimationDataJsonSerializer.DEVIATION_FROM_TARGET_JIBE_ANGLE);
70
+ Double targetTackAngle = (Double) object
71
+ .get(CompleteManeuverCurveWithEstimationDataJsonSerializer.TARGET_TACK_ANGLE);
72
+ Double targetJibeAngle = (Double) object
73
+ .get(CompleteManeuverCurveWithEstimationDataJsonSerializer.TARGET_JIBE_ANGLE);
74 74
return new CompleteManeuverCurveWithEstimationDataImpl(position, mainCurve, curveWithUnstableCourseAndSpeed,
75 75
wind, tackingCount, jibingCount, maneuverStartsByRunningAwayFromWind,
76 76
convertBearing(relativeBearingToNextMarkBeforeManeuver),
77 77
convertBearing(relativeBearingToNextMarkAfterManeuver), markPassing,
78
- convertDistance(closestDistanceToMarkInMeters), deviationFromTargetTackAngle,
79
- deviationFromTargetJibeAngle);
78
+ convertDistance(closestDistanceToMarkInMeters), targetTackAngle, targetJibeAngle);
80 79
}
81 80
82 81
private Bearing convertBearing(Double degrees) {
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorTrackWithEstimationDataJsonSerializer.java
... ...
@@ -26,7 +26,7 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl;
26 26
*
27 27
*/
28 28
public class CompetitorTrackWithEstimationDataJsonSerializer extends AbstractTrackedRaceDataJsonSerializer {
29
- public static final String elements = "elements";
29
+ public static final String ELEMENTS = "elements";
30 30
public static final String BOAT_CLASS = "boatClass";
31 31
public static final String COMPETITOR_NAME = "competitorName";
32 32
public static final String AVG_INTERVAL_BETWEEN_FIXES_IN_SECONDS = "avgIntervalBetweenFixesInSeconds";
... ...
@@ -67,27 +67,27 @@ public class CompetitorTrackWithEstimationDataJsonSerializer extends AbstractTra
67 67
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
68 68
ManeuverDetectorImpl maneuverDetector = new ManeuverDetectorImpl(trackedRace, competitor);
69 69
TrackTimeInfo trackTimeInfo = maneuverDetector.getTrackTimeInfo();
70
- TimePoint from = null;
71
- TimePoint to = null;
72
- if (startBeforeStartLineInSeconds != null) {
73
- from = trackTimeInfo.getTrackStartTimePoint()
74
- .minus(new MillisecondsDurationImpl(startBeforeStartLineInSeconds * 1000L));
75
- } else if (startAfterFinishLineInSeconds != null) {
76
- from = trackTimeInfo.getTrackEndTimePoint()
77
- .plus(new MillisecondsDurationImpl(startAfterFinishLineInSeconds * 1000L));
78
- } else {
79
- from = trackTimeInfo.getTrackStartTimePoint();
80
- }
81
- if (endAfterFinishLineInSeconds != null) {
82
- to = trackTimeInfo.getTrackEndTimePoint()
83
- .plus(new MillisecondsDurationImpl(endAfterFinishLineInSeconds * 1000L));
84
- } else if (endBeforeStartLineInSeconds != null) {
85
- to = trackTimeInfo.getTrackStartTimePoint()
86
- .minus(new MillisecondsDurationImpl(endBeforeStartLineInSeconds * 1000L));
87
- } else {
88
- to = trackTimeInfo.getTrackEndTimePoint();
89
- }
90 70
if (trackTimeInfo != null) {
71
+ TimePoint from = null;
72
+ TimePoint to = null;
73
+ if (startBeforeStartLineInSeconds != null) {
74
+ from = trackTimeInfo.getTrackStartTimePoint()
75
+ .minus(new MillisecondsDurationImpl(startBeforeStartLineInSeconds * 1000L));
76
+ } else if (startAfterFinishLineInSeconds != null) {
77
+ from = trackTimeInfo.getTrackEndTimePoint()
78
+ .plus(new MillisecondsDurationImpl(startAfterFinishLineInSeconds * 1000L));
79
+ } else {
80
+ from = trackTimeInfo.getTrackStartTimePoint();
81
+ }
82
+ if (endAfterFinishLineInSeconds != null) {
83
+ to = trackTimeInfo.getTrackEndTimePoint()
84
+ .plus(new MillisecondsDurationImpl(endAfterFinishLineInSeconds * 1000L));
85
+ } else if (endBeforeStartLineInSeconds != null) {
86
+ to = trackTimeInfo.getTrackStartTimePoint()
87
+ .minus(new MillisecondsDurationImpl(endBeforeStartLineInSeconds * 1000L));
88
+ } else {
89
+ to = trackTimeInfo.getTrackEndTimePoint();
90
+ }
91 91
final JSONObject forCompetitorJson = new JSONObject();
92 92
byCompetitorJson.add(forCompetitorJson);
93 93
forCompetitorJson.put(COMPETITOR_NAME, competitor.getName());
... ...
@@ -111,7 +111,7 @@ public class CompetitorTrackWithEstimationDataJsonSerializer extends AbstractTra
111 111
: trackTimeInfo.getTrackEndTimePoint().asMillis());
112 112
forCompetitorJson.put(MARK_PASSINGS_COUNT, getMarkPassingsCount(trackedRace, competitor));
113 113
forCompetitorJson.put(WAYPOINTS_COUNT, getWaypointsCount(trackedRace));
114
- forCompetitorJson.put(elements,
114
+ forCompetitorJson.put(ELEMENTS,
115 115
elementsJsonSerializer.serialize(trackedRace, competitor, from, to, trackTimeInfo));
116 116
}
117 117
}
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompleteManeuverCurveWithEstimationDataJsonSerializer.java
... ...
@@ -24,8 +24,8 @@ public class CompleteManeuverCurveWithEstimationDataJsonSerializer
24 24
public static final String RELATIVE_BEARING_TO_NEXT_MARK_BEFORE_MANEUVER = "relativeBearingToNextMarkBeforeManeuver";
25 25
public static final String RELATIVE_BEARING_TO_NEXT_MARK_AFTER_MANEUVER = "relativeBearingToNextMarkAfterManeuver";
26 26
public static final String CLOSEST_DISTANCE_TO_MARK = "closestDistanceToMarkInMeters";
27
- public static final String DEVIATION_FROM_TARGET_TACK_ANGLE = "deviationFromTargetTackAngleInDegrees";
28
- public static final String DEVIATION_FROM_TARGET_JIBE_ANGLE = "deviationFromTargetJibeAngleInDegrees";
27
+ public static final String TARGET_TACK_ANGLE = "targetTackAngleInDegrees";
28
+ public static final String TARGET_JIBE_ANGLE = "targetJibeAngleInDegrees";
29 29
30 30
private final ManeuverCurveBoundariesJsonSerializer mainCurveSerializer;
31 31
private final ManeuverCurveBoundariesJsonSerializer curveWithUnstableCourseAndSpeedSerializer;
... ...
@@ -64,10 +64,8 @@ public class CompleteManeuverCurveWithEstimationDataJsonSerializer
64 64
: maneuverWithEstimationData.getRelativeBearingToNextMarkAfterManeuver().getDegrees());
65 65
result.put(CLOSEST_DISTANCE_TO_MARK, maneuverWithEstimationData.getDistanceToClosestMark() == null ? null
66 66
: maneuverWithEstimationData.getDistanceToClosestMark().getMeters());
67
- result.put(DEVIATION_FROM_TARGET_TACK_ANGLE,
68
- maneuverWithEstimationData.getDeviationOfManeuverAngleFromTargetTackAngleInDegrees());
69
- result.put(DEVIATION_FROM_TARGET_JIBE_ANGLE,
70
- maneuverWithEstimationData.getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees());
67
+ result.put(TARGET_TACK_ANGLE, maneuverWithEstimationData.getTargetTackAngleInDegrees());
68
+ result.put(TARGET_JIBE_ANGLE, maneuverWithEstimationData.getTargetJibeAngleInDegrees());
71 69
return result;
72 70
}
73 71
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/GPSFixMovingJsonSerializer.java
... ...
@@ -2,19 +2,25 @@ 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.common.SpeedWithBearing;
5 6
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
6 7
import com.sap.sailing.server.gateway.deserialization.TypeBasedJsonDeserializer;
7 8
import com.sap.sailing.server.gateway.deserialization.impl.GPSFixMovingJsonDeserializer;
8 9
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
9 10
10 11
public class GPSFixMovingJsonSerializer implements JsonSerializer<GPSFixMoving> {
12
+
11 13
@Override
12 14
public JSONObject serialize(GPSFixMoving object) {
15
+ return serialize(object, object.getSpeed());
16
+ }
17
+
18
+ public JSONObject serialize(GPSFixMoving object, SpeedWithBearing speedWithCourse) {
13 19
JSONObject result = new GPSFixJsonSerializer().serialize(object);
14 20
15 21
result.put(TypeBasedJsonDeserializer.FIELD_TYPE, GPSFixMovingJsonDeserializer.TYPE);
16
- result.put(GPSFixMovingJsonDeserializer.FIELD_BEARING_DEG, object.getSpeed().getBearing().getDegrees());
17
- result.put(GPSFixMovingJsonDeserializer.FIELD_SPEED_KNOTS, object.getSpeed().getKnots());
22
+ result.put(GPSFixMovingJsonDeserializer.FIELD_BEARING_DEG, speedWithCourse.getBearing().getDegrees());
23
+ result.put(GPSFixMovingJsonDeserializer.FIELD_SPEED_KNOTS, speedWithCourse.getKnots());
18 24
19 25
return result;
20 26
}
java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/GpsFixesWithEstimationDataJsonSerializer.java
... ...
@@ -60,7 +60,9 @@ public class GpsFixesWithEstimationDataJsonSerializer implements CompetitorTrack
60 60
track.lockForRead();
61 61
try {
62 62
for (GPSFixMoving gpsFix : track.getFixes(from, true, to, true)) {
63
- JSONObject serializedGpsFix = gpsFixMovingJsonSerializer.serialize(gpsFix);
63
+ SpeedWithBearing speedWithBearing = smoothFixes ? track.getEstimatedSpeed(gpsFix.getTimePoint())
64
+ : gpsFix.getSpeed();
65
+ JSONObject serializedGpsFix = gpsFixMovingJsonSerializer.serialize(gpsFix, speedWithBearing);
64 66
if (addWind) {
65 67
Wind wind = trackedRace.getWind(gpsFix.getPosition(), gpsFix.getTimePoint());
66 68
JSONObject serializedWind = wind == null ? null : windJsonSerializer.serialize(wind);
... ...
@@ -69,8 +71,6 @@ public class GpsFixesWithEstimationDataJsonSerializer implements CompetitorTrack
69 71
if (addNextWaypoint) {
70 72
Distance closestDistanceToMark = estimationDataSupportDecoratorImpl
71 73
.getClosestDistanceToMark(gpsFix.getTimePoint());
72
- SpeedWithBearing speedWithBearing = smoothFixes ? track.getEstimatedSpeed(gpsFix.getTimePoint())
73
- : gpsFix.getSpeed();
74 74
Bearing relativeBearingToNextMark = speedWithBearing == null ? null
75 75
: estimationDataSupportDecoratorImpl.getRelativeBearingToNextMark(gpsFix.getTimePoint(),
76 76
speedWithBearing.getBearing());
java/com.sap.sailing.simulator.test/.project
... ...
@@ -22,12 +22,12 @@
22 22
</arguments>
23 23
</buildCommand>
24 24
<buildCommand>
25
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
25
+ <name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
26 26
<arguments>
27 27
</arguments>
28 28
</buildCommand>
29 29
<buildCommand>
30
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
30
+ <name>com.gwtplugins.gwt.eclipse.core.gwtProjectValidator</name>
31 31
<arguments>
32 32
</arguments>
33 33
</buildCommand>
... ...
@@ -35,6 +35,6 @@
35 35
<natures>
36 36
<nature>org.eclipse.pde.PluginNature</nature>
37 37
<nature>org.eclipse.jdt.core.javanature</nature>
38
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
38
+ <nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
39 39
</natures>
40 40
</projectDescription>
java/com.sap.sailing.simulator/.project
... ...
@@ -21,12 +21,12 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
24
+ <name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
25 25
<arguments>
26 26
</arguments>
27 27
</buildCommand>
28 28
<buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
29
+ <name>com.gwtplugins.gwt.eclipse.core.gwtProjectValidator</name>
30 30
<arguments>
31 31
</arguments>
32 32
</buildCommand>
... ...
@@ -34,6 +34,6 @@
34 34
<natures>
35 35
<nature>org.eclipse.pde.PluginNature</nature>
36 36
<nature>org.eclipse.jdt.core.javanature</nature>
37
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
37
+ <nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
38 38
</natures>
39 39
</projectDescription>
java/com.sap.sailing.www/release_notes_admin.html
... ...
@@ -24,6 +24,11 @@
24 24
25 25
<h2 class="articleSubheadline">July 2018</h2>
26 26
<ul class="bulletList">
27
+ <li>The mark passing editor now uses a full date/time format for the mark passing time points.</li>
28
+ </ul>
29
+
30
+ <h2 class="articleSubheadline">July 2018</h2>
31
+ <ul class="bulletList">
27 32
<li>When adding a YouTube video for tracked races ("Manage Media" in <tt>RaceBoard.html</tt> or "Tracked Races > Audio & Video" in <tt>AdminConsole.html</tt>) the respective video metadata is now read using YouTube API v3.
28 33
This functionality used to work some years ago using API v2 but was broken since this API version was discontinued some time ago.
29 34
Due to limitations of the new API we can't read the start timepoint of videos by now. You still need to provide this value manually.</li>
... ...
@@ -45,6 +50,10 @@
45 50
For any non-medal series, the standard low point rules apply.</li>
46 51
</ul>
47 52
</li>
53
+ <li>A TracAPI upgrade from version 3.10.1 to 3.11.0 unifies the handling of course updates and solves an issue
54
+ observed with updating mark passing instructions.</li>
55
+ <li>Bug fix for mark position editor, now providing consistent behavior during adding of new mark fixes</li>
56
+ <li>Data Mining now more aggressively terminates running queries if needed.</li>
48 57
</ul>
49 58
50 59
<h2 class="articleSubheadline">June 2018</h2>
java/com.sap.sse.common/.project
... ...
@@ -21,12 +21,12 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
24
+ <name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
25 25
<arguments>
26 26
</arguments>
27 27
</buildCommand>
28 28
<buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
29
+ <name>com.gwtplugins.gwt.eclipse.core.gwtProjectValidator</name>
30 30
<arguments>
31 31
</arguments>
32 32
</buildCommand>
... ...
@@ -34,6 +34,6 @@
34 34
<natures>
35 35
<nature>org.eclipse.pde.PluginNature</nature>
36 36
<nature>org.eclipse.jdt.core.javanature</nature>
37
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
37
+ <nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
38 38
</natures>
39 39
</projectDescription>
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/TestAbortingHeavyLoadQuery.java
... ...
@@ -0,0 +1,524 @@
1
+package com.sap.sse.datamining.impl;
2
+
3
+import static org.hamcrest.Matchers.is;
4
+import static org.junit.Assert.assertFalse;
5
+import static org.junit.Assert.assertThat;
6
+import static org.junit.Assert.assertTrue;
7
+
8
+import java.lang.reflect.Method;
9
+import java.text.SimpleDateFormat;
10
+import java.util.ArrayList;
11
+import java.util.Collection;
12
+import java.util.Collections;
13
+import java.util.Date;
14
+import java.util.HashSet;
15
+import java.util.Map;
16
+import java.util.Set;
17
+import java.util.concurrent.ConcurrentHashMap;
18
+import java.util.concurrent.ConcurrentLinkedQueue;
19
+import java.util.concurrent.ExecutionException;
20
+import java.util.concurrent.ExecutorService;
21
+import java.util.concurrent.FutureTask;
22
+import java.util.concurrent.RunnableFuture;
23
+import java.util.concurrent.TimeUnit;
24
+import java.util.function.Consumer;
25
+
26
+import org.junit.After;
27
+import org.junit.Before;
28
+import org.junit.Test;
29
+
30
+import com.sap.sse.datamining.Query;
31
+import com.sap.sse.datamining.QueryState;
32
+import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
33
+import com.sap.sse.datamining.components.Processor;
34
+import com.sap.sse.datamining.components.ProcessorInstruction;
35
+import com.sap.sse.datamining.components.ProcessorInstructionHandler;
36
+import com.sap.sse.datamining.data.QueryResult;
37
+import com.sap.sse.datamining.impl.components.AbstractParallelProcessor;
38
+import com.sap.sse.datamining.impl.components.AbstractProcessorInstruction;
39
+import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
40
+import com.sap.sse.datamining.impl.components.GroupedDataEntry;
41
+import com.sap.sse.datamining.impl.components.ProcessorInstructionPriority;
42
+import com.sap.sse.datamining.impl.components.aggregators.ParallelGroupedDataCollectingAsSetProcessor;
43
+import com.sap.sse.datamining.shared.GroupKey;
44
+import com.sap.sse.datamining.shared.data.QueryResultState;
45
+import com.sap.sse.datamining.shared.impl.GenericGroupKey;
46
+import com.sap.sse.datamining.test.util.components.StatefulBlockingInstruction;
47
+import com.sap.sse.datamining.test.util.components.StatefulProcessorInstruction;
48
+
49
+/**
50
+ * Integration test aborting a query with simulated heavy load instructions. Uses a highly customized processor chain
51
+ * (based on the processors/instructions used in production) that allows detailed introspection and logging of the
52
+ * execution process. The test is used to verify the behavior of processors, if such a heavy load query is aborted
53
+ * during the process. For example that no instructions are scheduled after the query was aborted and the behavior of
54
+ * already scheduled instructions that may or may not have been started.<br>
55
+ * <br>
56
+ * The test is configurable regarding the number of threads for the executor, the number of data elements/heavy load
57
+ * instructions, the duration of heavy load instructions, the time to wait before the query is aborted and the time
58
+ * given to the executor to finish the remaining instructions. Note that the test can fail for some configurations, due
59
+ * to race conditions that would be very hard to check for.<br>
60
+ * <br>
61
+ * The test optionally records the process in order of the execution (using a concurrent message queue), which is
62
+ * printed to the console before assertions are performed. This isn't used by the assertions, but can be used to get a
63
+ * better understanding of what happens during the execution.<br>
64
+ * <br>
65
+ * See {@link #initialize()} for more details about the processor chain.
66
+ *
67
+ * @author Lennart Hensler
68
+ */
69
+public class TestAbortingHeavyLoadQuery {
70
+
71
+ // Test Configuration ----------------------------------------------------------------------------------------
72
+ /**
73
+ * Number of threads in the executor. Determines the number of elements (and thus heavy load instructions)
74
+ * retrieved for each group. This means that each group should have a runtime of {@value #HeavyLoadInstructionTotalDuration}ms,
75
+ * since the single instructions are executed concurrently.
76
+ */
77
+ private static final int ExecutorPoolSize = Math.max(3, Runtime.getRuntime().availableProcessors());
78
+
79
+ /** The number of groups contained in the initial data source. */
80
+ private static final int DataSourceSize = 2000;
81
+ private static final String GroupKeyPrefix = "G";
82
+
83
+ /** The time a step of a heavy load instruction blocks the executing thread (using {@link Thread#sleep(long)}). */
84
+ private static final long HeavyLoadInstructionStepDuration = 50;
85
+ /** The number of steps a heavy load instruction performs */
86
+ private static final int HeavyLoadInstructionNumberOfSteps = 10;
87
+ /** The total time a heavy load instruction blocks the executing thread (using {@link Thread#sleep(long)}). */
88
+ private static final long HeavyLoadInstructionTotalDuration = HeavyLoadInstructionStepDuration * HeavyLoadInstructionNumberOfSteps;
89
+
90
+ /** The number of milliseconds to wait before {@link Query#abort()} is called. */
91
+ private static final long AbortQueryDelay = (long) (HeavyLoadInstructionTotalDuration * 5.45);
92
+ /** The time given to the executor to complete all unfinished instructions */
93
+ private static final long TerminationTimeout = HeavyLoadInstructionStepDuration * 2;
94
+ //------------------------------------------------------------------------------------------------------------
95
+
96
+ // Execution Recording Configuration -------------------------------------------------------------------------
97
+ /** Enables concurrent logging of the query execution and prints the current record before assertions. */
98
+ private static final boolean RecordExecution = true;
99
+ private static final SimpleDateFormat DateFormatter = new SimpleDateFormat("HH:mm:ss.SSS");
100
+ private ConcurrentLinkedQueue<String> executionRecord;
101
+ //------------------------------------------------------------------------------------------------------------
102
+
103
+ // Test State - Initialized in initialize() ------------------------------------------------------------------
104
+ private ExecutorService executor;
105
+ private Query<HashSet<Integer>> query;
106
+ private Collection<Processor<?, ?>> processors;
107
+ private Set<StatefulProcessorInstruction<?>> unfinishedInstructions;
108
+ //------------------------------------------------------------------------------------------------------------
109
+
110
+ @Test
111
+ public void testAbortingHeavyLoadQuery() throws InterruptedException, ExecutionException {
112
+ // Executing query in separate thread
113
+ RunnableFuture<QueryResult<HashSet<Integer>>> queryTask = new FutureTask<>(() -> {
114
+ logExecution("Starting query execution");
115
+ long start = System.currentTimeMillis();
116
+ QueryResult<HashSet<Integer>> result = query.run();
117
+ long duration = System.currentTimeMillis() - start;
118
+ logExecution("Finished query in " + duration + "ms");
119
+ return result;
120
+ });
121
+ Thread worker = new Thread(queryTask, "Worker");
122
+ worker.start();
123
+ do {
124
+ Thread.sleep(10);
125
+ } while (query.getState() != QueryState.RUNNING);
126
+
127
+ // Aborting query and waiting for completion
128
+ Thread.sleep(AbortQueryDelay);
129
+ logExecution("Aborting query");
130
+ query.abort();
131
+ QueryResult<HashSet<Integer>> result = queryTask.get();
132
+
133
+ // The query execution returned, so all processors are aborted (checked below).
134
+ // The number of unfinished instructions mustn't change after this point
135
+ int unfinishedInstructionsCount = unfinishedInstructions.size();
136
+ boolean unfinishedInstructionWasFinished = false;
137
+ Set<StatefulProcessorInstruction<?>> runningInstructions = new HashSet<>();
138
+ Set<StatefulProcessorInstruction<?>> notStartedInstructions = new HashSet<>();
139
+ for (StatefulProcessorInstruction<?> instruction : unfinishedInstructions) {
140
+ if (instruction.runWasCalled()) {
141
+ runningInstructions.add(instruction);
142
+ } else {
143
+ notStartedInstructions.add(instruction);
144
+ }
145
+ unfinishedInstructionWasFinished |= instruction.computeResultWasFinished();
146
+ }
147
+ logExecution(unfinishedInstructionsCount + " unfinished instructions left - " +
148
+ runningInstructions.size() + " running, " + notStartedInstructions.size() + " not started");
149
+ printExecutionRecord();
150
+ assertThat("Number of unfinished instructions changed", runningInstructions.size() + notStartedInstructions.size(), is(unfinishedInstructionsCount));
151
+ assertFalse("Unfinished instructions expected, but at least one was completed", unfinishedInstructionWasFinished);
152
+
153
+ // Checking query, result and processor chain state
154
+ assertThat(query.getState(), is(QueryState.ABORTED));
155
+ assertThat(result.getState(), is(QueryResultState.ABORTED));
156
+ assertTrue("The result is not empty", result.isEmpty());
157
+ for (Processor<?, ?> processor : processors) {
158
+ assertTrue("Processor wasn't aborted", processor.isAborted());
159
+ }
160
+
161
+ // Execution of unfinished instructions
162
+ executor.shutdown();
163
+ boolean terminated = executor.awaitTermination(TerminationTimeout, TimeUnit.MILLISECONDS);
164
+ printExecutionRecord();
165
+ assertTrue("The executor didn't terminate in the given time", terminated);
166
+
167
+ // Verify that the collection of unfinished instructions didn't change
168
+ assertThat("Number of unfinished instructions changed", unfinishedInstructions.size(), is(unfinishedInstructionsCount));
169
+ for (StatefulProcessorInstruction<?> instruction : unfinishedInstructions) {
170
+ boolean previouslyContained = runningInstructions.contains(instruction) || notStartedInstructions.contains(instruction);
171
+ assertTrue("A new instruction has been scheduled after aborting the query", previouslyContained);
172
+ }
173
+ for (StatefulProcessorInstruction<?> instruction : runningInstructions) {
174
+ assertTrue("A previously running instruction was removed from unfinished instructions", unfinishedInstructions.contains(instruction));
175
+ }
176
+ for (StatefulProcessorInstruction<?> instruction : notStartedInstructions) {
177
+ assertTrue("A previously unstarted instruction was removed from unfinished instructions", unfinishedInstructions.contains(instruction));
178
+ }
179
+
180
+ // Checking state of unfinished instructions
181
+ for (StatefulProcessorInstruction<?> instruction : runningInstructions) {
182
+ assertTrue("computeResult() of a running unfinished instruction wasn't called", instruction.computeResultWasCalled());
183
+ assertTrue("computeResult() of a running unfinished instruction didn't finish", instruction.computeResultWasFinished());
184
+ if (instruction instanceof StatefulBlockingInstruction) {
185
+ StatefulBlockingInstruction<?> blockingInstruction = (StatefulBlockingInstruction<?>) instruction;
186
+ assertTrue("computeResult() of a running heavy load instruction wasn't aborted", blockingInstruction.computeResultWasAborted());
187
+ }
188
+ }
189
+ for (StatefulProcessorInstruction<?> instruction : notStartedInstructions) {
190
+ assertTrue("run() of an unstarted unfinished instruction wasn't called", instruction.runWasCalled());
191
+
192
+ assertFalse("computeResult() of an unstarted unfinished instruction was called", instruction.computeResultWasCalled());
193
+ assertFalse("computeResult() of an unstarted unfinished instruction was finished", instruction.computeResultWasFinished());
194
+ }
195
+ }
196
+
197
+ private void printExecutionRecord() {
198
+ if (RecordExecution) {
199
+ Collection<String> snapshot = new ArrayList<>(executionRecord);
200
+ executionRecord.clear();
201
+ for (String string : snapshot) {
202
+ System.out.println(string);
203
+ }
204
+ }
205
+ }
206
+
207
+ private void logExecution(String message) {
208
+ if (RecordExecution) {
209
+ String timeString = DateFormatter.format(new Date());
210
+ executionRecord.add(timeString + " - " + Thread.currentThread().getName() + ": " + message);
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Initializes the {@link ExecutorService}, the execution record, helper collections (e.g. the processors in the
216
+ * chain or the unfinished instructions) and most importantly the processor chain for the query, which works as
217
+ * follows:
218
+ * <ol>
219
+ * <li>
220
+ * The initial data source is a collection of strings from {@value #GroupKeyPrefix}<code>n</code> to
221
+ * {@value #GroupKeyPrefix}<code>n-1</code>, denoting a group. <code>n</code> is specified in {@link #DataSourceSize}.
222
+ * </li>
223
+ * <li>
224
+ * <code>x</code> (specified by {@link #ExecutorPoolSize}) {@link Element elements} are retrieved for each
225
+ * group, where the elements name is set to the received string and the elements value is the current value
226
+ * of <code>x</code>.
227
+ * </li>
228
+ * <li>
229
+ * A heavy load instruction for each element is scheduled, which blocks the running thread for
230
+ * {@value #HeavyLoadInstructionTotalDuration}ms.
231
+ * </li>
232
+ * <li>
233
+ * Each element is grouped by its name and its value is used as value for the {@link GroupedDataEntry}.
234
+ * </li>
235
+ * <li>The grouped data is collected as set.</li>
236
+ * </ol>
237
+ * This results in <code>n * x</code> data elements (and heavy load instructions), with <code>x</code> instructions
238
+ * executed concurrently.<br>
239
+ * <br>
240
+ * Each processor creates {@link StatefulProcessorInstruction} or uses {@link StatefulInstructionWrapper}, which allows
241
+ * to verify if <code>instruction.run()</code> was called, its computation started and its computation finished.<br>
242
+ * <br>
243
+ * A concurrent set ({@link ConcurrentHashMap#newKeySet()}) is used to track the unfinished instructions. An instruction
244
+ * is added to the set upon its construction and is removed when the instruction finished callback method is called.
245
+ */
246
+ @Before
247
+ @SuppressWarnings("unchecked")
248
+ public void initialize() {
249
+ if (RecordExecution) {
250
+ executionRecord = new ConcurrentLinkedQueue<>();
251
+ }
252
+
253
+ executor = new DataMiningExecutorService(ExecutorPoolSize);
254
+// executor = new ThreadPoolExecutor(ExecutorPoolSize, ExecutorPoolSize, 0, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<>());
255
+// executor = new ThreadPoolExecutor(ExecutorPoolSize, ExecutorPoolSize, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
256
+ processors = new ArrayList<>();
257
+ unfinishedInstructions = ConcurrentHashMap.newKeySet();
258
+
259
+ Class<Iterable<String>> dataSourceType = (Class<Iterable<String>>)(Class<?>) Iterable.class;
260
+ Class<GroupedDataEntry<Integer>> groupedType = (Class<GroupedDataEntry<Integer>>)(Class<?>) GroupedDataEntry.class;
261
+ Class<HashSet<Integer>> resultType = (Class<HashSet<Integer>>)(Class<?>) HashSet.class;
262
+
263
+ Collection<String> dataSource = new ArrayList<>(DataSourceSize);
264
+ for (int i = 0; i < DataSourceSize; i++) {
265
+ dataSource.add(GroupKeyPrefix + i);
266
+ }
267
+ query = new ProcessorQuery<HashSet<Integer>, Iterable<String>>(dataSource, resultType) {
268
+ @Override
269
+ protected Processor<Iterable<String>, ?> createChainAndReturnFirstProcessor(Processor<Map<GroupKey, HashSet<Integer>>, Void> resultReceiver) {
270
+ Processor<GroupedDataEntry<Integer>, Map<GroupKey, HashSet<Integer>>> aggregator = new ParallelGroupedDataCollectingAsSetProcessor<Integer>(executor, Collections.singleton(resultReceiver)) {
271
+ @Override
272
+ protected ProcessorInstruction<Map<GroupKey, HashSet<Integer>>> createInstruction(GroupedDataEntry<Integer> element) {
273
+ AbstractProcessorInstruction<Map<GroupKey, HashSet<Integer>>> instruction = (AbstractProcessorInstruction<Map<GroupKey, HashSet<Integer>>>) super.createInstruction(element);
274
+ StatefulProcessorInstruction<Map<GroupKey, HashSet<Integer>>> statefulInstruction = new StatefulInstructionWrapper<>(instruction);
275
+ unfinishedInstructions.add(statefulInstruction);
276
+ return statefulInstruction;
277
+ }
278
+
279
+ @Override
280
+ protected void storeElement(GroupedDataEntry<Integer> element) {
281
+ logExecution("Storing " + element);
282
+ super.storeElement(element);
283
+ }
284
+
285
+ @Override
286
+ public void afterInstructionFinished(ProcessorInstruction<Map<GroupKey, HashSet<Integer>>> instruction) {
287
+ super.afterInstructionFinished(instruction);
288
+ if(canProcessElements()) unfinishedInstructions.remove(instruction);
289
+ }
290
+ };
291
+
292
+ Processor<Element, GroupedDataEntry<Integer>> grouper = new AbstractParallelProcessor<Element, GroupedDataEntry<Integer>>(Element.class, groupedType, executor, Collections.singleton(aggregator)) {
293
+ @Override
294
+ protected ProcessorInstruction<GroupedDataEntry<Integer>> createInstruction(Element element) {
295
+ StatefulProcessorInstruction<GroupedDataEntry<Integer>> instruction = new StatefulProcessorInstruction<GroupedDataEntry<Integer>>(this, ProcessorInstructionPriority.Grouping) {
296
+ @Override
297
+ protected GroupedDataEntry<Integer> internalComputeResult() throws Exception {
298
+ logExecution("Grouping " + element);
299
+ return new GroupedDataEntry<>(new GenericGroupKey<>(element.getName()), element.getValue());
300
+ }
301
+ };
302
+ unfinishedInstructions.add(instruction);
303
+ return instruction;
304
+ }
305
+
306
+ @Override
307
+ public void afterInstructionFinished(ProcessorInstruction<GroupedDataEntry<Integer>> instruction) {
308
+ super.afterInstructionFinished(instruction);
309
+ if(canProcessElements()) unfinishedInstructions.remove(instruction);
310
+ }
311
+
312
+ @Override
313
+ protected void setAdditionalData(AdditionalResultDataBuilder additionalDataBuilder) { }
314
+ };
315
+
316
+ Processor<Element, Element> heavyLoadProcessor = new AbstractParallelProcessor<Element, Element>(Element.class, Element.class, executor, Collections.singleton(grouper)) {
317
+ @Override
318
+ protected ProcessorInstruction<Element> createInstruction(Element element) {
319
+ StatefulProcessorInstruction<Element> instruction = new HeavyLoadInstruction(this,
320
+ ProcessorInstructionPriority.Extraction, HeavyLoadInstructionStepDuration,
321
+ HeavyLoadInstructionNumberOfSteps, element, TestAbortingHeavyLoadQuery.this::logExecution);
322
+ unfinishedInstructions.add(instruction);
323
+ return instruction;
324
+ }
325
+
326
+ @Override
327
+ public void afterInstructionFinished(ProcessorInstruction<Element> instruction) {
328
+ super.afterInstructionFinished(instruction);
329
+ if(canProcessElements()) unfinishedInstructions.remove(instruction);
330
+ }
331
+
332
+ @Override
333
+ protected void setAdditionalData(AdditionalResultDataBuilder additionalDataBuilder) { }
334
+ };
335
+
336
+ Processor<String, Element> retriever1 = new AbstractRetrievalProcessor<String, Element>(String.class, Element.class, executor, Collections.singleton(heavyLoadProcessor), 1) {
337
+ @Override
338
+ protected ProcessorInstruction<Element> createInstruction(String element) {
339
+ AbstractProcessorInstruction<Element> instruction = (AbstractProcessorInstruction<Element>) super.createInstruction(element);
340
+ StatefulProcessorInstruction<Element> statefulInstruction = new StatefulInstructionWrapper<>(instruction);
341
+ unfinishedInstructions.add(statefulInstruction);
342
+ return statefulInstruction;
343
+ }
344
+
345
+ @Override
346
+ protected Iterable<Element> retrieveData(String element) {
347
+ int count = ExecutorPoolSize;
348
+ logExecution("Retrieving " + count + " elements for " + element);
349
+ Collection<Element> data = new ArrayList<>();
350
+ for (int i = 0; i < count; i++) {
351
+ data.add(new Element(element, i));
352
+ }
353
+ return data;
354
+ }
355
+
356
+ @Override
357
+ public void instructionSucceeded(Element result) {
358
+ logExecution("Group retrieval finished");
359
+ super.instructionSucceeded(result);
360
+ }
361
+
362
+ @Override
363
+ public void afterInstructionFinished(ProcessorInstruction<Element> instruction) {
364
+ super.afterInstructionFinished(instruction);
365
+ if(canProcessElements()) unfinishedInstructions.remove(instruction);
366
+ }
367
+ };
368
+ Processor<Iterable<String>, String> retriever0 = new AbstractRetrievalProcessor<Iterable<String>, String>(dataSourceType, String.class, executor, Collections.singleton(retriever1), 0) {
369
+ @Override
370
+ protected ProcessorInstruction<String> createInstruction(Iterable<String> element) {
371
+ AbstractProcessorInstruction<String> instruction = (AbstractProcessorInstruction<String>) super.createInstruction(element);
372
+ StatefulProcessorInstruction<String> statefulInstruction = new StatefulInstructionWrapper<>(instruction);
373
+ unfinishedInstructions.add(statefulInstruction);
374
+ return statefulInstruction;
375
+ }
376
+
377
+ @Override
378
+ protected Iterable<String> retrieveData(Iterable<String> element) {
379
+ logExecution("Retrieving data from data source");
380
+ return element;
381
+ }
382
+
383
+ @Override
384
+ public void instructionSucceeded(String result) {
385
+ logExecution("Data source retrieval finished");
386
+ super.instructionSucceeded(result);
387
+ }
388
+
389
+ @Override
390
+ public void afterInstructionFinished(ProcessorInstruction<String> instruction) {
391
+ super.afterInstructionFinished(instruction);
392
+ if(canProcessElements()) unfinishedInstructions.remove(instruction);
393
+ }
394
+ };
395
+
396
+ processors.add(retriever0);
397
+ processors.add(retriever1);
398
+ processors.add(heavyLoadProcessor);
399
+ processors.add(grouper);
400
+ processors.add(aggregator);
401
+
402
+ return retriever0;
403
+ }
404
+ };
405
+ }
406
+
407
+ private static class HeavyLoadInstruction extends StatefulBlockingInstruction<Element> {
408
+
409
+ private final Consumer<String> recorder;
410
+
411
+ public HeavyLoadInstruction(ProcessorInstructionHandler<Element> handler, ProcessorInstructionPriority priority,
412
+ long stepDuration, int numberOfSteps, Element result, Consumer<String> recorder) {
413
+ super(handler, priority, stepDuration, numberOfSteps, result);
414
+ this.recorder = recorder;
415
+ }
416
+
417
+ @Override
418
+ public void run() {
419
+ recorder.accept("Executing heavy load instruction for " + result);
420
+ super.run();
421
+ }
422
+
423
+ @Override
424
+ protected void actionBeforeBlock() {
425
+ recorder.accept("Starting work for heavy load instruction for " + result);
426
+ }
427
+
428
+ @Override
429
+ protected void actionBeforeAbort() {
430
+ recorder.accept("Aborting heavy load instruction for " + result);
431
+ }
432
+
433
+ @Override
434
+ protected void actionAfterBlock() {
435
+ recorder.accept("Finished heavy load instruction for " + result);
436
+ }
437
+
438
+ }
439
+
440
+ private static class StatefulInstructionWrapper<ResultType> extends StatefulProcessorInstruction<ResultType> {
441
+
442
+ private static Method computeResult;
443
+
444
+ private final AbstractProcessorInstruction<ResultType> instruction;
445
+
446
+ public StatefulInstructionWrapper(AbstractProcessorInstruction<ResultType> instruction) {
447
+ super(instruction.getHandler(), instruction.getPriority());
448
+ this.instruction = instruction;
449
+ }
450
+
451
+ @Override
452
+ @SuppressWarnings("unchecked")
453
+ protected ResultType internalComputeResult() throws Exception {
454
+ if (computeResult == null) {
455
+ computeResult = AbstractProcessorInstruction.class.getDeclaredMethod("computeResult");
456
+ computeResult.setAccessible(true);
457
+ }
458
+ return (ResultType) computeResult.invoke(instruction);
459
+ }
460
+
461
+ }
462
+
463
+ @After
464
+ public void resetComputeResultAccessibility() throws SecurityException, NoSuchMethodException {
465
+ AbstractProcessorInstruction.class.getDeclaredMethod("computeResult").setAccessible(false);
466
+ }
467
+
468
+ /**
469
+ * Simple data type consisting of a name and value.
470
+ */
471
+ private static class Element {
472
+
473
+ private final String name;
474
+ private final int value;
475
+
476
+ public Element(String name, int value) {
477
+ this.name = name;
478
+ this.value = value;
479
+ }
480
+
481
+ public String getName() {
482
+ return name;
483
+ }
484
+
485
+ public int getValue() {
486
+ return value;
487
+ }
488
+
489
+ @Override
490
+ public String toString() {
491
+ return getName() + "-" + getValue();
492
+ }
493
+
494
+ @Override
495
+ public int hashCode() {
496
+ final int prime = 31;
497
+ int result = 1;
498
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
499
+ result = prime * result + value;
500
+ return result;
501
+ }
502
+
503
+ @Override
504
+ public boolean equals(Object obj) {
505
+ if (this == obj)
506
+ return true;
507
+ if (obj == null)
508
+ return false;
509
+ if (getClass() != obj.getClass())
510
+ return false;
511
+ Element other = (Element) obj;
512
+ if (name == null) {
513
+ if (other.name != null)
514
+ return false;
515
+ } else if (!name.equals(other.name))
516
+ return false;
517
+ if (value != other.value)
518
+ return false;
519
+ return true;
520
+ }
521
+
522
+ }
523
+
524
+}
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/TestProcessorQuery.java
... ...
@@ -63,7 +63,7 @@ public class TestProcessorQuery {
63 63
Collection<Processor<Double, ?>> resultReceivers = new ArrayList<>();
64 64
resultReceivers.add(new AbortResultReceiver(resultReceiver));
65 65
return new BlockingProcessor<Iterable<Number>, Double>((Class<Iterable<Number>>)(Class<?>) Iterable.class, Double.class,
66
- ConcurrencyTestsUtil.getExecutor(), resultReceivers, 1000) {
66
+ ConcurrencyTestsUtil.getSharedExecutor(), resultReceivers, 1000) {
67 67
@Override
68 68
protected Double createResult(Iterable<Number> element) {
69 69
return 0.0;
... ...
@@ -101,7 +101,7 @@ public class TestProcessorQuery {
101 101
Collection<Processor<Double, ?>> resultReceivers = new ArrayList<>();
102 102
resultReceivers.add(new AbortResultReceiver(resultReceiver));
103 103
return new BlockingProcessor<Iterable<Number>, Double>((Class<Iterable<Number>>)(Class<?>) Iterable.class, Double.class,
104
- ConcurrencyTestsUtil.getExecutor(), resultReceivers, 1000) {
104
+ ConcurrencyTestsUtil.getSharedExecutor(), resultReceivers, 1000) {
105 105
@Override
106 106
protected Double createResult(Iterable<Number> element) {
107 107
return 0.0;
... ...
@@ -168,7 +168,7 @@ public class TestProcessorQuery {
168 168
resultReceivers.add(resultReceiver);
169 169
return new AbstractParallelProcessor<Iterable<Number>, Map<GroupKey, Double>>((Class<Iterable<Number>>)(Class<?>) Iterable.class,
170 170
(Class<Map<GroupKey, Double>>)(Class<?>) Map.class,
171
- ConcurrencyTestsUtil.getExecutor(),
171
+ ConcurrencyTestsUtil.getSharedExecutor(),
172 172
resultReceivers) {
173 173
@Override
174 174
protected ProcessorInstruction<Map<GroupKey, Double>> createInstruction(final Iterable<Number> element) {
... ...
@@ -242,7 +242,7 @@ public class TestProcessorQuery {
242 242
resultReceivers.add(resultReceiver);
243 243
return new AbstractParallelProcessor<Double, Map<GroupKey, Double>>(Double.class,
244 244
(Class<Map<GroupKey, Double>>)(Class<?>) Map.class,
245
- ConcurrencyTestsUtil.getExecutor(),
245
+ ConcurrencyTestsUtil.getSharedExecutor(),
246 246
resultReceivers) {
247 247
@Override
248 248
protected ProcessorInstruction<Map<GroupKey, Double>> createInstruction(Double element) {
... ...
@@ -282,7 +282,7 @@ public class TestProcessorQuery {
282 282
resultReceivers.add(resultReceiver);
283 283
return new AbstractParallelProcessor<Double, Map<GroupKey, Double>>(Double.class,
284 284
(Class<Map<GroupKey, Double>>)(Class<?>) Map.class,
285
- ConcurrencyTestsUtil.getExecutor(),
285
+ ConcurrencyTestsUtil.getSharedExecutor(),
286 286
resultReceivers) {
287 287
@Override
288 288
protected ProcessorInstruction<Map<GroupKey, Double>> createInstruction(Double element) {
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestAbstractParallelProcessorElementProcessing.java
... ...
@@ -0,0 +1,152 @@
1
+package com.sap.sse.datamining.impl.components;
2
+
3
+import static org.hamcrest.Matchers.is;
4
+import static org.junit.Assert.assertFalse;
5
+import static org.junit.Assert.assertThat;
6
+import static org.junit.Assert.assertTrue;
7
+
8
+import java.util.ArrayList;
9
+import java.util.Collections;
10
+import java.util.List;
11
+import java.util.concurrent.LinkedBlockingQueue;
12
+import java.util.concurrent.ThreadPoolExecutor;
13
+import java.util.concurrent.TimeUnit;
14
+
15
+import org.junit.Before;
16
+import org.junit.Test;
17
+
18
+import com.sap.sse.common.Util.Pair;
19
+import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
20
+import com.sap.sse.datamining.components.Processor;
21
+import com.sap.sse.datamining.components.ProcessorInstruction;
22
+import com.sap.sse.datamining.test.util.ConcurrencyTestsUtil;
23
+import com.sap.sse.datamining.test.util.components.StatefulBlockingInstruction;
24
+
25
+public class TestAbstractParallelProcessorElementProcessing {
26
+
27
+ private ThreadPoolExecutor executor;
28
+ private Processor<Pair<Long, Integer>, Object> processor;
29
+ private List<StatefulBlockingInstruction<?>> createdInstructions;
30
+
31
+ @Before
32
+ public void initialize() {
33
+ int corePoolSize = Runtime.getRuntime().availableProcessors();
34
+ executor = new ThreadPoolExecutor(corePoolSize, corePoolSize, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
35
+ createdInstructions = new ArrayList<>();
36
+
37
+ @SuppressWarnings("unchecked")
38
+ Class<Pair<Long, Integer>> inputType = (Class<Pair<Long, Integer>>)(Class<?>) Pair.class;
39
+ processor = new AbstractParallelProcessor<Pair<Long, Integer>, Object>(inputType, Object.class, executor, Collections.emptySet()) {
40
+ @Override
41
+ protected ProcessorInstruction<Object> createInstruction(Pair<Long, Integer> sleepTime) {
42
+ StatefulBlockingInstruction<Object> instruction = new StatefulBlockingInstruction<>(this, sleepTime.getA(), sleepTime.getB());
43
+ createdInstructions.add(instruction);
44
+ return instruction;
45
+ }
46
+ @Override
47
+ protected void setAdditionalData(AdditionalResultDataBuilder additionalDataBuilder) { }
48
+ };
49
+ }
50
+
51
+ @Test
52
+ public void testSimpleProcessing() throws InterruptedException {
53
+ long stepDuration = 10;
54
+ int numberOfSteps = 1;
55
+ Pair<Long, Integer> input = new Pair<Long, Integer>(stepDuration, numberOfSteps);
56
+ int elementCount = executor.getMaximumPoolSize() * 2;
57
+ for (int i = 0; i < elementCount; i++) {
58
+ processor.processElement(input);
59
+ }
60
+
61
+ assertThat("Unexpected amount of created instructions", createdInstructions.size(), is(elementCount));
62
+ double executionTime = Math.ceil((double) elementCount / executor.getMaximumPoolSize()) * stepDuration * numberOfSteps;
63
+ executor.shutdown();
64
+ assertTrue("Executor couldn't terminate", executor.awaitTermination((long) (executionTime * 1.2), TimeUnit.SECONDS));
65
+ for (StatefulBlockingInstruction<?> instruction : createdInstructions) {
66
+ assertTrue("run wasn't called", instruction.runWasCalled());
67
+ assertTrue("computeResult wasn't called", instruction.computeResultWasCalled());
68
+ assertTrue("computeResult didn't finish", instruction.computeResultWasFinished());
69
+ assertFalse("computeResult was aborted", instruction.computeResultWasAborted());
70
+ }
71
+ }
72
+
73
+ @Test
74
+ public void testProcessingAfterFinish() throws InterruptedException {
75
+ long stepDuration = 10;
76
+ int numberOfSteps = 5;
77
+ Pair<Long, Integer> input = new Pair<Long, Integer>(stepDuration, numberOfSteps);
78
+ int elementCount = executor.getMaximumPoolSize() + 1; // Last instruction will be queued
79
+ for (int i = 0; i < elementCount; i++) {
80
+ processor.processElement(input);
81
+ }
82
+ assertThat("Unexpected amount of created instructions", createdInstructions.size(), is(elementCount));
83
+
84
+ Thread.sleep(stepDuration); // Giving some time to ensure execution of unqueued instructions
85
+ Thread finishingThread = ConcurrencyTestsUtil.tryToFinishTheProcessorInAnotherThread(processor);
86
+ do {
87
+ Thread.sleep(1);
88
+ } while (!finishingThread.isAlive());
89
+ assertFalse("Processor is already finished", processor.isFinished());
90
+ // Processor not yet finished. New elements will be accepted
91
+ processor.processElement(input);
92
+ elementCount++;
93
+ assertThat("Unexpected amount of created instructions", createdInstructions.size(), is(elementCount));
94
+
95
+ finishingThread.join();
96
+ assertTrue("Processor isn't finished", processor.isFinished());
97
+ processor.processElement(input);
98
+ assertThat("Unexpected amount of created instructions", createdInstructions.size(), is(elementCount));
99
+
100
+ for (StatefulBlockingInstruction<?> instruction : createdInstructions) {
101
+ assertTrue("run wasn't called", instruction.runWasCalled());
102
+ assertTrue("computeResult wasn't called", instruction.computeResultWasCalled());
103
+ assertTrue("computeResult didn't finish", instruction.computeResultWasFinished());
104
+ assertFalse("computeResult was aborted", instruction.computeResultWasAborted());
105
+ }
106
+ }
107
+
108
+ @Test
109
+ public void testProcessingAfterAbort() throws InterruptedException {
110
+ long stepDuration = 10;
111
+ int numberOfSteps = 5;
112
+ Pair<Long, Integer> input = new Pair<Long, Integer>(stepDuration, numberOfSteps);
113
+ int elementCount = executor.getMaximumPoolSize() // Set of finished instructions
114
+ + executor.getMaximumPoolSize() // Set of started, but not yet finished instructions
115
+ + 1; // Scheduled instruction
116
+ for (int i = 0; i < elementCount; i++) {
117
+ processor.processElement(input);
118
+ }
119
+ assertThat("Unexpected amount of created instructions", createdInstructions.size(), is(elementCount));
120
+
121
+ long instructionDuration = stepDuration * numberOfSteps;
122
+ Thread.sleep(instructionDuration + stepDuration); // Time to finish first set and start second set
123
+ processor.abort();
124
+ processor.processElement(new Pair<>(0L, 0));
125
+ assertThat("Unexpected amount of created instructions", createdInstructions.size(), is(elementCount));
126
+
127
+ executor.shutdown();
128
+ assertTrue("Executor couldn't terminate", executor.awaitTermination(2 * stepDuration, TimeUnit.MILLISECONDS));
129
+ for (int i = 0; i < createdInstructions.size(); i++) {
130
+ StatefulBlockingInstruction<?> instruction = createdInstructions.get(i);
131
+ // run should be called for all instructions
132
+ assertTrue("run wasn't called", instruction.runWasCalled());
133
+ if (i < executor.getMaximumPoolSize()) {
134
+ // First set of instructions should be processed normally
135
+ assertTrue("computeResult wasn't called", instruction.computeResultWasCalled());
136
+ assertTrue("computeResult didn't finish", instruction.computeResultWasFinished());
137
+ assertFalse("computeResult was aborted", instruction.computeResultWasAborted());
138
+ } else if (i < executor.getMaximumPoolSize() * 2) {
139
+ // Second set of instructions was running when the processor was aborted. computeResult should be aborted
140
+ assertTrue("computeResult wasn't called", instruction.computeResultWasCalled());
141
+ assertTrue("computeResult didn't finish", instruction.computeResultWasFinished());
142
+ assertTrue("computeResult wasn't aborted", instruction.computeResultWasAborted());
143
+ } else {
144
+ // Last instructions was still scheduled when the processor was aborted. computeResult should not be called
145
+ assertFalse("computeResult of last instruction was called", instruction.computeResultWasCalled());
146
+ assertFalse("computeResult of last instruction finished", instruction.computeResultWasFinished());
147
+ assertFalse("computeResult was aborted", instruction.computeResultWasAborted());
148
+ }
149
+ }
150
+ }
151
+
152
+}
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestAbstractParallelProcessorFinishing.java
... ...
@@ -68,7 +68,7 @@ public class TestAbstractParallelProcessorFinishing {
68 68
}
69 69
70 70
private AbstractParallelProcessor<Integer, Integer> createProcessor(Collection<Processor<Integer, ?>> receivers) {
71
- return new AbstractParallelProcessor<Integer, Integer>(Integer.class, Integer.class, ConcurrencyTestsUtil.getExecutor(), receivers) {
71
+ return new AbstractParallelProcessor<Integer, Integer>(Integer.class, Integer.class, ConcurrencyTestsUtil.getSharedExecutor(), receivers) {
72 72
@Override
73 73
protected ProcessorInstruction<Integer> createInstruction(Integer partialElement) {
74 74
return new AbstractProcessorInstruction<Integer>(this) {
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestAbstractParallelProcessorWithManySimpleInstructions.java
... ...
@@ -37,7 +37,7 @@ public class TestAbstractParallelProcessorWithManySimpleInstructions {
37 37
38 38
Collection<Processor<Integer, ?>> receivers = new ArrayList<>();
39 39
receivers.add(receiver);
40
- processor = new AbstractParallelProcessor<Integer, Integer>(Integer.class, Integer.class, ConcurrencyTestsUtil.getExecutor(), receivers) {
40
+ processor = new AbstractParallelProcessor<Integer, Integer>(Integer.class, Integer.class, ConcurrencyTestsUtil.getSharedExecutor(), receivers) {
41 41
@Override
42 42
protected ProcessorInstruction<Integer> createInstruction(final Integer element) {
43 43
return new AbstractProcessorInstruction<Integer>(this) {
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestDataRetrieverChainCreation.java
... ...
@@ -1,6 +1,6 @@
1 1
package com.sap.sse.datamining.impl.components;
2 2
3
-import static com.sap.sse.datamining.test.util.ConcurrencyTestsUtil.getExecutor;
3
+import static com.sap.sse.datamining.test.util.ConcurrencyTestsUtil.getSharedExecutor;
4 4
import static org.hamcrest.Matchers.is;
5 5
import static org.hamcrest.Matchers.not;
6 6
import static org.junit.Assert.assertThat;
... ...
@@ -90,12 +90,12 @@ public class TestDataRetrieverChainCreation {
90 90
91 91
assertThat(chainClone, not(dataRetrieverChainDefinition));
92 92
93
- chainClone.startBuilding(ConcurrencyTestsUtil.getExecutor());
93
+ chainClone.startBuilding(ConcurrencyTestsUtil.getSharedExecutor());
94 94
}
95 95
96 96
@Test
97 97
public void testThatTheDataRetrieverChainBuilderHasToBeInitialized() {
98
- DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getExecutor());
98
+ DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getSharedExecutor());
99 99
100 100
try {
101 101
chainBuilder.getCurrentRetrievedDataType();
... ...
@@ -126,7 +126,7 @@ public class TestDataRetrieverChainCreation {
126 126
127 127
@Test
128 128
public void testStepByStepDataRetrieverChainCreation() throws InterruptedException {
129
- DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getExecutor());
129
+ DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getSharedExecutor());
130 130
chainBuilder.stepFurther(); //Initialization
131 131
132 132
assertThat(chainBuilder.getCurrentRetrievedDataType().equals(Test_Regatta.class), is(true));
... ...
@@ -206,7 +206,7 @@ public class TestDataRetrieverChainCreation {
206 206
207 207
@Test(expected=IllegalArgumentException.class)
208 208
public void testSettingAFilterWithWrongElementType() {
209
- DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getExecutor());
209
+ DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getSharedExecutor());
210 210
chainBuilder.stepFurther(); //Initialization
211 211
212 212
chainBuilder.setFilter(raceFilter);
... ...
@@ -214,7 +214,7 @@ public class TestDataRetrieverChainCreation {
214 214
215 215
@Test(expected=IllegalArgumentException.class)
216 216
public void testSettingAResultReceiverWithWrongInputType() {
217
- DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getExecutor());
217
+ DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getSharedExecutor());
218 218
chainBuilder.stepFurther(); //Initialization
219 219
220 220
chainBuilder.addResultReceiver(legReceiver);
... ...
@@ -253,12 +253,12 @@ public class TestDataRetrieverChainCreation {
253 253
raceRetrieverClass,
254 254
Test_HasRaceContext.class, "race");
255 255
256
- dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getExecutor());
256
+ dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getSharedExecutor());
257 257
}
258 258
259 259
@Test(expected=IllegalStateException.class)
260 260
public void testSteppingToFar() {
261
- DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getExecutor());
261
+ DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getSharedExecutor());
262 262
while (chainBuilder.canStepFurther()) {
263 263
chainBuilder.stepFurther();
264 264
}
... ...
@@ -272,7 +272,7 @@ public class TestDataRetrieverChainCreation {
272 272
chainWithSettings.endWith(TestLegOfCompetitorWithContextRetrievalProcessor.class, Test_RetrievalProcessorWithSettings.class, Test_HasLegOfCompetitorContext.class,
273 273
Test_RetrievalProcessorSettings.class, new Test_RetrievalProcessorSettings("Default Settings"), "legOfCompetitor");
274 274
275
- DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = chainWithSettings.startBuilding(getExecutor());
275
+ DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = chainWithSettings.startBuilding(getSharedExecutor());
276 276
while (chainBuilder.canStepFurther()) {
277 277
chainBuilder.stepFurther();
278 278
}
... ...
@@ -311,7 +311,7 @@ public class TestDataRetrieverChainCreation {
311 311
chainWithSettings.endWith(TestLegOfCompetitorWithContextRetrievalProcessor.class, Test_RetrievalProcessorWithSettings.class, Test_HasLegOfCompetitorContext.class,
312 312
Test_RetrievalProcessorSettings.class, new Test_RetrievalProcessorSettings("Default Settings"), "legOfCompetitor");
313 313
314
- DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = chainWithSettings.startBuilding(getExecutor());
314
+ DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = chainWithSettings.startBuilding(getSharedExecutor());
315 315
while (chainBuilder.canStepFurther()) {
316 316
chainBuilder.stepFurther();
317 317
}
... ...
@@ -320,7 +320,7 @@ public class TestDataRetrieverChainCreation {
320 320
321 321
@Test(expected=IllegalStateException.class)
322 322
public void testRetrieverWithNoSettingsButSettedSettingsCreated() {
323
- DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getExecutor());
323
+ DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getSharedExecutor());
324 324
chainBuilder.stepFurther(); // Initialization
325 325
chainBuilder.setSettings(new WrongSettings());
326 326
}
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestFilteringProcessors.java
... ...
@@ -34,7 +34,7 @@ public class TestFilteringProcessors {
34 34
return element % 2 == 0;
35 35
}
36 36
};
37
- Processor<Integer, Integer> filteringProcessor = new ParallelFilteringProcessor<Integer>(Integer.class, ConcurrencyTestsUtil.getExecutor(), receivers, elementIsEvenCriteria);
37
+ Processor<Integer, Integer> filteringProcessor = new ParallelFilteringProcessor<Integer>(Integer.class, ConcurrencyTestsUtil.getSharedExecutor(), receivers, elementIsEvenCriteria);
38 38
ConcurrencyTestsUtil.processElements(filteringProcessor, createElementsToProcess());
39 39
ConcurrencyTestsUtil.sleepFor(100); // Giving the processor time to process the instructions
40 40
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestParallelExtractionProcessor.java
... ...
@@ -63,7 +63,7 @@ public class TestParallelExtractionProcessor {
63 63
64 64
@Test
65 65
public void testValueExtraction() {
66
- Processor<GroupedDataEntry<Number>, GroupedDataEntry<Integer>> processor = new ParallelGroupedElementsValueExtractionProcessor<Number, Integer>(ConcurrencyTestsUtil.getExecutor(), receivers, getCrossSumFunction);
66
+ Processor<GroupedDataEntry<Number>, GroupedDataEntry<Integer>> processor = new ParallelGroupedElementsValueExtractionProcessor<Number, Integer>(ConcurrencyTestsUtil.getSharedExecutor(), receivers, getCrossSumFunction);
67 67
Collection<GroupedDataEntry<Number>> elements = createElements();
68 68
ConcurrencyTestsUtil.processElements(processor, elements);
69 69
ConcurrencyTestsUtil.sleepFor(100); //Giving the processor time to finish the instructions
... ...
@@ -81,7 +81,7 @@ public class TestParallelExtractionProcessor {
81 81
82 82
@Test
83 83
public void testValueExtractionWithInvalidFunction() {
84
- Processor<GroupedDataEntry<Number>, GroupedDataEntry<Integer>> processor = new ParallelGroupedElementsValueExtractionProcessor<Number, Integer>(ConcurrencyTestsUtil.getExecutor(), receivers, invalidFunction);
84
+ Processor<GroupedDataEntry<Number>, GroupedDataEntry<Integer>> processor = new ParallelGroupedElementsValueExtractionProcessor<Number, Integer>(ConcurrencyTestsUtil.getSharedExecutor(), receivers, invalidFunction);
85 85
ConcurrencyTestsUtil.processElements(processor, createElements());
86 86
ConcurrencyTestsUtil.sleepFor(100); //Giving the processor time to finish the instructions
87 87
assertThat("Values have been received, but the processor function is invalid.", receivedValues.isEmpty(), is(true));
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestParallelMultiDimensionalGroupingProcessor.java
... ...
@@ -57,7 +57,7 @@ public class TestParallelMultiDimensionalGroupingProcessor {
57 57
58 58
@Test(expected=IllegalArgumentException.class)
59 59
public void testConstructionWithNullDimensions() {
60
- new ParallelMultiDimensionsValueNestingGroupingProcessor<>(Number.class, ConcurrencyTestsUtil.getExecutor(), receivers, null);
60
+ new ParallelMultiDimensionsValueNestingGroupingProcessor<>(Number.class, ConcurrencyTestsUtil.getSharedExecutor(), receivers, null);
61 61
}
62 62
63 63
@Test(expected=IllegalArgumentException.class)
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestRetrieverFilterProcessorChain.java
... ...
@@ -72,7 +72,7 @@ public class TestRetrieverFilterProcessorChain {
72 72
resultReceivers.add(retrievalProcessor);
73 73
@SuppressWarnings("unchecked")
74 74
Processor<Iterable<Iterable<Integer>>, Iterable<Integer>> layeredRetrievalProcessor = new AbstractRetrievalProcessor<Iterable<Iterable<Integer>>, Iterable<Integer>>((Class<Iterable<Iterable<Integer>>>)(Class<?>) Iterable.class, (Class<Iterable<Integer>>)(Class<?>) Iterable.class,
75
- ConcurrencyTestsUtil.getExecutor(), resultReceivers, 0) {
75
+ ConcurrencyTestsUtil.getSharedExecutor(), resultReceivers, 0) {
76 76
@Override
77 77
protected Iterable<Iterable<Integer>> retrieveData(Iterable<Iterable<Integer>> element) {
78 78
return element;
... ...
@@ -110,11 +110,11 @@ public class TestRetrieverFilterProcessorChain {
110 110
return element >= 0;
111 111
}
112 112
};
113
- Processor<Integer, Integer> filtrationProcessor = new ParallelFilteringProcessor<>(Integer.class, ConcurrencyTestsUtil.getExecutor(), filtrationResultReceivers, elementGreaterZeroFilterCriteria);
113
+ Processor<Integer, Integer> filtrationProcessor = new ParallelFilteringProcessor<>(Integer.class, ConcurrencyTestsUtil.getSharedExecutor(), filtrationResultReceivers, elementGreaterZeroFilterCriteria);
114 114
115 115
Collection<Processor<Integer, ?>> retrievalResultReceivers = new ArrayList<>();
116 116
retrievalResultReceivers.add(filtrationProcessor);
117
- retrievalProcessor = new AbstractRetrievalProcessor<Iterable<Integer>, Integer>((Class<Iterable<Integer>>)(Class<?>) Iterable.class, Integer.class, ConcurrencyTestsUtil.getExecutor(), retrievalResultReceivers, 1) {
117
+ retrievalProcessor = new AbstractRetrievalProcessor<Iterable<Integer>, Integer>((Class<Iterable<Integer>>)(Class<?>) Iterable.class, Integer.class, ConcurrencyTestsUtil.getSharedExecutor(), retrievalResultReceivers, 1) {
118 118
@Override
119 119
protected Iterable<Integer> retrieveData(Iterable<Integer> element) {
120 120
return element;
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/aggregators/TestAbstractStoringParallelAggregationProcessor.java
... ...
@@ -48,7 +48,7 @@ public class TestAbstractStoringParallelAggregationProcessor {
48 48
49 49
@Test
50 50
public void testAbstractAggregationHandling() throws InterruptedException {
51
- Processor<GroupedDataEntry<Integer>, Map<GroupKey, Integer>> processor = new AbstractParallelGroupedDataStoringAggregationProcessor<Integer, Integer>(ConcurrencyTestsUtil.getExecutor(), receivers, "Sum") {
51
+ Processor<GroupedDataEntry<Integer>, Map<GroupKey, Integer>> processor = new AbstractParallelGroupedDataStoringAggregationProcessor<Integer, Integer>(ConcurrencyTestsUtil.getSharedExecutor(), receivers, "Sum") {
52 52
@Override
53 53
protected void storeElement(GroupedDataEntry<Integer> element) {
54 54
elementStore.add(element);
... ...
@@ -104,7 +104,7 @@ public class TestAbstractStoringParallelAggregationProcessor {
104 104
}
105 105
}
106 106
});
107
- Processor<GroupedDataEntry<Integer>, Map<GroupKey, Integer>> processor = new AbstractParallelGroupedDataStoringAggregationProcessor<Integer, Integer>(ConcurrencyTestsUtil.getExecutor(), receivers, "Sum") {
107
+ Processor<GroupedDataEntry<Integer>, Map<GroupKey, Integer>> processor = new AbstractParallelGroupedDataStoringAggregationProcessor<Integer, Integer>(ConcurrencyTestsUtil.getSharedExecutor(), receivers, "Sum") {
108 108
@Override
109 109
protected void storeElement(GroupedDataEntry<Integer> element) {
110 110
if (element.getDataEntry() < 0) {
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/aggregators/TestParallelAggregationProcessors.java
... ...
@@ -16,7 +16,7 @@ public class TestParallelAggregationProcessors extends AbstractTestParallelAvera
16 16
17 17
@Test
18 18
public void testSumAggregationProcessor() throws InterruptedException {
19
- Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> sumAggregationProcessor = ParallelGroupedNumberDataSumAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
19
+ Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> sumAggregationProcessor = ParallelGroupedNumberDataSumAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getSharedExecutor(), receivers);
20 20
Collection<GroupedDataEntry<Number>> elements = createElements();
21 21
ConcurrencyTestsUtil.processElements(sumAggregationProcessor, elements);
22 22
... ...
@@ -27,7 +27,7 @@ public class TestParallelAggregationProcessors extends AbstractTestParallelAvera
27 27
28 28
@Test
29 29
public void testMedianAggregationProcessor() throws InterruptedException {
30
- Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> medianAggregationProcessor = ParallelGroupedNumberDataMedianAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
30
+ Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> medianAggregationProcessor = ParallelGroupedNumberDataMedianAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getSharedExecutor(), receivers);
31 31
Collection<GroupedDataEntry<Number>> elements = createElements();
32 32
ConcurrencyTestsUtil.processElements(medianAggregationProcessor, elements);
33 33
... ...
@@ -38,7 +38,7 @@ public class TestParallelAggregationProcessors extends AbstractTestParallelAvera
38 38
39 39
@Test
40 40
public void testMaxAggregationProcessor() throws InterruptedException {
41
- Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> maxAggregationProcessor = ParallelGroupedNumberDataMaxAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
41
+ Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> maxAggregationProcessor = ParallelGroupedNumberDataMaxAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getSharedExecutor(), receivers);
42 42
Collection<GroupedDataEntry<Number>> elements = createElements();
43 43
ConcurrencyTestsUtil.processElements(maxAggregationProcessor, elements);
44 44
... ...
@@ -49,7 +49,7 @@ public class TestParallelAggregationProcessors extends AbstractTestParallelAvera
49 49
50 50
@Test
51 51
public void testMinAggregationProcessor() throws InterruptedException {
52
- Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> minAggregationProcessor = ParallelGroupedNumberDataMinAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
52
+ Processor<GroupedDataEntry<Number>, Map<GroupKey, Number>> minAggregationProcessor = ParallelGroupedNumberDataMinAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getSharedExecutor(), receivers);
53 53
Collection<GroupedDataEntry<Number>> elements = createElements();
54 54
ConcurrencyTestsUtil.processElements(minAggregationProcessor, elements);
55 55
... ...
@@ -60,7 +60,7 @@ public class TestParallelAggregationProcessors extends AbstractTestParallelAvera
60 60
61 61
@Test
62 62
public void testCountAggregationProcessor() throws InterruptedException {
63
- Processor<GroupedDataEntry<Object>, Map<GroupKey, Number>> countAggregationProcessor = ParallelGroupedDataCountAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
63
+ Processor<GroupedDataEntry<Object>, Map<GroupKey, Number>> countAggregationProcessor = ParallelGroupedDataCountAggregationProcessor.getDefinition().construct(ConcurrencyTestsUtil.getSharedExecutor(), receivers);
64 64
@SuppressWarnings("unchecked")
65 65
Collection<GroupedDataEntry<Object>> elements = (Collection<GroupedDataEntry<Object>>)(Collection<?>) createElements();
66 66
ConcurrencyTestsUtil.processElements(countAggregationProcessor, elements);
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/aggregators/TestParallelAveragingProcessors.java
... ...
@@ -19,7 +19,7 @@ public class TestParallelAveragingProcessors extends AbstractTestParallelAveragi
19 19
@Test
20 20
public void testAverageAggregationProcessor() throws InterruptedException {
21 21
Processor<GroupedDataEntry<Number>, Map<GroupKey, AverageWithStats<Number>>> averageAggregationProcessor = ParallelGroupedNumberDataAverageAggregationProcessor
22
- .getDefinition().construct(ConcurrencyTestsUtil.getExecutor(), receivers);
22
+ .getDefinition().construct(ConcurrencyTestsUtil.getSharedExecutor(), receivers);
23 23
Collection<GroupedDataEntry<Number>> elements = createElements();
24 24
ConcurrencyTestsUtil.processElements(averageAggregationProcessor, elements);
25 25
averageAggregationProcessor.finish();
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/aggregators/TestParallelGroupedDataCollectingAsSetProcessor.java
... ...
@@ -37,7 +37,7 @@ public class TestParallelGroupedDataCollectingAsSetProcessor {
37 37
38 38
@Test
39 39
public void testDataCollecting() throws InterruptedException {
40
- Processor<GroupedDataEntry<Double>, Map<GroupKey, HashSet<Double>>> collectingProcessor = new ParallelGroupedDataCollectingAsSetProcessor<Double>(ConcurrencyTestsUtil.getExecutor(), receivers);
40
+ Processor<GroupedDataEntry<Double>, Map<GroupKey, HashSet<Double>>> collectingProcessor = new ParallelGroupedDataCollectingAsSetProcessor<Double>(ConcurrencyTestsUtil.getSharedExecutor(), receivers);
41 41
Collection<GroupedDataEntry<Double>> elements = createElements();
42 42
43 43
ConcurrencyTestsUtil.processElements(collectingProcessor, elements);
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestFunctionManagerAsFunctionRegistry.java
... ...
@@ -63,7 +63,7 @@ public class TestFunctionManagerAsFunctionRegistry {
63 63
DataRetrieverChainDefinitionRegistry dataRetrieverChainDefinitionRegistry = new DataRetrieverChainDefinitionManager();
64 64
AggregationProcessorDefinitionRegistry aggregationProcessorDefinitionRegistry = new AggregationProcessorDefinitionManager();
65 65
QueryDefinitionDTORegistry queryDefinitionRegistry = new QueryDefinitionDTOManager();
66
- ModifiableDataMiningServer server = new DataMiningServerImpl(ConcurrencyTestsUtil.getExecutor(), functionManager,
66
+ ModifiableDataMiningServer server = new DataMiningServerImpl(ConcurrencyTestsUtil.getSharedExecutor(), functionManager,
67 67
dataSourceProviderRegistry,
68 68
dataRetrieverChainDefinitionRegistry,
69 69
aggregationProcessorDefinitionRegistry,
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/test/util/ComponentTestsUtil.java
... ...
@@ -22,7 +22,7 @@ import com.sap.sse.datamining.test.domain.impl.Test_TeamImpl;
22 22
23 23
public final class ComponentTestsUtil {
24 24
25
- private final static ProcessorFactory processorFactory = new ProcessorFactory(ConcurrencyTestsUtil.getExecutor());
25
+ private final static ProcessorFactory processorFactory = new ProcessorFactory(ConcurrencyTestsUtil.getSharedExecutor());
26 26
27 27
public static ProcessorFactory getProcessorFactory() {
28 28
return processorFactory;
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/test/util/ConcurrencyTestsUtil.java
... ...
@@ -19,7 +19,7 @@ public class ConcurrencyTestsUtil extends TestsUtil {
19 19
private static final int THREAD_POOL_SIZE = Math.max(Runtime.getRuntime().availableProcessors(), 3);
20 20
private static final ExecutorService executor = new DataMiningExecutorService(THREAD_POOL_SIZE);
21 21
22
- public static ExecutorService getExecutor() {
22
+ public static ExecutorService getSharedExecutor() {
23 23
return executor;
24 24
}
25 25
... ...
@@ -47,7 +47,7 @@ public class ConcurrencyTestsUtil extends TestsUtil {
47 47
}
48 48
}
49 49
50
- public static void tryToFinishTheProcessorInAnotherThread(final Processor<?, ?> processor) {
50
+ public static Thread tryToFinishTheProcessorInAnotherThread(final Processor<?, ?> processor) {
51 51
Thread finishingThread = new Thread(new Runnable() {
52 52
@Override
53 53
public void run() {
... ...
@@ -59,6 +59,7 @@ public class ConcurrencyTestsUtil extends TestsUtil {
59 59
}
60 60
});
61 61
finishingThread.start();
62
+ return finishingThread;
62 63
}
63 64
64 65
protected ConcurrencyTestsUtil() {
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/test/util/TestsUtil.java
... ...
@@ -1,6 +1,7 @@
1 1
package com.sap.sse.datamining.test.util;
2 2
3 3
import java.nio.charset.StandardCharsets;
4
+import java.util.concurrent.ExecutorService;
4 5
5 6
import com.sap.sse.datamining.ModifiableDataMiningServer;
6 7
import com.sap.sse.datamining.components.management.AggregationProcessorDefinitionRegistry;
... ...
@@ -55,12 +56,16 @@ public class TestsUtil {
55 56
}
56 57
57 58
public static ModifiableDataMiningServer createNewServer() {
59
+ return createNewServer(ConcurrencyTestsUtil.getSharedExecutor());
60
+ }
61
+
62
+ public static ModifiableDataMiningServer createNewServer(ExecutorService executor) {
58 63
FunctionRegistry functionRegistry = new FunctionManager();
59 64
DataSourceProviderRegistry dataSourceProviderRegistry = new DataSourceProviderManager();
60 65
DataRetrieverChainDefinitionRegistry dataRetrieverChainDefinitionRegistry = new DataRetrieverChainDefinitionManager();
61 66
AggregationProcessorDefinitionRegistry aggregationProcessorDefinitionRegistry = new AggregationProcessorDefinitionManager();
62 67
QueryDefinitionDTORegistry queryDefinitionRegistry = new QueryDefinitionDTOManager();
63
- return new DataMiningServerImpl(ConcurrencyTestsUtil.getExecutor(), functionRegistry,
68
+ return new DataMiningServerImpl(executor, functionRegistry,
64 69
dataSourceProviderRegistry,
65 70
dataRetrieverChainDefinitionRegistry,
66 71
aggregationProcessorDefinitionRegistry,
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/test/util/components/StatefulBlockingInstruction.java
... ...
@@ -0,0 +1,58 @@
1
+package com.sap.sse.datamining.test.util.components;
2
+
3
+import com.sap.sse.datamining.components.ProcessorInstructionHandler;
4
+import com.sap.sse.datamining.impl.components.ProcessorInstructionPriority;
5
+
6
+public class StatefulBlockingInstruction<ResultType> extends StatefulProcessorInstruction<ResultType> {
7
+
8
+ protected final long stepDuration;
9
+ protected final int numberOfSteps;
10
+ protected final ResultType result;
11
+
12
+ private boolean computeResultWasAborted;
13
+
14
+ public StatefulBlockingInstruction(ProcessorInstructionHandler<ResultType> handler, long stepDuration, int numberOfSteps) {
15
+ this(handler, 0, stepDuration, numberOfSteps, null);
16
+ }
17
+
18
+ public StatefulBlockingInstruction(ProcessorInstructionHandler<ResultType> handler, ProcessorInstructionPriority priority, long stepDuration, int numberOfSteps, ResultType result) {
19
+ this(handler, priority.asIntValue(), stepDuration, numberOfSteps, result);
20
+ }
21
+
22
+ public StatefulBlockingInstruction(ProcessorInstructionHandler<ResultType> handler, int priority, long stepDuration, int numberOfSteps, ResultType result) {
23
+ super(handler, priority);
24
+ this.stepDuration = stepDuration;
25
+ this.numberOfSteps = numberOfSteps;
26
+ this.result = result;
27
+ }
28
+
29
+ @Override
30
+ protected ResultType internalComputeResult() throws Exception {
31
+ if (getTotalBlockDuration() > 0) {
32
+ actionBeforeBlock();
33
+ for (int i = 0; i < numberOfSteps; i++) {
34
+ if (isAborted()) {
35
+ actionBeforeAbort();
36
+ computeResultWasAborted = true;
37
+ break;
38
+ }
39
+ Thread.sleep(stepDuration);
40
+ }
41
+ actionAfterBlock();
42
+ }
43
+ return result;
44
+ }
45
+
46
+ protected void actionBeforeBlock() { }
47
+ protected void actionBeforeAbort() { }
48
+ protected void actionAfterBlock() { }
49
+
50
+ public long getTotalBlockDuration() {
51
+ return stepDuration * numberOfSteps;
52
+ }
53
+
54
+ public boolean computeResultWasAborted() {
55
+ return computeResultWasAborted;
56
+ }
57
+
58
+}
... ...
\ No newline at end of file
java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/test/util/components/StatefulProcessorInstruction.java
... ...
@@ -0,0 +1,54 @@
1
+package com.sap.sse.datamining.test.util.components;
2
+
3
+import com.sap.sse.datamining.components.ProcessorInstructionHandler;
4
+import com.sap.sse.datamining.impl.components.AbstractProcessorInstruction;
5
+import com.sap.sse.datamining.impl.components.ProcessorInstructionPriority;
6
+
7
+public abstract class StatefulProcessorInstruction<ResultType> extends AbstractProcessorInstruction<ResultType> {
8
+
9
+ private boolean runWasCalled;
10
+ private boolean computeResultWasCalled;
11
+ private boolean computeResultWasFinished;
12
+
13
+ public StatefulProcessorInstruction(ProcessorInstructionHandler<ResultType> processor, int priority) {
14
+ super(processor, priority);
15
+ }
16
+
17
+ public StatefulProcessorInstruction(ProcessorInstructionHandler<ResultType> handler,
18
+ ProcessorInstructionPriority priority) {
19
+ super(handler, priority);
20
+ }
21
+
22
+ public StatefulProcessorInstruction(ProcessorInstructionHandler<ResultType> handler) {
23
+ super(handler);
24
+ }
25
+
26
+ @Override
27
+ public void run() {
28
+ runWasCalled = true;
29
+ super.run();
30
+ }
31
+
32
+ @Override
33
+ protected ResultType computeResult() throws Exception {
34
+ computeResultWasCalled = true;
35
+ ResultType result = internalComputeResult();
36
+ computeResultWasFinished = true;
37
+ return result;
38
+ }
39
+
40
+ protected abstract ResultType internalComputeResult() throws Exception;
41
+
42
+ public boolean runWasCalled() {
43
+ return runWasCalled;
44
+ }
45
+
46
+ public boolean computeResultWasCalled() {
47
+ return computeResultWasCalled;
48
+ }
49
+
50
+ public boolean computeResultWasFinished() {
51
+ return computeResultWasFinished;
52
+ }
53
+
54
+}
java/com.sap.sse.datamining.ui/.project
... ...
@@ -21,12 +21,12 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
24
+ <name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
25 25
<arguments>
26 26
</arguments>
27 27
</buildCommand>
28 28
<buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
29
+ <name>com.gwtplugins.gwt.eclipse.core.gwtProjectValidator</name>
30 30
<arguments>
31 31
</arguments>
32 32
</buildCommand>
... ...
@@ -34,6 +34,6 @@
34 34
<natures>
35 35
<nature>org.eclipse.pde.PluginNature</nature>
36 36
<nature>org.eclipse.jdt.core.javanature</nature>
37
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
37
+ <nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
38 38
</natures>
39 39
</projectDescription>
java/com.sap.sse.datamining.ui/META-INF/MANIFEST.MF
... ...
@@ -17,7 +17,6 @@ Export-Package: com.sap.sse.datamining.ui.client,
17 17
com.sap.sse.datamining.ui.client.presentation,
18 18
com.sap.sse.datamining.ui.client.presentation.dataproviders,
19 19
com.sap.sse.datamining.ui.client.selection,
20
- com.sap.sse.datamining.ui.client.selection.filter,
21 20
com.sap.sse.datamining.ui.client.settings
22 21
Bundle-ActivationPolicy: lazy
23 22
Automatic-Module-Name: com.sap.sse.datamining.ui
java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/selection/DimensionFilterSelectionProvider.java
... ...
@@ -0,0 +1,371 @@
1
+package com.sap.sse.datamining.ui.client.selection;
2
+
3
+import java.io.Serializable;
4
+import java.util.ArrayList;
5
+import java.util.Collection;
6
+import java.util.Collections;
7
+import java.util.HashMap;
8
+import java.util.HashSet;
9
+import java.util.List;
10
+import java.util.Map;
11
+import java.util.Set;
12
+
13
+import com.google.gwt.cell.client.CheckboxCell;
14
+import com.google.gwt.core.client.Scheduler;
15
+import com.google.gwt.core.shared.GWT;
16
+import com.google.gwt.dom.client.BrowserEvents;
17
+import com.google.gwt.dom.client.NativeEvent;
18
+import com.google.gwt.dom.client.Style.TextAlign;
19
+import com.google.gwt.dom.client.Style.Unit;
20
+import com.google.gwt.i18n.client.LocaleInfo;
21
+import com.google.gwt.user.cellview.client.Column;
22
+import com.google.gwt.user.cellview.client.DataGrid;
23
+import com.google.gwt.user.cellview.client.TextColumn;
24
+import com.google.gwt.user.client.ui.DockLayoutPanel;
25
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;
26
+import com.google.gwt.user.client.ui.HasVerticalAlignment;
27
+import com.google.gwt.user.client.ui.HorizontalPanel;
28
+import com.google.gwt.user.client.ui.Image;
29
+import com.google.gwt.user.client.ui.Label;
30
+import com.google.gwt.user.client.ui.LayoutPanel;
31
+import com.google.gwt.user.client.ui.ToggleButton;
32
+import com.google.gwt.user.client.ui.Widget;
33
+import com.google.gwt.view.client.CellPreviewEvent;
34
+import com.google.gwt.view.client.DefaultSelectionEventManager;
35
+import com.google.gwt.view.client.DefaultSelectionEventManager.EventTranslator;
36
+import com.google.gwt.view.client.DefaultSelectionEventManager.SelectAction;
37
+import com.google.gwt.view.client.ListDataProvider;
38
+import com.google.gwt.view.client.MultiSelectionModel;
39
+import com.google.gwt.view.client.SelectionChangeEvent;
40
+import com.sap.sse.common.settings.SerializableSettings;
41
+import com.sap.sse.common.util.NaturalComparator;
42
+import com.sap.sse.datamining.shared.DataMiningSession;
43
+import com.sap.sse.datamining.shared.GroupKey;
44
+import com.sap.sse.datamining.shared.impl.GenericGroupKey;
45
+import com.sap.sse.datamining.shared.impl.dto.DataRetrieverLevelDTO;
46
+import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
47
+import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO;
48
+import com.sap.sse.datamining.ui.client.DataMiningServiceAsync;
49
+import com.sap.sse.datamining.ui.client.DataRetrieverChainDefinitionProvider;
50
+import com.sap.sse.datamining.ui.client.FilterSelectionChangedListener;
51
+import com.sap.sse.datamining.ui.client.FilterSelectionProvider;
52
+import com.sap.sse.datamining.ui.client.ManagedDataMiningQueriesCounter;
53
+import com.sap.sse.datamining.ui.client.execution.ManagedDataMiningQueryCallback;
54
+import com.sap.sse.datamining.ui.client.execution.SimpleManagedDataMiningQueriesCounter;
55
+import com.sap.sse.datamining.ui.client.resources.DataMiningDataGridResources;
56
+import com.sap.sse.datamining.ui.client.resources.DataMiningResources;
57
+import com.sap.sse.gwt.client.ErrorReporter;
58
+import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
59
+import com.sap.sse.gwt.client.panels.AbstractFilterablePanel;
60
+import com.sap.sse.gwt.client.shared.components.AbstractComponent;
61
+import com.sap.sse.gwt.client.shared.components.Component;
62
+import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
63
+import com.sap.sse.gwt.client.shared.settings.ComponentContext;
64
+
65
+public class DimensionFilterSelectionProvider extends AbstractComponent<SerializableSettings> {
66
+
67
+ private static final DataMiningResources resources = GWT.create(DataMiningResources.class);
68
+ private static final NaturalComparator NaturalComparator = new NaturalComparator();
69
+
70
+ private final DataMiningServiceAsync dataMiningService;
71
+ private final ErrorReporter errorReporter;
72
+ private final DataMiningSession session;
73
+ private final ManagedDataMiningQueriesCounter counter;
74
+ private final Set<FilterSelectionChangedListener> listeners;
75
+
76
+ private final DataRetrieverChainDefinitionProvider retrieverChainProvider;
77
+ private final FilterSelectionProvider filterSelectionProvider;
78
+
79
+ private final DataRetrieverLevelDTO retrieverLevel;
80
+ private final FunctionDTO dimension;
81
+ private final Set<Serializable> selectionToBeApplied;
82
+
83
+ private final DockLayoutPanel mainPanel;
84
+ private final AbstractFilterablePanel<Serializable> filterPanel;
85
+ private final LayoutPanel contentContainer;
86
+ private final SimpleBusyIndicator busyIndicator;
87
+
88
+ private final ListDataProvider<Serializable> filteredData;
89
+ private final MultiSelectionModel<Serializable> selectionModel;
90
+ private final DataGrid<Serializable> dataGrid;
91
+ private final Column<Serializable, Boolean> checkboxColumn;
92
+
93
+ public DimensionFilterSelectionProvider(Component<?> parent, ComponentContext<?> componentContext, DataMiningServiceAsync dataMiningService,
94
+ ErrorReporter errorReporter, DataMiningSession session, DataRetrieverChainDefinitionProvider retrieverChainProvider,
95
+ FilterSelectionProvider filterSelectionProvider, DataRetrieverLevelDTO retrieverLevel, FunctionDTO dimension) {
96
+ super(parent, componentContext);
97
+ this.dataMiningService = dataMiningService;
98
+ this.errorReporter = errorReporter;
99
+ this.session = session;
100
+ this.retrieverChainProvider = retrieverChainProvider;
101
+ this.filterSelectionProvider = filterSelectionProvider;
102
+ this.retrieverLevel = retrieverLevel;
103
+ this.dimension = dimension;
104
+
105
+ counter = new SimpleManagedDataMiningQueriesCounter();
106
+ listeners = new HashSet<>();
107
+ selectionToBeApplied = new HashSet<>();
108
+
109
+ DataMiningDataGridResources dataGridResources = GWT.create(DataMiningDataGridResources.class);
110
+ dataGrid = new DataGrid<>(Integer.MAX_VALUE, dataGridResources);
111
+ dataGrid.setAutoHeaderRefreshDisabled(true);
112
+ dataGrid.setAutoFooterRefreshDisabled(true);
113
+ dataGrid.addStyleName("dataMiningBorderTop");
114
+
115
+ filteredData = new ListDataProvider<Serializable>(this::elementAsString);
116
+ filterPanel = new AbstractFilterablePanel<Serializable>(null, dataGrid, filteredData) {
117
+ @Override
118
+ public Iterable<String> getSearchableStrings(Serializable element) {
119
+ return Collections.singleton(elementAsString(element));
120
+ }
121
+ };
122
+ filterPanel.setWidth("100%");
123
+ filterPanel.setSpacing(1);
124
+ filterPanel.getTextBox().setWidth("100%");
125
+ filterPanel.getAllListDataProvider().addDataDisplay(dataGrid);
126
+
127
+ selectionModel = new MultiSelectionModel<>(this::elementAsString);
128
+ selectionModel.addSelectionChangeHandler(this::selectionChanged);
129
+ dataGrid.setSelectionModel(selectionModel, DefaultSelectionEventManager.createCustomManager(new CustomCheckboxEventTranslator()));
130
+
131
+ checkboxColumn = new Column<Serializable, Boolean>(new CheckboxCell(true, false)) {
132
+ @Override
133
+ public Boolean getValue(Serializable object) {
134
+ return selectionModel.isSelected(object);
135
+ }
136
+ };
137
+ dataGrid.addColumn(checkboxColumn);
138
+ TextColumn<Serializable> contentColumn = new TextColumn<Serializable>() {
139
+ @Override
140
+ public String getValue(Serializable element) {
141
+ return elementAsString(element);
142
+ }
143
+ };
144
+ contentColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
145
+ dataGrid.addColumn(contentColumn);
146
+
147
+ busyIndicator = new SimpleBusyIndicator(false, 0.85f);
148
+ busyIndicator.getElement().getStyle().setTextAlign(TextAlign.CENTER);
149
+
150
+ contentContainer = new LayoutPanel();
151
+ contentContainer.add(busyIndicator);
152
+ contentContainer.setWidgetTopBottom(busyIndicator, 10, Unit.PX, 10, Unit.PX);
153
+ contentContainer.setWidgetLeftRight(busyIndicator, 10, Unit.PX, 10, Unit.PX);
154
+
155
+ mainPanel = new DockLayoutPanel(Unit.PX);
156
+ mainPanel.addNorth(createHeaderPanel(), 40);
157
+ mainPanel.addNorth(filterPanel, 35);
158
+ mainPanel.setWidgetHidden(filterPanel, true);
159
+ mainPanel.add(contentContainer);
160
+
161
+ updateContent(null);
162
+ }
163
+
164
+ private Widget createHeaderPanel() {
165
+ HorizontalPanel headerPanel = new HorizontalPanel();
166
+ headerPanel.setSpacing(2);
167
+ headerPanel.setWidth("100%");
168
+ headerPanel.setHeight("100%");
169
+ headerPanel.addStyleName("dimensionFilterSelectionHeader");
170
+ headerPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
171
+
172
+ Label headerLabel = new Label(dimension.getDisplayName());
173
+ headerPanel.add(headerLabel);
174
+ headerPanel.setCellWidth(headerLabel, "100%");
175
+ headerPanel.setCellHorizontalAlignment(headerLabel, HasHorizontalAlignment.ALIGN_CENTER);
176
+
177
+ ToggleButton toggleFilterButton = new ToggleButton(new Image(resources.searchIcon()));
178
+ toggleFilterButton.addClickHandler(e -> {
179
+ boolean enabled = toggleFilterButton.isDown();
180
+ mainPanel.setWidgetHidden(filterPanel, !enabled);
181
+ if (enabled) {
182
+ Scheduler.get().scheduleDeferred(() -> {
183
+ filterPanel.getTextBox().setFocus(true);
184
+ filterPanel.getTextBox().selectAll();
185
+ });
186
+ }
187
+
188
+ ListDataProvider<Serializable> oldProvider = enabled ? filterPanel.getAllListDataProvider(): filteredData;
189
+ ListDataProvider<Serializable> newProvider = enabled ? filteredData : filterPanel.getAllListDataProvider();
190
+ oldProvider.removeDataDisplay(dataGrid);
191
+ newProvider.addDataDisplay(dataGrid);
192
+ });
193
+ headerPanel.add(toggleFilterButton);
194
+ headerPanel.setCellHorizontalAlignment(toggleFilterButton, HasHorizontalAlignment.ALIGN_RIGHT);
195
+
196
+ return headerPanel;
197
+ }
198
+
199
+ public void updateContent(Runnable callback) {
200
+ HashMap<DataRetrieverLevelDTO,SerializableSettings> retrieverSettings = retrieverChainProvider.getRetrieverSettings();
201
+ HashMap<DataRetrieverLevelDTO, HashMap<FunctionDTO, HashSet<? extends Serializable>>> filterSelection = filterSelectionProvider.getSelection();
202
+ if (filterSelection.containsKey(retrieverLevel)) {
203
+ filterSelection.get(retrieverLevel).remove(dimension);
204
+ }
205
+ HashSet<FunctionDTO> dimensions = new HashSet<>();
206
+ dimensions.add(dimension);
207
+
208
+ counter.increase();
209
+ contentContainer.remove(dataGrid);
210
+ busyIndicator.setBusy(true);
211
+ dataMiningService.getDimensionValuesFor(session, retrieverChainProvider.getDataRetrieverChainDefinition(), retrieverLevel, dimensions,
212
+ retrieverSettings, filterSelection, LocaleInfo.getCurrentLocale().getLocaleName(), new ManagedDataMiningQueryCallback<HashSet<Object>>(counter) {
213
+ @SuppressWarnings("unchecked")
214
+ @Override
215
+ protected void handleSuccess(QueryResultDTO<HashSet<Object>> result) {
216
+ Map<GroupKey, HashSet<Object>> results = result.getResults();
217
+ List<Serializable> content = new ArrayList<>();
218
+
219
+ if (!results.isEmpty()) {
220
+ GroupKey contentKey = new GenericGroupKey<FunctionDTO>(dimension);
221
+ content.addAll((Collection<? extends Serializable>) results.get(contentKey));
222
+ content.sort((o1, o2) -> NaturalComparator.compare(o1.toString(), o2.toString()));
223
+ }
224
+
225
+ busyIndicator.setBusy(false);
226
+ filterPanel.updateAll(content);
227
+ contentContainer.add(dataGrid);
228
+
229
+ internalSetSelection(!selectionToBeApplied.isEmpty() ? selectionToBeApplied : selectionModel.getSelectedSet());
230
+ selectionToBeApplied.clear();
231
+
232
+ if (callback != null) {
233
+ callback.run();
234
+ }
235
+ }
236
+ @Override
237
+ protected void handleFailure(Throwable caught) {
238
+ errorReporter.reportError("Error fetching the dimension values of " + dimension + ": " + caught.getMessage());
239
+ }
240
+ });
241
+ }
242
+
243
+ private String elementAsString(Object element) {
244
+ return element.toString();
245
+ }
246
+
247
+ private void selectionChanged(SelectionChangeEvent event) {
248
+ notifyListeners();
249
+ }
250
+
251
+ public HashSet<? extends Serializable> getSelection() {
252
+ return new HashSet<>(selectionModel.getSelectedSet());
253
+ }
254
+
255
+ public void setSelection(Iterable<? extends Serializable> items) {
256
+ selectionToBeApplied.clear();
257
+ for (Serializable item : items) {
258
+ selectionToBeApplied.add(item);
259
+ }
260
+
261
+ if (!busyIndicator.isBusy()) {
262
+ internalSetSelection(selectionToBeApplied);
263
+ selectionToBeApplied.clear();
264
+ }
265
+ }
266
+
267
+ private void internalSetSelection(Set<? extends Serializable> selection) {
268
+ clearSelection();
269
+ if (!selection.isEmpty()) {
270
+ for (Serializable item : filterPanel.getAll()) {
271
+ if (selection.contains(item)) {
272
+ selectionModel.setSelected(item, true);
273
+ }
274
+ }
275
+ }
276
+ }
277
+
278
+ public void clearSelection() {
279
+ selectionModel.clear();
280
+ }
281
+
282
+ public void addListener(FilterSelectionChangedListener listener) {
283
+ listeners.add(listener);
284
+ }
285
+
286
+ private void notifyListeners() {
287
+ for (FilterSelectionChangedListener listener : listeners) {
288
+ listener.selectionChanged();
289
+ }
290
+ }
291
+
292
+ @Override
293
+ public Widget getEntryWidget() {
294
+ return mainPanel;
295
+ }
296
+
297
+ @Override
298
+ public String getId() {
299
+ return "DimensionFilterSelectionProvider";
300
+ }
301
+
302
+ @Override
303
+ public String getLocalizedShortName() {
304
+ return getClass().getSimpleName();
305
+ }
306
+
307
+ @Override
308
+ public boolean isVisible() {
309
+ return getEntryWidget().isVisible();
310
+ }
311
+
312
+ @Override
313
+ public void setVisible(boolean visibility) {
314
+ getEntryWidget().setVisible(visibility);
315
+ }
316
+
317
+ @Override
318
+ public boolean hasSettings() {
319
+ return false;
320
+ }
321
+
322
+ @Override
323
+ public SettingsDialogComponent<SerializableSettings> getSettingsDialogComponent(SerializableSettings settings) {
324
+ return null;
325
+ }
326
+
327
+ @Override
328
+ public SerializableSettings getSettings() {
329
+ return null;
330
+ }
331
+
332
+ @Override
333
+ public void updateSettings(SerializableSettings newSettings) {
334
+ // no-op
335
+ }
336
+
337
+ @Override
338
+ public String getDependentCssClassName() {
339
+ return "dimensionFilterSelectionProvider";
340
+ }
341
+
342
+ private class CustomCheckboxEventTranslator implements EventTranslator<Serializable> {
343
+
344
+ @Override
345
+ public boolean clearCurrentSelection(CellPreviewEvent<Serializable> event) {
346
+ return !isCheckboxColumn(event.getColumn());
347
+ }
348
+
349
+ @Override
350
+ public SelectAction translateSelectionEvent(CellPreviewEvent<Serializable> event) {
351
+ NativeEvent nativeEvent = event.getNativeEvent();
352
+ if (BrowserEvents.CLICK.equals(nativeEvent.getType())) {
353
+ if (nativeEvent.getCtrlKey()) {
354
+ Serializable value = event.getValue();
355
+ selectionModel.setSelected(value, !selectionModel.isSelected(value));
356
+ return SelectAction.IGNORE;
357
+ }
358
+ if (!selectionModel.getSelectedSet().isEmpty() && !isCheckboxColumn(event.getColumn())) {
359
+ return SelectAction.DEFAULT;
360
+ }
361
+ }
362
+ return SelectAction.TOGGLE;
363
+ }
364
+
365
+ private boolean isCheckboxColumn(int columnIndex) {
366
+ return columnIndex == dataGrid.getColumnIndex(checkboxColumn);
367
+ }
368
+
369
+ }
370
+
371
+}
java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/selection/HierarchicalDimensionListFilterSelectionProvider.java
... ...
@@ -0,0 +1,618 @@
1
+package com.sap.sse.datamining.ui.client.selection;
2
+
3
+import java.io.Serializable;
4
+import java.util.ArrayList;
5
+import java.util.Collection;
6
+import java.util.Collections;
7
+import java.util.HashMap;
8
+import java.util.HashSet;
9
+import java.util.Iterator;
10
+import java.util.List;
11
+import java.util.Map;
12
+import java.util.Map.Entry;
13
+import java.util.Objects;
14
+import java.util.Set;
15
+import java.util.stream.Collectors;
16
+
17
+import com.google.gwt.cell.client.CheckboxCell;
18
+import com.google.gwt.core.client.GWT;
19
+import com.google.gwt.dom.builder.shared.TableCellBuilder;
20
+import com.google.gwt.dom.builder.shared.TableRowBuilder;
21
+import com.google.gwt.dom.client.Element;
22
+import com.google.gwt.dom.client.NativeEvent;
23
+import com.google.gwt.dom.client.NodeList;
24
+import com.google.gwt.dom.client.Style.Unit;
25
+import com.google.gwt.dom.client.TableCellElement;
26
+import com.google.gwt.dom.client.TableRowElement;
27
+import com.google.gwt.i18n.client.LocaleInfo;
28
+import com.google.gwt.user.cellview.client.AbstractCellTable;
29
+import com.google.gwt.user.cellview.client.Column;
30
+import com.google.gwt.user.cellview.client.DataGrid;
31
+import com.google.gwt.user.cellview.client.RowHoverEvent;
32
+import com.google.gwt.user.cellview.client.TextColumn;
33
+import com.google.gwt.user.client.rpc.AsyncCallback;
34
+import com.google.gwt.user.client.ui.DockLayoutPanel;
35
+import com.google.gwt.user.client.ui.Label;
36
+import com.google.gwt.user.client.ui.ScrollPanel;
37
+import com.google.gwt.user.client.ui.Widget;
38
+import com.google.gwt.view.client.CellPreviewEvent;
39
+import com.google.gwt.view.client.DefaultSelectionEventManager;
40
+import com.google.gwt.view.client.DefaultSelectionEventManager.EventTranslator;
41
+import com.google.gwt.view.client.DefaultSelectionEventManager.SelectAction;
42
+import com.google.gwt.view.client.ListDataProvider;
43
+import com.google.gwt.view.client.MultiSelectionModel;
44
+import com.google.gwt.view.client.SelectionChangeEvent;
45
+import com.sap.sse.common.settings.SerializableSettings;
46
+import com.sap.sse.datamining.shared.DataMiningSession;
47
+import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
48
+import com.sap.sse.datamining.shared.impl.dto.DataRetrieverChainDefinitionDTO;
49
+import com.sap.sse.datamining.shared.impl.dto.DataRetrieverLevelDTO;
50
+import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
51
+import com.sap.sse.datamining.shared.impl.dto.ReducedDimensionsDTO;
52
+import com.sap.sse.datamining.ui.client.DataMiningServiceAsync;
53
+import com.sap.sse.datamining.ui.client.DataRetrieverChainDefinitionProvider;
54
+import com.sap.sse.datamining.ui.client.FilterSelectionChangedListener;
55
+import com.sap.sse.datamining.ui.client.FilterSelectionPresenter;
56
+import com.sap.sse.datamining.ui.client.FilterSelectionProvider;
57
+import com.sap.sse.datamining.ui.client.StringMessages;
58
+import com.sap.sse.datamining.ui.client.presentation.PlainFilterSelectionPresenter;
59
+import com.sap.sse.datamining.ui.client.resources.DataMiningDataGridResources;
60
+import com.sap.sse.datamining.ui.client.resources.DataMiningDataGridResources.DataMiningDataGridStyle;
61
+import com.sap.sse.gwt.client.ErrorReporter;
62
+import com.sap.sse.gwt.client.celltable.BaseCellTableBuilder;
63
+import com.sap.sse.gwt.client.panels.AbstractFilterablePanel;
64
+import com.sap.sse.gwt.client.shared.components.AbstractComponent;
65
+import com.sap.sse.gwt.client.shared.components.Component;
66
+import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
67
+import com.sap.sse.gwt.client.shared.settings.ComponentContext;
68
+
69
+public class HierarchicalDimensionListFilterSelectionProvider extends AbstractComponent<SerializableSettings> implements FilterSelectionProvider {
70
+
71
+ private final static String DimensionListSubheaderAttribute = "subheader";
72
+
73
+ private static final Unit LayoutUnit = Unit.PX;
74
+ private static final double SelectionPresenterHeight = 100;
75
+ private static final double DimensionSelectionWidth = 300;
76
+ private static final double DimensionSelectionHeaderHeight = 40;
77
+ private static final double FilterSelectionTableWidth = 250;
78
+
79
+ private final DataMiningSession session;
80
+ private final DataMiningServiceAsync dataMiningService;
81
+ private final ErrorReporter errorReporter;
82
+ private final DataRetrieverChainDefinitionProvider retrieverChainProvider;
83
+ private final Set<FilterSelectionChangedListener> listeners;
84
+
85
+ private boolean isAwaitingReload;
86
+ private DataRetrieverChainDefinitionDTO retrieverChain;
87
+ private ReducedDimensionsDTO reducedDimensions;
88
+ private final List<DimensionWithContext> allFilterDimensions;
89
+ private final ListDataProvider<DimensionWithContext> filteredFilterDimensions;
90
+
91
+ private final DockLayoutPanel mainPanel;
92
+
93
+ private final AbstractFilterablePanel<DimensionWithContext> filterFilterDimensionsPanel;
94
+ private final MultiSelectionModel<DimensionWithContext> filterDimensionSelectionModel;
95
+ private final DataGrid<DimensionWithContext> filterDimensionsList;
96
+ private final Column<DimensionWithContext, Boolean> checkboxColumn;
97
+
98
+ private final DockLayoutPanel dimensionFilterSelectionProvidersPanel;
99
+ private final Map<DimensionWithContext, DimensionFilterSelectionProvider> dimensionFilterSelectionProviders;
100
+ private boolean updateInProgress;
101
+
102
+ private final FilterSelectionPresenter filterSelectionPresenter;
103
+ private final ScrollPanel filterSelectionPresenterContainer;
104
+
105
+ public HierarchicalDimensionListFilterSelectionProvider(Component<?> parent, ComponentContext<?> context,
106
+ DataMiningSession session, StringMessages stringMessages,
107
+ DataMiningServiceAsync dataMiningService, ErrorReporter errorReporter,
108
+ DataRetrieverChainDefinitionProvider retrieverChainProvider) {
109
+ super(parent, context);
110
+ this.session = session;
111
+ this.dataMiningService = dataMiningService;
112
+ this.errorReporter = errorReporter;
113
+ this.retrieverChainProvider = retrieverChainProvider;
114
+ retrieverChainProvider.addDataRetrieverChainDefinitionChangedListener(this);
115
+
116
+ listeners = new HashSet<>();
117
+ isAwaitingReload = false;
118
+ retrieverChain = null;
119
+ allFilterDimensions = new ArrayList<>();
120
+ filteredFilterDimensions = new ListDataProvider<>();
121
+
122
+ Label filterDimensionsSelectionTitleLabel = new Label(stringMessages.selectDimensionsToFilterBy());
123
+ filterDimensionsSelectionTitleLabel.addStyleName("emphasizedLabel");
124
+ filterDimensionsSelectionTitleLabel.addStyleName("dataMiningMarginLeft");
125
+ filterDimensionsSelectionTitleLabel.addStyleName("filterDimensionsTitleLabel");
126
+
127
+ DataMiningDataGridResources resources = GWT.create(DataMiningDataGridResources.class);
128
+ filterDimensionsList = new DataGrid<>(Integer.MAX_VALUE, resources);
129
+ filterDimensionsList.setAutoHeaderRefreshDisabled(true);
130
+ filterDimensionsList.setAutoFooterRefreshDisabled(true);
131
+ filterDimensionsList.setTableBuilder(new FilterDimensionsListBuilder(filterDimensionsList, resources.dataGridStyle()));
132
+ filteredFilterDimensions.addDataDisplay(filterDimensionsList);
133
+
134
+ filterFilterDimensionsPanel = new AbstractFilterablePanel<DimensionWithContext>(
135
+ null, filterDimensionsList, filteredFilterDimensions)
136
+ {
137
+ @Override
138
+ public Iterable<String> getSearchableStrings(DimensionWithContext dimension) {
139
+ return dimension.getMatchingStrings();
140
+ }
141
+ };
142
+ filterFilterDimensionsPanel.addStyleName("filterFilterDimensionsPanel");
143
+ filterFilterDimensionsPanel.setSpacing(2);
144
+ filterFilterDimensionsPanel.setWidth("100%");
145
+ filterFilterDimensionsPanel.setHeight("100%");
146
+ filterFilterDimensionsPanel.getTextBox().setWidth("100%");
147
+ filterFilterDimensionsPanel.getTextBox().getElement().setPropertyString("placeholder", stringMessages.filterShownDimensions());
148
+
149
+ filterDimensionSelectionModel = new MultiSelectionModel<>();
150
+ filterDimensionSelectionModel.addSelectionChangeHandler(this::selectedFilterDimensionsChanged);
151
+ filterDimensionsList.setSelectionModel(filterDimensionSelectionModel, DefaultSelectionEventManager.createCustomManager(new CustomCheckboxEventTranslator()));
152
+
153
+ checkboxColumn = new Column<DimensionWithContext, Boolean>(new CheckboxCell(true, false)) {
154
+ @Override
155
+ public Boolean getValue(DimensionWithContext object) {
156
+ return filterDimensionSelectionModel.isSelected(object);
157
+ }
158
+ };
159
+ filterDimensionsList.addColumn(checkboxColumn);
160
+ TextColumn<DimensionWithContext> dimensionColumn = new TextColumn<DimensionWithContext>() {
161
+ @Override
162
+ public String getValue(DimensionWithContext object) {
163
+ return object.getDimension().getDisplayName();
164
+ }
165
+ };
166
+ filterDimensionsList.addColumn(dimensionColumn);
167
+
168
+ DockLayoutPanel filterDimensionsSelectionPanel = new DockLayoutPanel(LayoutUnit);
169
+ filterDimensionsSelectionPanel.addNorth(filterDimensionsSelectionTitleLabel, 20);
170
+ filterDimensionsSelectionPanel.addNorth(filterFilterDimensionsPanel, DimensionSelectionHeaderHeight);
171
+ filterDimensionsSelectionPanel.add(filterDimensionsList);
172
+
173
+ dimensionFilterSelectionProviders = new HashMap<>();
174
+ dimensionFilterSelectionProvidersPanel = new DockLayoutPanel(LayoutUnit);
175
+ dimensionFilterSelectionProvidersPanel.addStyleName("dimensionFilterSelectionTablesContainer");
176
+ dimensionFilterSelectionProvidersPanel.addStyleName("dataMiningBorderLeft");
177
+
178
+ filterSelectionPresenter = new PlainFilterSelectionPresenter(this, context, stringMessages, retrieverChainProvider, this);
179
+ filterSelectionPresenter.getEntryWidget().addStyleName("dataMiningMarginLeft");
180
+ filterSelectionPresenterContainer = new ScrollPanel(filterSelectionPresenter.getEntryWidget());
181
+ filterSelectionPresenterContainer.addStyleName("dataMiningBorderTop");
182
+
183
+ mainPanel = new DockLayoutPanel(LayoutUnit);
184
+ mainPanel.addSouth(filterSelectionPresenterContainer, SelectionPresenterHeight);
185
+ mainPanel.setWidgetHidden(filterSelectionPresenterContainer, true);
186
+ mainPanel.addWest(filterDimensionsSelectionPanel, DimensionSelectionWidth);
187
+ mainPanel.add(dimensionFilterSelectionProvidersPanel);
188
+ }
189
+
190
+ @Override
191
+ public void awaitReloadComponents() {
192
+ isAwaitingReload = true;
193
+ }
194
+
195
+ @Override
196
+ public boolean isAwaitingReload() {
197
+ return isAwaitingReload;
198
+ }
199
+
200
+ @Override
201
+ public void reloadComponents() {
202
+ updateFilterDimensions();
203
+ isAwaitingReload = false;
204
+ notifyListeners();
205
+ }
206
+
207
+ @Override
208
+ public void dataRetrieverChainDefinitionChanged(DataRetrieverChainDefinitionDTO newDataRetrieverChainDefinition) {
209
+ if (!Objects.equals(retrieverChain, newDataRetrieverChainDefinition)) {
210
+ retrieverChain = newDataRetrieverChainDefinition;
211
+ if (!isAwaitingReload && retrieverChain != null) {
212
+ updateFilterDimensions();
213
+ } else if (!isAwaitingReload) {
214
+ clearContent();
215
+ }
216
+ }
217
+ }
218
+
219
+ private void updateFilterDimensions() {
220
+ clearContent();
221
+ dataMiningService.getReducedDimensionsMappedByLevelFor(retrieverChain, LocaleInfo.getCurrentLocale().getLocaleName(), new AsyncCallback<ReducedDimensionsDTO>() {
222
+ @Override
223
+ public void onSuccess(ReducedDimensionsDTO result) {
224
+ reducedDimensions = result;
225
+ for (Entry<DataRetrieverLevelDTO, HashSet<FunctionDTO>> entry : reducedDimensions.getReducedDimensions().entrySet()) {
226
+ DataRetrieverLevelDTO retrieverlevel = entry.getKey();
227
+ for (FunctionDTO dimension : entry.getValue()) {
228
+ allFilterDimensions.add(new DimensionWithContext(dimension, retrieverlevel));
229
+ }
230
+ }
231
+ allFilterDimensions.sort(null);
232
+ filterFilterDimensionsPanel.updateAll(allFilterDimensions);
233
+ }
234
+ @Override
235
+ public void onFailure(Throwable caught) {
236
+ errorReporter.reportError("Error fetching the dimensions of the retriever chain from the server: " + caught.getMessage());
237
+ }
238
+ });
239
+ }
240
+
241
+ private void clearContent() {
242
+ reducedDimensions = null;
243
+ allFilterDimensions.clear();
244
+ filterDimensionSelectionModel.clear();
245
+ filterFilterDimensionsPanel.removeAll();
246
+ }
247
+
248
+ @Override
249
+ public void applyQueryDefinition(StatisticQueryDefinitionDTO queryDefinition) {
250
+ HashMap<DataRetrieverLevelDTO, HashMap<FunctionDTO, HashSet<? extends Serializable>>> filterSelection = queryDefinition.getFilterSelection();
251
+ for (DimensionWithContext dimensionWithContext : allFilterDimensions) {
252
+ HashMap<FunctionDTO, HashSet<? extends Serializable>> retrieverLevelSelection = filterSelection.get(dimensionWithContext.getRetrieverLevel());
253
+ if (retrieverLevelSelection != null) {
254
+ HashSet<? extends Serializable> items = retrieverLevelSelection.get(dimensionWithContext.getDimension());
255
+ if (items != null) {
256
+ setSelection(dimensionWithContext, items);
257
+ }
258
+ }
259
+ }
260
+ }
261
+
262
+ @Override
263
+ public void setHighestRetrieverLevelWithFilterDimension(FunctionDTO dimension, Serializable groupKey) {
264
+ FunctionDTO reducedDimension = reducedDimensions == null ? dimension : reducedDimensions.getReducedDimension(dimension);
265
+ Collection<Serializable> items = Collections.singleton(groupKey);
266
+ for (DimensionWithContext dimensionWithContext : allFilterDimensions) {
267
+ if (dimensionWithContext.getDimension().equals(reducedDimension)) {
268
+ setSelection(dimensionWithContext, items);
269
+ break;
270
+ }
271
+ }
272
+ }
273
+
274
+ private void setSelection(DimensionWithContext dimension, Collection<? extends Serializable> items) {
275
+ DimensionFilterSelectionProvider selectionProvider;
276
+ if (filterDimensionSelectionModel.isSelected(dimension)) {
277
+ selectionProvider = dimensionFilterSelectionProviders.get(dimension);
278
+ } else {
279
+ selectionProvider = addDimensionFilterSelectionProvider(dimension);
280
+ filterDimensionSelectionModel.setSelected(dimension, true);
281
+ }
282
+ selectionProvider.setSelection(items);
283
+ }
284
+
285
+ private void selectedFilterDimensionsChanged(SelectionChangeEvent event) {
286
+ Iterable<DimensionWithContext> displayedDimensions = new HashSet<>(dimensionFilterSelectionProviders.keySet());
287
+ for (DimensionWithContext displayedDimension : displayedDimensions) {
288
+ if (!filterDimensionSelectionModel.isSelected(displayedDimension)) {
289
+ removeDimensionFilterSelectionProvider(displayedDimension);
290
+ }
291
+ }
292
+
293
+ for (DimensionWithContext selectedDimension : filterDimensionSelectionModel.getSelectedSet()) {
294
+ if (!dimensionFilterSelectionProviders.containsKey(selectedDimension)) {
295
+ addDimensionFilterSelectionProvider(selectedDimension);
296
+ }
297
+ }
298
+ }
299
+
300
+ private DimensionFilterSelectionProvider addDimensionFilterSelectionProvider(DimensionWithContext dimension) {
301
+ DimensionFilterSelectionProvider selectionProvider = new DimensionFilterSelectionProvider(this, getComponentContext(),
302
+ dataMiningService, errorReporter, session, retrieverChainProvider, this, dimension.getRetrieverLevel(), dimension.getDimension());
303
+ selectionProvider.addListener(() -> filterSelectionChanged(dimension));
304
+ dimensionFilterSelectionProviders.put(dimension, selectionProvider);
305
+
306
+ DimensionWithContext nextDimension = null;
307
+ for (DimensionWithContext displayedDimension : dimensionFilterSelectionProviders.keySet()) {
308
+ if (displayedDimension.compareTo(dimension) > 0 &&
309
+ (nextDimension == null || displayedDimension.compareTo(nextDimension) < 0)) {
310
+ nextDimension = displayedDimension;
311
+ }
312
+ }
313
+ Widget beforeWidget = nextDimension != null ? dimensionFilterSelectionProviders.get(nextDimension).getEntryWidget() : null;
314
+ dimensionFilterSelectionProvidersPanel.insertWest(selectionProvider.getEntryWidget(), FilterSelectionTableWidth, beforeWidget);
315
+
316
+ return selectionProvider;
317
+ }
318
+
319
+ private void removeDimensionFilterSelectionProvider(DimensionWithContext dimension) {
320
+ DimensionFilterSelectionProvider selectionProvider = dimensionFilterSelectionProviders.get(dimension);
321
+ if (selectionProvider != null) {
322
+ selectionProvider.clearSelection();
323
+ dimensionFilterSelectionProviders.remove(dimension);
324
+ dimensionFilterSelectionProvidersPanel.remove(selectionProvider.getEntryWidget());
325
+ dimensionFilterSelectionProvidersPanel.animate(0); // Schedule Layout
326
+ }
327
+ }
328
+
329
+ private void filterSelectionChanged(DimensionWithContext changedDimension) {
330
+ if (!updateInProgress) {
331
+ updateInProgress = true;
332
+ int levelToStartWith = changedDimension.getRetrieverLevel().getLevel();
333
+ List<DimensionWithContext> dimensionsToUpdate = dimensionFilterSelectionProviders.keySet()
334
+ .stream().filter(d -> d.getRetrieverLevel().getLevel() >= levelToStartWith)
335
+ .collect(Collectors.toList());
336
+ updateDimensionFilterSelectionProviders(dimensionsToUpdate.iterator(), changedDimension);
337
+ }
338
+ }
339
+
340
+ private void updateDimensionFilterSelectionProviders(Iterator<DimensionWithContext> dimensionIterator, DimensionWithContext exceptDimension) {
341
+ if (dimensionIterator.hasNext()) {
342
+ DimensionWithContext dimension = dimensionIterator.next();
343
+ if (dimension.equals(exceptDimension)) {
344
+ updateDimensionFilterSelectionProviders(dimensionIterator, exceptDimension);
345
+ } else {
346
+ DimensionFilterSelectionProvider selectionProvider = dimensionFilterSelectionProviders.get(dimension);
347
+ HashSet<? extends Serializable> selectionBefore = selectionProvider.getSelection();
348
+ selectionProvider.updateContent(() -> {
349
+ boolean selectionChanged = !selectionBefore.equals(selectionProvider.getSelection());
350
+ if (selectionChanged) {
351
+ updateInProgress = false;
352
+ filterSelectionChanged(dimension);
353
+ } else {
354
+ updateDimensionFilterSelectionProviders(dimensionIterator, exceptDimension);
355
+ }
356
+ });
357
+ }
358
+ } else {
359
+ updateInProgress = false;
360
+ notifyListeners();
361
+ }
362
+ }
363
+
364
+ @Override
365
+ public HashMap<DataRetrieverLevelDTO, HashMap<FunctionDTO, HashSet<? extends Serializable>>> getSelection() {
366
+ HashMap<DataRetrieverLevelDTO, HashMap<FunctionDTO, HashSet<? extends Serializable>>> filterSelection = new HashMap<>();
367
+ for (DimensionWithContext dimensionWithContext : allFilterDimensions) {
368
+ DataRetrieverLevelDTO retrieverLevel = dimensionWithContext.getRetrieverLevel();
369
+ FunctionDTO dimension = dimensionWithContext.getDimension();
370
+ DimensionFilterSelectionProvider selectionProvider = dimensionFilterSelectionProviders.get(dimensionWithContext);
371
+ if (selectionProvider != null) {
372
+ HashSet<? extends Serializable> dimensionFilterSelection = selectionProvider.getSelection();
373
+ if (!dimensionFilterSelection.isEmpty()) {
374
+ HashMap<FunctionDTO, HashSet<? extends Serializable>> retrieverFilterSelection = filterSelection.get(retrieverLevel);
375
+ if (retrieverFilterSelection == null) {
376
+ retrieverFilterSelection = new HashMap<>();
377
+ filterSelection.put(retrieverLevel, retrieverFilterSelection);
378
+ }
379
+ retrieverFilterSelection.put(dimension, dimensionFilterSelection);
380
+ }
381
+ }
382
+ }
383
+ return filterSelection;
384
+ }
385
+
386
+ @Override
387
+ public void clearSelection() {
388
+ for (DimensionFilterSelectionProvider selectionProvider : dimensionFilterSelectionProviders.values()) {
389
+ selectionProvider.clearSelection();
390
+ }
391
+ }
392
+
393
+ @Override
394
+ public void addSelectionChangedListener(FilterSelectionChangedListener listener) {
395
+ listeners.add(listener);
396
+ }
397
+
398
+ private void notifyListeners() {
399
+ mainPanel.setWidgetHidden(filterSelectionPresenterContainer, getSelection().isEmpty());
400
+ for (FilterSelectionChangedListener listener : listeners) {
401
+ listener.selectionChanged();
402
+ }
403
+ }
404
+
405
+ @Override
406
+ public String getLocalizedShortName() {
407
+ return getClass().getSimpleName();
408
+ }
409
+
410
+ @Override
411
+ public Widget getEntryWidget() {
412
+ return mainPanel;
413
+ }
414
+
415
+ @Override
416
+ public boolean isVisible() {
417
+ return mainPanel.isVisible();
418
+ }
419
+
420
+ @Override
421
+ public void setVisible(boolean visibility) {
422
+ mainPanel.setVisible(visibility);
423
+ }
424
+
425
+ @Override
426
+ public String getDependentCssClassName() {
427
+ return "hierarchicalDimensionListFilterSelectionProvider";
428
+ }
429
+
430
+ @Override
431
+ public boolean hasSettings() {
432
+ return false;
433
+ }
434
+
435
+ @Override
436
+ public SettingsDialogComponent<SerializableSettings> getSettingsDialogComponent(SerializableSettings settings) {
437
+ return null;
438
+ }
439
+
440
+ @Override
441
+ public void updateSettings(SerializableSettings newSettings) {
442
+ // no-op
443
+ }
444
+
445
+ @Override
446
+ public SerializableSettings getSettings() {
447
+ return null;
448
+ }
449
+
450
+ @Override
451
+ public String getId() {
452
+ return "HierarchicalDimensionListFilterSelectionProvider";
453
+ }
454
+
455
+ private static class DimensionWithContext implements Comparable<DimensionWithContext> {
456
+
457
+ private final FunctionDTO dimension;
458
+ private final DataRetrieverLevelDTO retrieverLevel;
459
+ private Collection<String> matchingStrings;
460
+
461
+ public DimensionWithContext(FunctionDTO dimension, DataRetrieverLevelDTO retrieverLevel) {
462
+ this.dimension = dimension;
463
+ this.retrieverLevel = retrieverLevel;
464
+ }
465
+
466
+ public FunctionDTO getDimension() {
467
+ return dimension;
468
+ }
469
+
470
+ public DataRetrieverLevelDTO getRetrieverLevel() {
471
+ return retrieverLevel;
472
+ }
473
+
474
+ public Collection<String> getMatchingStrings() {
475
+ if (matchingStrings == null) {
476
+ matchingStrings = new ArrayList<>(2);
477
+ matchingStrings.add(dimension.getDisplayName());
478
+ matchingStrings.add(retrieverLevel.getRetrievedDataType().getDisplayName());
479
+ }
480
+ return matchingStrings;
481
+ }
482
+
483
+ @Override
484
+ public int compareTo(DimensionWithContext o) {
485
+ int retrieverLevelComparison = retrieverLevel.compareTo(o.retrieverLevel);
486
+ if (retrieverLevelComparison != 0) return retrieverLevelComparison;
487
+
488
+ return dimension.compareTo(o.dimension);
489
+ }
490
+
491
+ @Override
492
+ public int hashCode() {
493
+ final int prime = 31;
494
+ int result = 1;
495
+ result = prime * result + ((dimension == null) ? 0 : dimension.hashCode());
496
+ result = prime * result + ((retrieverLevel == null) ? 0 : retrieverLevel.hashCode());
497
+ return result;
498
+ }
499
+
500
+ @Override
501
+ public boolean equals(Object obj) {
502
+ if (this == obj)
503
+ return true;
504
+ if (obj == null)
505
+ return false;
506
+ if (getClass() != obj.getClass())
507
+ return false;
508
+ DimensionWithContext other = (DimensionWithContext) obj;
509
+ if (dimension == null) {
510
+ if (other.dimension != null)
511
+ return false;
512
+ } else if (!dimension.equals(other.dimension))
513
+ return false;
514
+ if (retrieverLevel == null) {
515
+ if (other.retrieverLevel != null)
516
+ return false;
517
+ } else if (!retrieverLevel.equals(other.retrieverLevel))
518
+ return false;
519
+ return true;
520
+ }
521
+
522
+ }
523
+
524
+ private class FilterDimensionsListBuilder extends BaseCellTableBuilder<DimensionWithContext> {
525
+
526
+ private final String headerStyle;
527
+ private final String subHeaderStyle;
528
+ private final String spacedSubHeaderStyle;
529
+ private final String subHeaderLabelStyle;
530
+ private final String firstColumnStyle;
531
+ private final String hoveredRowStyle;
532
+ private final String hoveredRowCellStyle;
533
+ private final String clearFocus;
534
+
535
+ public FilterDimensionsListBuilder(AbstractCellTable<DimensionWithContext> cellTable, DataMiningDataGridStyle style) {
536
+ super(cellTable);
537
+ headerStyle = style.dataGridHeader();
538
+ subHeaderStyle = style.dataGridSubHeader();
539
+ firstColumnStyle = style.dataGridFirstColumn();
540
+ spacedSubHeaderStyle = style.dataGridSpacedSubHeader();
541
+ hoveredRowStyle = style.dataGridHoveredRow();
542
+ hoveredRowCellStyle = style.dataGridHoveredRowCell();
543
+ subHeaderLabelStyle = style.dataGridSubHeaderLabel();
544
+ clearFocus = style.dataGridClearFocus();
545
+
546
+ cellTable.addRowHoverHandler(new RowHoverEvent.Handler() {
547
+ @Override
548
+ public void onRowHover(RowHoverEvent event) {
549
+ TableRowElement tr = event.getHoveringRow();
550
+ if (tr.hasAttribute(DimensionListSubheaderAttribute)) {
551
+ tr.removeClassName(hoveredRowStyle);
552
+ NodeList<TableCellElement> cells = tr.getCells();
553
+ for (int i = 0; i < cells.getLength(); i++) {
554
+ cells.getItem(i).removeClassName(hoveredRowCellStyle);
555
+ }
556
+ }
557
+ }
558
+ });
559
+ }
560
+
561
+ @Override
562
+ public void buildRowImpl(DimensionWithContext rowValue, int absRowIndex) {
563
+ DataRetrieverLevelDTO valueLevel = rowValue.getRetrieverLevel();
564
+ DataRetrieverLevelDTO previousLevel = null;
565
+ if (absRowIndex > 0) {
566
+ previousLevel = filteredFilterDimensions.getList().get(absRowIndex - 1).getRetrieverLevel();
567
+ }
568
+
569
+ if (!Objects.equals(previousLevel, valueLevel)) {
570
+ StringBuilder styleBuilder = new StringBuilder();
571
+ styleBuilder.append(subHeaderStyle).append(" ").append(headerStyle)
572
+ .append(" ").append(clearFocus);
573
+ if (absRowIndex != 0) {
574
+ styleBuilder.append(" ").append(spacedSubHeaderStyle);
575
+ }
576
+ String style = styleBuilder.toString();
577
+
578
+ String subHeaderText = valueLevel.getRetrievedDataType().getDisplayName();
579
+ TableRowBuilder subHeaderBuilder = startRow().className(clearFocus).attribute(DimensionListSubheaderAttribute, subHeaderText);
580
+ // Additional cell to fix the checkbox column size
581
+ subHeaderBuilder.startTD().className(style + " " + firstColumnStyle).endTD();
582
+ // Actual header cell
583
+ TableCellBuilder headerCellBuilder = subHeaderBuilder.startTD();
584
+ headerCellBuilder.colSpan(this.cellTable.getColumnCount() - 1).className(style);
585
+ headerCellBuilder.startDiv().className(subHeaderLabelStyle).text(subHeaderText).endDiv();
586
+ headerCellBuilder.endTD();
587
+ subHeaderBuilder.endTR();
588
+ }
589
+
590
+ super.buildRowImpl(rowValue, absRowIndex);
591
+ }
592
+ }
593
+
594
+ private class CustomCheckboxEventTranslator implements EventTranslator<DimensionWithContext> {
595
+
596
+ @Override
597
+ public boolean clearCurrentSelection(CellPreviewEvent<DimensionWithContext> event) {
598
+ return false;
599
+ }
600
+
601
+ @Override
602
+ public SelectAction translateSelectionEvent(CellPreviewEvent<DimensionWithContext> event) {
603
+ SelectAction action = SelectAction.TOGGLE;
604
+
605
+ NativeEvent nativeEvent = event.getNativeEvent();
606
+ Element targetRow = Element.as(nativeEvent.getEventTarget());
607
+ while (!TableRowElement.is(targetRow) && targetRow != null) {
608
+ targetRow = targetRow.getParentElement();
609
+ }
610
+ if (targetRow != null && targetRow.hasAttribute(DimensionListSubheaderAttribute)) {
611
+ action = SelectAction.IGNORE;
612
+ }
613
+ return action;
614
+ }
615
+
616
+ }
617
+
618
+}
java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/selection/QueryDefinitionProviderWithControls.java
... ...
@@ -43,7 +43,6 @@ import com.sap.sse.datamining.ui.client.StatisticProvider;
43 43
import com.sap.sse.datamining.ui.client.WithControls;
44 44
import com.sap.sse.datamining.ui.client.developer.PredefinedQueryRunner;
45 45
import com.sap.sse.datamining.ui.client.developer.QueryDefinitionViewer;
46
-import com.sap.sse.datamining.ui.client.selection.filter.HierarchicalDimensionListFilterSelectionProvider;
47 46
import com.sap.sse.datamining.ui.client.settings.AdvancedDataMiningSettings;
48 47
import com.sap.sse.datamining.ui.client.settings.AdvancedDataMiningSettingsDialogComponent;
49 48
import com.sap.sse.gwt.client.ErrorReporter;
java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/selection/SuggestBoxStatisticProvider.java
... ...
@@ -219,24 +219,12 @@ public class SuggestBoxStatisticProvider extends AbstractDataMiningComponent<Com
219 219
awaitingRetrieverChainStatistics--;
220 220
if (awaitingRetrieverChainStatistics == 0) {
221 221
Collections.sort(availableExtractionFunctions);
222
- Map<String, ExtractionFunctionWithContext> displayDuplicates = new HashMap<>();
223
- for (ExtractionFunctionWithContext statistic : availableExtractionFunctions) {
224
- ExtractionFunctionWithContext duplicate = displayDuplicates
225
- .get(statistic.getExtractionFunction().getDisplayName());
226
- if (duplicate == null) {
227
- displayDuplicates.put(statistic.getExtractionFunction().getDisplayName(), statistic);
228
- } else {
229
- statistic.setVerbose(true);
230
- duplicate.setVerbose(true);
231
- }
232
- }
233 222
extractionFunctionSuggestBox.setSelectableValues(availableExtractionFunctions);
234 223
235 224
// TODO Do not pre-select the first element. The other UI components have to be able to handle "empty content"
236 225
ExtractionFunctionWithContext currentValue = extractionFunctionSuggestBox.getExtractionFunction();
237 226
ExtractionFunctionWithContext valueToBeSelected = availableExtractionFunctions.contains(currentValue)
238 227
? currentValue : Util.first(availableExtractionFunctions);
239
- extractionFunctionSuggestBox.getValueBox().setValue(valueToBeSelected.getDisplayString(), false);
240 228
extractionFunctionSuggestBox.setExtractionFunction(valueToBeSelected);
241 229
}
242 230
}
... ...
@@ -377,18 +365,9 @@ public class SuggestBoxStatisticProvider extends AbstractDataMiningComponent<Com
377 365
if (index != -1) {
378 366
statistic = availableExtractionFunctions.get(index);
379 367
} else {
380
- String displayName = extractionFunction.getDisplayName();
381
- for (ExtractionFunctionWithContext availableStatistic : availableExtractionFunctions) {
382
- if (availableStatistic.getExtractionFunction().getDisplayName().equals(displayName)) {
383
- statistic.setVerbose(true);
384
- availableStatistic.setVerbose(true);
385
- }
386
- }
387 368
availableExtractionFunctions.add(statistic);
388
- extractionFunctionSuggestBox.setSelectableValues(availableExtractionFunctions);
389 369
}
390 370
391
- extractionFunctionSuggestBox.getValueBox().setValue(statistic.getDisplayString(), false);
392 371
extractionFunctionSuggestBox.setExtractionFunction(statistic);
393 372
aggregatorListBox.setValue(queryDefinition.getAggregatorDefinition());
394 373
}
... ...
@@ -488,7 +467,6 @@ public class SuggestBoxStatisticProvider extends AbstractDataMiningComponent<Com
488 467
private final DataRetrieverChainDefinitionDTO retrieverChain;
489 468
private final FunctionDTO extractionFunction;
490 469
private final Collection<String> matchingStrings;
491
- private boolean verbose;
492 470
493 471
public ExtractionFunctionWithContext(DataRetrieverChainDefinitionDTO retrieverChain,
494 472
FunctionDTO extractionFunction) {
... ...
@@ -511,30 +489,13 @@ public class SuggestBoxStatisticProvider extends AbstractDataMiningComponent<Com
511 489
return matchingStrings;
512 490
}
513 491
514
- public boolean isVerbose() {
515
- return verbose;
516
- }
517
-
518
- public void setVerbose(boolean verbose) {
519
- this.verbose = verbose;
520
- }
521
-
522
- public String getDisplayString() {
523
- StringBuilder builder = new StringBuilder(extractionFunction.getDisplayName());
524
- if (isVerbose()) {
525
- builder.append(" (").append(getDataMiningStringMessages().basedOn()).append(" ")
526
- .append(retrieverChain.getName()).append(")");
527
- }
528
- return builder.toString();
529
- }
530
-
531 492
@Override
532 493
public int compareTo(ExtractionFunctionWithContext o) {
533
- int comparedDisplayName = extractionFunction.getDisplayName()
534
- .compareTo(o.getExtractionFunction().getDisplayName());
535
- if (comparedDisplayName != 0)
494
+ String otherDisplayName = o.getExtractionFunction().getDisplayName();
495
+ int comparedDisplayName = extractionFunction.getDisplayName().compareToIgnoreCase(otherDisplayName);
496
+ if (comparedDisplayName != 0) {
536 497
return comparedDisplayName;
537
-
498
+ }
538 499
return retrieverChain.compareTo(o.getRetrieverChain());
539 500
}
540 501
... ...
@@ -597,12 +558,12 @@ public class SuggestBoxStatisticProvider extends AbstractDataMiningComponent<Com
597 558
598 559
@Override
599 560
protected String createSuggestionKeyString(ExtractionFunctionWithContext value) {
600
- return value.getDisplayString();
561
+ return value.getExtractionFunction().getDisplayName();
601 562
}
602 563
603 564
@Override
604 565
protected String createSuggestionAdditionalDisplayString(ExtractionFunctionWithContext value) {
605
- return null;
566
+ return value.getRetrieverChain().getName();
606 567
}
607 568
}, new ScrollableSuggestionDisplay());
608 569
suggestOracle = (AbstractListSuggestOracle<ExtractionFunctionWithContext>) getSuggestOracle();
... ...
@@ -622,9 +583,10 @@ public class SuggestBoxStatisticProvider extends AbstractDataMiningComponent<Com
622 583
public void setExtractionFunction(ExtractionFunctionWithContext extractionFunction) {
623 584
if (!Objects.equals(this.extractionFunction, extractionFunction)) {
624 585
this.extractionFunction = extractionFunction;
625
- this.setFocus(false);
586
+ setValue(extractionFunction.getExtractionFunction().getDisplayName(), false);
626 587
onValueChange();
627 588
}
589
+ setFocus(false);
628 590
}
629 591
630 592
public ExtractionFunctionWithContext getExtractionFunction() {
java/com.sap.sse.datamining/src/com/sap/sse/datamining/components/ProcessorInstructionHandler.java
... ...
@@ -2,9 +2,11 @@ package com.sap.sse.datamining.components;
2 2
3 3
public interface ProcessorInstructionHandler<ResultType> {
4 4
5
- public void instructionSucceeded(ResultType result);
6
- public void instructionFailed(Exception e);
5
+ boolean isAborted();
7 6
8
- public void afterInstructionFinished();
7
+ void instructionSucceeded(ResultType result);
8
+ void instructionFailed(Exception e);
9
+
10
+ void afterInstructionFinished(ProcessorInstruction<ResultType> instruction);
9 11
10 12
}
java/com.sap.sse.datamining/src/com/sap/sse/datamining/components/management/FunctionProvider.java
... ...
@@ -24,7 +24,9 @@ public interface FunctionProvider {
24 24
DataRetrieverChainDefinition<?, ?> dataRetrieverChainDefinition);
25 25
26 26
/**
27
- * @param classLoader TODO
27
+ * @param functionDTO The {@link FunctionDTO} to resolve
28
+ * @param classLoader The class loader used to get the actual {@link Class} objects described
29
+ * by the <code>functionDTO</code>
28 30
* @return The first function, that matches the given DTO or <code>null</code>
29 31
*/
30 32
public Function<?> getFunctionForDTO(FunctionDTO functionDTO, ClassLoader classLoader);
java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/AbstractParallelMultiDimensionalNestingGroupingProcessor.java
... ...
@@ -69,6 +69,9 @@ public abstract class AbstractParallelMultiDimensionalNestingGroupingProcessor<D
69 69
} else {
70 70
List<GroupKey> keys = new ArrayList<>();
71 71
for (ParameterizedFunction<?> parameterizedDimension : parameterizedDimensions) {
72
+ if (isAborted()) {
73
+ break;
74
+ }
72 75
keys.add(createGroupKeyFor(input, parameterizedDimension.getFunction(), parameterizedDimension.getParameterProvider()));
73 76
}
74 77
return new CompoundGroupKey(keys);
java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/AbstractParallelProcessor.java
... ...
@@ -59,18 +59,21 @@ public abstract class AbstractParallelProcessor<InputType, ResultType> extends A
59 59
private boolean isInstructionValid(ProcessorInstruction<ResultType> instruction) {
60 60
return instruction != null;
61 61
}
62
-
62
+
63
+ @Override
63 64
public void instructionSucceeded(ResultType result) {
64 65
forwardResultToReceivers(result);
65 66
}
66
-
67
+
68
+ @Override
67 69
public void instructionFailed(Exception e) {
68 70
if (!isAborted() || !(e instanceof InterruptedException)) {
69 71
onFailure(e);
70 72
}
71 73
}
72
-
73
- public void afterInstructionFinished() {
74
+
75
+ @Override
76
+ public void afterInstructionFinished(ProcessorInstruction<ResultType> instruction) {
74 77
unfinishedInstructionsCounter.getAndDecrement();
75 78
}
76 79
java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/AbstractProcessorInstruction.java
... ...
@@ -52,17 +52,27 @@ public abstract class AbstractProcessorInstruction<ResultType> implements Proces
52 52
@Override
53 53
public void run() {
54 54
try {
55
- ResultType result = computeResult();
56
- handler.instructionSucceeded(result);
55
+ if (!isAborted()) {
56
+ ResultType result = computeResult();
57
+ handler.instructionSucceeded(result);
58
+ }
57 59
} catch (Exception e) {
58 60
handler.instructionFailed(e);
59 61
} finally {
60
- handler.afterInstructionFinished();
62
+ handler.afterInstructionFinished(this);
61 63
}
62 64
}
65
+
66
+ protected boolean isAborted() {
67
+ return handler.isAborted();
68
+ }
63 69
64 70
protected abstract ResultType computeResult() throws Exception;
65 71
72
+ public ProcessorInstructionHandler<ResultType> getHandler() {
73
+ return handler;
74
+ }
75
+
66 76
@Override
67 77
public int getPriority() {
68 78
return priority;
java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/AbstractRetrievalProcessor.java
... ...
@@ -38,6 +38,9 @@ public abstract class AbstractRetrievalProcessor<InputType, ResultType> extends
38 38
@Override
39 39
public ResultType computeResult() {
40 40
for (ResultType retrievedElement : retrieveData(element)) {
41
+ if (isAborted()) {
42
+ break;
43
+ }
41 44
retrievedDataAmount.incrementAndGet();
42 45
forwardResultToReceivers(retrievedElement);
43 46
}
java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/aggregators/AbstractParallelAggregationProcessor.java
... ...
@@ -5,6 +5,7 @@ import java.util.concurrent.ExecutorService;
5 5
6 6
import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
7 7
import com.sap.sse.datamining.components.Processor;
8
+import com.sap.sse.datamining.components.ProcessorInstruction;
8 9
import com.sap.sse.datamining.impl.components.AbstractParallelProcessor;
9 10
import com.sap.sse.datamining.impl.components.AbstractProcessorInstruction;
10 11
import com.sap.sse.datamining.impl.components.ProcessorInstructionPriority;
... ...
@@ -26,7 +27,7 @@ public abstract class AbstractParallelAggregationProcessor<InputType, Aggregated
26 27
}
27 28
28 29
@Override
29
- protected AbstractProcessorInstruction<AggregatedType> createInstruction(final InputType element) {
30
+ protected ProcessorInstruction<AggregatedType> createInstruction(final InputType element) {
30 31
if (needsSynchronization()) {
31 32
return new AbstractProcessorInstruction<AggregatedType>(this, ProcessorInstructionPriority.Aggregation) {
32 33
@Override
java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/aggregators/ParallelGroupedNumberDataAverageAggregationProcessor.java
... ...
@@ -82,6 +82,9 @@ public class ParallelGroupedNumberDataAverageAggregationProcessor
82 82
protected Map<GroupKey, AverageWithStats<Number>> aggregateResult() {
83 83
Map<GroupKey, AverageWithStats<Number>> result = new HashMap<>();
84 84
for (Entry<GroupKey, DoubleHolder> sumAggregationEntry : sumPerKey.entrySet()) {
85
+ if (isAborted()) {
86
+ break;
87
+ }
85 88
GroupKey key = sumAggregationEntry.getKey();
86 89
result.put(key, new AverageWithStatsImpl<Number>(sumAggregationEntry.getValue().value / elementAmountPerKey.get(key).get(),
87 90
minPerKey.get(key), maxPerKey.get(key),
java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/aggregators/ParallelGroupedNumberDataMedianAggregationProcessor.java
... ...
@@ -47,6 +47,9 @@ public class ParallelGroupedNumberDataMedianAggregationProcessor
47 47
protected Map<GroupKey, Number> aggregateResult() {
48 48
Map<GroupKey, Number> result = new HashMap<>();
49 49
for (Entry<GroupKey, List<Number>> groupedValuesEntry : groupedValues.entrySet()) {
50
+ if (isAborted()) {
51
+ break;
52
+ }
50 53
result.put(groupedValuesEntry.getKey(), getMedianOf(groupedValuesEntry.getValue()));
51 54
}
52 55
return result;
java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/aggregators/ParallelGroupedNumberPairAverageAggregationProcessor.java
... ...
@@ -90,6 +90,9 @@ public class ParallelGroupedNumberPairAverageAggregationProcessor
90 90
protected Map<GroupKey, PairWithStats<Number>> aggregateResult() {
91 91
Map<GroupKey, PairWithStats<Number>> result = new HashMap<>();
92 92
for (Entry<GroupKey, Pair<Number, Number>> sumAggregationEntry : sumPerKey.entrySet()) {
93
+ if (isAborted()) {
94
+ break;
95
+ }
93 96
GroupKey key = sumAggregationEntry.getKey();
94 97
result.put(key, new PairWithStatsImpl<Number>(new Pair<>(sumAggregationEntry.getValue().getA() != null ? sumAggregationEntry.getValue().getA().doubleValue() / elementAmountPerKey.get(key).get() : null, sumAggregationEntry.getValue().getB() != null ? sumAggregationEntry.getValue().getB().doubleValue() / elementAmountPerKey.get(key).get() : null) ,
95 98
minPerKey.get(key), maxPerKey.get(key),
java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/aggregators/ParallelGroupedNumberPairCollectingProcessor.java
... ...
@@ -81,6 +81,9 @@ public class ParallelGroupedNumberPairCollectingProcessor
81 81
protected Map<GroupKey, PairWithStats<Number>> aggregateResult() {
82 82
Map<GroupKey, PairWithStats<Number>> result = new HashMap<>();
83 83
for (Entry<GroupKey, HashSet<Pair<Number, Number>>> sumAggregationEntry : individualPairs.entrySet()) {
84
+ if (isAborted()) {
85
+ break;
86
+ }
84 87
GroupKey key = sumAggregationEntry.getKey();
85 88
result.put(key, new PairWithStatsImpl<Number>(null,
86 89
/* min */ null,
java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/functions/ConcatenatingCompoundFunction.java
... ...
@@ -228,7 +228,7 @@ public class ConcatenatingCompoundFunction<ReturnType> extends AbstractFunction<
228 228
229 229
@Override
230 230
public String toString() {
231
- return getSimpleName();
231
+ return getDeclaringType().getSimpleName() + "." + getSimpleName() + " : " + getReturnType().getSimpleName();
232 232
}
233 233
234 234
@Override
java/com.sap.sse.gwt.test/.project
... ...
@@ -21,16 +21,6 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
25
- <arguments>
26
- </arguments>
27
- </buildCommand>
28
- <buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
30
- <arguments>
31
- </arguments>
32
- </buildCommand>
33
- <buildCommand>
34 24
<name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
35 25
<arguments>
36 26
</arguments>
... ...
@@ -44,7 +34,6 @@
44 34
<natures>
45 35
<nature>org.eclipse.pde.PluginNature</nature>
46 36
<nature>org.eclipse.jdt.core.javanature</nature>
47
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
48 37
<nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
49 38
</natures>
50 39
</projectDescription>
java/com.sap.sse.gwt/.project
... ...
@@ -11,16 +11,6 @@
11 11
</arguments>
12 12
</buildCommand>
13 13
<buildCommand>
14
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
15
- <arguments>
16
- </arguments>
17
- </buildCommand>
18
- <buildCommand>
19
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
20
- <arguments>
21
- </arguments>
22
- </buildCommand>
23
- <buildCommand>
24 14
<name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
25 15
<arguments>
26 16
</arguments>
... ...
@@ -33,7 +23,7 @@
33 23
</buildSpec>
34 24
<natures>
35 25
<nature>org.eclipse.jdt.core.javanature</nature>
36
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
26
+ <nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
37 27
<nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
38 28
</natures>
39 29
</projectDescription>
java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/NotificationPanel.java
... ...
@@ -1,9 +1,13 @@
1 1
package com.sap.sse.gwt.client;
2 2
3 3
import com.google.gwt.animation.client.Animation;
4
+import com.google.gwt.dom.client.Element;
4 5
import com.google.gwt.dom.client.Style.Cursor;
5
-import com.google.gwt.event.dom.client.ClickEvent;
6
-import com.google.gwt.event.dom.client.ClickHandler;
6
+import com.google.gwt.event.shared.HandlerRegistration;
7
+import com.google.gwt.storage.client.Storage;
8
+import com.google.gwt.user.client.Event;
9
+import com.google.gwt.user.client.Event.NativePreviewEvent;
10
+import com.google.gwt.user.client.Event.NativePreviewHandler;
7 11
import com.google.gwt.user.client.ui.FlowPanel;
8 12
import com.google.gwt.user.client.ui.Panel;
9 13
import com.sap.sse.gwt.client.Notification.NotificationType;
... ...
@@ -24,6 +28,7 @@ public class NotificationPanel {
24 28
private final Animation animation;
25 29
26 30
private boolean alreadyShown = false;
31
+ private HandlerRegistration registration;
27 32
28 33
29 34
public NotificationPanel(String message, NotificationType type, Panel parent) {
... ...
@@ -37,12 +42,17 @@ public class NotificationPanel {
37 42
panel.getElement().getStyle().setColor(type.getColor());
38 43
panel.getElement().getStyle().setBackgroundColor(type.getBackgroundColor());
39 44
panel.getElement().setInnerText(type.getDecorator() + " " + message);
40
- panel.addDomHandler(new ClickHandler() {
45
+
46
+ // ensure notifications work if a dataentry dialog is open!
47
+ registration = Event.addNativePreviewHandler(new NativePreviewHandler() {
41 48
@Override
42
- public void onClick(ClickEvent event) {
43
- animation.cancel();
49
+ public void onPreviewNativeEvent(NativePreviewEvent event) {
50
+ Element target = Element.as(event.getNativeEvent().getEventTarget());
51
+ if (event.getTypeInt() == Event.ONCLICK && target == panel.getElement()) {
52
+ animation.cancel();
53
+ }
44 54
}
45
- }, ClickEvent.getType());
55
+ });
46 56
47 57
animation = new Animation() {
48 58
@Override
... ...
@@ -61,7 +71,7 @@ public class NotificationPanel {
61 71
double relPr = (progress - FADE_OUT_PERCENT) / (1 - FADE_OUT_PERCENT);
62 72
panel.getElement().getStyle().setOpacity(1 - relPr);
63 73
} else {
64
- panel.getElement().getStyle().setOpacity(1);
74
+ panel.getElement().getStyle().clearOpacity();
65 75
}
66 76
}
67 77
... ...
@@ -81,9 +91,21 @@ public class NotificationPanel {
81 91
* Displays notification at UI.
82 92
*/
83 93
public void show() {
94
+ final Storage localStorageIfSupported = Storage.getLocalStorageIfSupported();
95
+ int timeout = NOTIFICATION_TIME;
96
+ if (localStorageIfSupported != null) {
97
+ final String customTimeOut = localStorageIfSupported.getItem("sse.notification.customTimeOutInSeconds");
98
+ if (customTimeOut != null && !customTimeOut.isEmpty()) {
99
+ try {
100
+ timeout = Integer.parseInt(customTimeOut) * 1000;
101
+ } catch (Exception e) {
102
+ // If the value can't be parsed, we just use the default
103
+ }
104
+ }
105
+ }
84 106
if (!animation.isRunning()) {
85 107
parent.add(panel);
86
- animation.run(NOTIFICATION_TIME);
108
+ animation.run(timeout);
87 109
}
88 110
}
89 111
... ...
@@ -99,6 +121,7 @@ public class NotificationPanel {
99 121
* Removes panel from parent element at UI and force checking of queue for notifications.
100 122
*/
101 123
public void remove() {
124
+ registration.removeHandler();
102 125
parent.remove(panel);
103 126
Notification.checkQueue(this);
104 127
}
java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/datetime/DateInput.java
... ...
@@ -14,7 +14,7 @@ public class DateInput extends AbstractInput {
14 14
* Created a new {@link DateInput} instance.
15 15
*/
16 16
public DateInput() {
17
- super(DateTimeInputType.TIME.isSupported() ? NativeDateTimeInput.date() : new CustomDateBox());
17
+ super(DateTimeInputType.DATE.isSupported() ? NativeDateTimeInput.date() : new CustomDateBox());
18 18
}
19 19
20 20
private static class CustomDateBox extends DateBox {
java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/suggestion/AbstractListSuggestOracle.java
... ...
@@ -18,8 +18,9 @@ public abstract class AbstractListSuggestOracle<C> extends AbstractSuggestOracle
18 18
19 19
@Override
20 20
protected final void getSuggestions(Request request, Callback callback, Iterable<String> queryTokens) {
21
- Iterable<C> filteredList = suggestionMatchingFilter.applyFilter(getKeywordStrings(queryTokens), suggestionObjectList);
22
- this.setSuggestions(request, callback, filteredList, queryTokens);
21
+ Iterable<String> keywords = getKeywordStrings(queryTokens);
22
+ Iterable<C> filteredList = suggestionMatchingFilter.applyFilter(keywords, suggestionObjectList);
23
+ this.setSuggestions(request, callback, filteredList, keywords);
23 24
}
24 25
25 26
protected Iterable<String> getKeywordStrings(Iterable<String> queryTokens) {
java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/suggestion/AbstractSuggestOracle.java
... ...
@@ -90,10 +90,12 @@ public abstract class AbstractSuggestOracle<T> extends SuggestOracle {
90 90
int index = displayString.length();
91 91
String matchToken = null;
92 92
for (String token : queryTokens) {
93
- int matchIndex = normalizedString.indexOf(token, cursor);
94
- if (matchIndex >= 0 && matchIndex < index) {
95
- index = matchIndex;
96
- matchToken = token;
93
+ if (token != null && !token.isEmpty()) {
94
+ int matchIndex = normalizedString.indexOf(token, cursor);
95
+ if (matchIndex >= 0 && matchIndex < index) {
96
+ index = matchIndex;
97
+ matchToken = token;
98
+ }
97 99
}
98 100
}
99 101
if (matchToken != null) {
java/com.sap.sse.security.ui/.project
... ...
@@ -21,16 +21,6 @@
21 21
</arguments>
22 22
</buildCommand>
23 23
<buildCommand>
24
- <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
25
- <arguments>
26
- </arguments>
27
- </buildCommand>
28
- <buildCommand>
29
- <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
30
- <arguments>
31
- </arguments>
32
- </buildCommand>
33
- <buildCommand>
34 24
<name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
35 25
<arguments>
36 26
</arguments>
... ...
@@ -44,7 +34,6 @@
44 34
<natures>
45 35
<nature>org.eclipse.pde.PluginNature</nature>
46 36
<nature>org.eclipse.jdt.core.javanature</nature>
47
- <nature>com.google.gwt.eclipse.core.gwtNature</nature>
48 37
<nature>com.gwtplugins.gwt.eclipse.core.gwtNature</nature>
49 38
</natures>
50 39
</projectDescription>
java/com.tractrac.clientmodule/META-INF/MANIFEST.MF
... ...
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
2 2
Bundle-ManifestVersion: 2
3 3
Bundle-Name: TracTrac Client module
4 4
Bundle-SymbolicName: com.tractrac.clientmodule
5
-Bundle-Version: 3.10.1
5
+Bundle-Version: 3.11.0
6 6
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
7 7
Bundle-ClassPath: .,
8 8
lib/TracAPI.jar
... ...
@@ -88,7 +88,6 @@ Export-Package: com.tractrac.asio.lib.api,
88 88
com.tractrac.subscription.lib.impl.io.controllers,
89 89
com.tractrac.subscription.lib.impl.io.receivers,
90 90
com.tractrac.subscription.lib.impl.race,
91
- com.tractrac.subscription.lib.impl.route,
92 91
com.tractrac.subscription.lib.impl.ws,
93 92
com.tractrac.util.lib.api,
94 93
com.tractrac.util.lib.api.autolog,
java/com.tractrac.clientmodule/README.txt
... ...
@@ -17,10 +17,38 @@ It contains also some files:
17 17
- Manifest.txt -> manifest used to create the test.jar file
18 18
19 19
********************************************
20
+************* TracAPI 3.11.0 ***************
21
+********************************************
22
+This is a final version. It changes the implementation of the IRaceSubscriber interface,
23
+breaking the backward compatibility:
24
+
25
+ - The methods IRaceSubscriber.subscribeRoutes() and IRaceSubscriber.unsubscribeRoutes()
26
+ have been removed.
27
+ - The IRoutesListener has been removed.
28
+ - The IControlRouteChangeListener has been extended adding a new method to get updates
29
+ of a IPathRoute. If you are managing "sailing events" this method will never be invoked.
30
+ - When any of the attributes of the route is updated, will be notified using the
31
+ IRaceSubscriber.subscribeRouteChanges(IControlRouteChangeListener) method
32
+
33
+Release date: 30/07/2018
34
+Build number: 416b827959b696583cce509ac39b7fd64aaefe9b
35
+
36
+ 1) Features
37
+
38
+ - Merging the subscriptions IRaceSubscriber.subscribeRouteChanges and IRaceSubscriber.subscribeRoutes
39
+ in the same method (Requested by Axel Uhl, 23/07/2018)
40
+
41
+ 2) Bugs
42
+
43
+ - When the client is offline, if it tries to load a race it gets a RaceLoadingException. But then,
44
+ when the client is online again, it can't reuse the same race because it is in an internal wrong
45
+ status (Reported by Thomas Scott, 19/06/2018)
46
+
47
+********************************************
20 48
************* TracAPI 3.10.1 ***************
21 49
********************************************
22
- This is a final version.It fixes bugs in the implementation and it adds a some features.
23
- It keeps the backward compatibility.
50
+This is a final version.It fixes bugs in the implementation and it adds a some features.
51
+It keeps the backward compatibility:
24 52
25 53
Release date: 28/06/2018
26 54
Build number: 35a26e503339fff26fe984617e5190a18438e10b
... ...
@@ -35,7 +63,7 @@ It contains also some files:
35 63
when the client is online again, it can't reuse the same race because it is in an internal wrong
36 64
status (Reported by Thomas Scott, 19/06/2018)
37 65
- The live delay is not propagated (sometimes). This feature has been reimplemented and now the
38
- value is attached and send with the race object using the same approach used to transmit the race
66
+ value is attached and sent with the race object using the same approach used to transmit the race
39 67
start time or the tracking start time (Reported by Axel Uhl, 19/06/2018)
40 68
41 69
********************************************
java/com.tractrac.clientmodule/javadoc/allclasses-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>All Classes</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/allclasses-noframe.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>All Classes</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/IIdentifiable.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IIdentifiable</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/INamed.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>INamed</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/ModelLocator.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>ModelLocator</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/attachment/AbstractAttachable.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>AbstractAttachable</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/attachment/IAttachable.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IAttachable</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/attachment/IAttachmentKey.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IAttachmentKey</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/attachment/IAttachmentManager.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IAttachmentManager</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/attachment/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.attachment</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/attachment/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.attachment</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/attachment/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.attachment Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/IControlPassing.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IControlPassing</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/IControlPassings.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IControlPassings</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
... ...
@@ -128,7 +128,7 @@ var activeTableTab = "activeTableTab";
128 128
<td class="colFirst"><code>java.util.List&lt;<a href="../../../../../../com/tractrac/model/lib/api/data/IControlPassing.html" title="interface in com.tractrac.model.lib.api.data">IControlPassing</a>&gt;</code></td>
129 129
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../com/tractrac/model/lib/api/data/IControlPassings.html#getPassings--">getPassings</a></span>()</code>
130 130
<div class="block">
131
- Returns a list of control passings.</div>
131
+ Returns a list of control passings sorted by time.</div>
132 132
</td>
133 133
</tr>
134 134
</table>
... ...
@@ -154,7 +154,7 @@ var activeTableTab = "activeTableTab";
154 154
<h4>getPassings</h4>
155 155
<pre>java.util.List&lt;<a href="../../../../../../com/tractrac/model/lib/api/data/IControlPassing.html" title="interface in com.tractrac.model.lib.api.data">IControlPassing</a>&gt;&nbsp;getPassings()</pre>
156 156
<div class="block"><p>
157
- Returns a list of control passings.
157
+ Returns a list of control passings sorted by time.
158 158
</p>
159 159
<p>
160 160
This method is thread-safety: it returns a copy of the list.
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/IMessageData.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IMessageData</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/IPosition.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IPosition</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/IPositionFactory.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IPositionFactory</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/IPositionOffset.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IPositionOffset</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/IPositionSnapped.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IPositionSnapped</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/IStartStopData.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IStartStopData</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/ITimeData.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>ITimeData</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.data</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.data</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/data/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.data Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/CreateModelException.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>CreateModelException</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/DataSource.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>DataSource</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/EventType.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>EventType</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/ICompetitor.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>ICompetitor</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/ICompetitorClass.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>ICompetitorClass</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/IEvent.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IEvent</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/IEventFactory.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IEventFactory</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/IRace.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IRace</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/IRaceCompetitor.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IRaceCompetitor</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/IRaceSerie.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IRaceSerie</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/ITeam.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>ITeam</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/RaceCompetitorStatusType.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>RaceCompetitorStatusType</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/RaceLoadingException.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>RaceLoadingException</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/RaceStatusType.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>RaceStatusType</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/RaceVisibilityType.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>RaceVisibilityType</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/StartTimeType.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>StartTimeType</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.event</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.event</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/event/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.event Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
... ...
@@ -150,12 +150,12 @@
150 150
<ul>
151 151
<li type="circle">java.lang.Enum&lt;E&gt; (implements java.lang.Comparable&lt;T&gt;, java.io.Serializable)
152 152
<ul>
153
-<li type="circle">com.tractrac.model.lib.api.event.<a href="../../../../../../com/tractrac/model/lib/api/event/RaceVisibilityType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">RaceVisibilityType</span></a></li>
154 153
<li type="circle">com.tractrac.model.lib.api.event.<a href="../../../../../../com/tractrac/model/lib/api/event/EventType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">EventType</span></a></li>
155
-<li type="circle">com.tractrac.model.lib.api.event.<a href="../../../../../../com/tractrac/model/lib/api/event/StartTimeType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">StartTimeType</span></a></li>
156
-<li type="circle">com.tractrac.model.lib.api.event.<a href="../../../../../../com/tractrac/model/lib/api/event/RaceStatusType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">RaceStatusType</span></a></li>
157 154
<li type="circle">com.tractrac.model.lib.api.event.<a href="../../../../../../com/tractrac/model/lib/api/event/RaceCompetitorStatusType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">RaceCompetitorStatusType</span></a></li>
158 155
<li type="circle">com.tractrac.model.lib.api.event.<a href="../../../../../../com/tractrac/model/lib/api/event/DataSource.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">DataSource</span></a></li>
156
+<li type="circle">com.tractrac.model.lib.api.event.<a href="../../../../../../com/tractrac/model/lib/api/event/RaceStatusType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">RaceStatusType</span></a></li>
157
+<li type="circle">com.tractrac.model.lib.api.event.<a href="../../../../../../com/tractrac/model/lib/api/event/RaceVisibilityType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">RaceVisibilityType</span></a></li>
158
+<li type="circle">com.tractrac.model.lib.api.event.<a href="../../../../../../com/tractrac/model/lib/api/event/StartTimeType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">StartTimeType</span></a></li>
159 159
</ul>
160 160
</li>
161 161
</ul>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/metadata/IMetadata.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IMetadata</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/metadata/IMetadataContainer.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IMetadataContainer</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/metadata/IMetadataFactory.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IMetadataFactory</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/metadata/IPropertiesContainer.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IPropertiesContainer</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/metadata/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.metadata</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/metadata/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.metadata</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/metadata/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.metadata Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/IControl.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IControl</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/IControlPoint.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IControlPoint</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/IControlRoute.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IControlRoute</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/IPathRoute.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IPathRoute</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/IPathRouteFactory.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IPathRouteFactory</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/IPathSegment.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IPathSegment</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/IRoute.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IRoute</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/ISegment.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>ISegment</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.route</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.route</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/route/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.route Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/sensor/ISensorData.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>ISensorData</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/sensor/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.sensor</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/sensor/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.sensor</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/sensor/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.sensor Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/spatial/ICoordinate.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>ICoordinate</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/spatial/ICoordinateSequence.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>ICoordinateSequence</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/spatial/IExtent.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IExtent</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/spatial/IGeoCoordinate.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IGeoCoordinate</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/spatial/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.spatial</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/spatial/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.spatial</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/model/lib/api/spatial/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.model.lib.api.spatial Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/IEventSubscriber.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IEventSubscriber</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/IRaceSubscriber.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IRaceSubscriber</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
... ...
@@ -18,7 +18,7 @@
18 18
catch(err) {
19 19
}
20 20
//-->
21
-var methods = {"i0":6,"i1":6,"i2":6,"i3":6,"i4":6,"i5":6,"i6":6,"i7":6,"i8":6,"i9":6,"i10":6,"i11":6,"i12":6,"i13":6,"i14":6,"i15":6,"i16":6,"i17":6,"i18":6,"i19":6,"i20":6,"i21":6,"i22":6,"i23":6,"i24":6,"i25":6,"i26":6,"i27":6,"i28":6,"i29":6};
21
+var methods = {"i0":6,"i1":6,"i2":6,"i3":6,"i4":6,"i5":6,"i6":6,"i7":6,"i8":6,"i9":6,"i10":6,"i11":6,"i12":6,"i13":6,"i14":6,"i15":6,"i16":6,"i17":6,"i18":6,"i19":6,"i20":6,"i21":6,"i22":6,"i23":6,"i24":6,"i25":6,"i26":6,"i27":6,"i28":6,"i29":6,"i30":6,"i31":6,"i32":6};
22 22
var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],4:["t3","Abstract Methods"]};
23 23
var altColor = "altColor";
24 24
var rowColor = "rowColor";
... ...
@@ -149,11 +149,18 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
149 149
</tr>
150 150
<tr id="i3" class="rowColor">
151 151
<td class="colFirst"><code>void</code></td>
152
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeControlPassings-com.tractrac.subscription.lib.api.control.IControlPassingsListener-java.util.UUID...-">subscribeControlPassings</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPassingsListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPassingsListener</a>&nbsp;listener,
153
+ java.util.UUID...&nbsp;classIds)</code>
154
+<div class="block">Subscribes to control passing data for the specified race and a class(es)</div>
155
+</td>
156
+</tr>
157
+<tr id="i4" class="altColor">
158
+<td class="colFirst"><code>void</code></td>
152 159
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeControlPositions-com.tractrac.subscription.lib.api.control.IControlPointPositionListener-">subscribeControlPositions</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPointPositionListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPointPositionListener</a>&nbsp;listener)</code>
153 160
<div class="block">Subscribes to control positions for the race.</div>
154 161
</td>
155 162
</tr>
156
-<tr id="i4" class="altColor">
163
+<tr id="i5" class="rowColor">
157 164
<td class="colFirst"><code>void</code></td>
158 165
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeControlPositions-com.tractrac.subscription.lib.api.control.IControlPointPositionListener-long-long-">subscribeControlPositions</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPointPositionListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPointPositionListener</a>&nbsp;listener,
159 166
long&nbsp;fromTime,
... ...
@@ -162,13 +169,13 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
162 169
data.</div>
163 170
</td>
164 171
</tr>
165
-<tr id="i5" class="rowColor">
172
+<tr id="i6" class="altColor">
166 173
<td class="colFirst"><code>void</code></td>
167 174
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeControlSensorData-com.tractrac.subscription.lib.api.control.IControlPointSensorDataListener-">subscribeControlSensorData</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPointSensorDataListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPointSensorDataListener</a>&nbsp;listener)</code>
168 175
<div class="block">Subscribes to control sensor data for the race.</div>
169 176
</td>
170 177
</tr>
171
-<tr id="i6" class="altColor">
178
+<tr id="i7" class="rowColor">
172 179
<td class="colFirst"><code>void</code></td>
173 180
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeControlSensorData-com.tractrac.subscription.lib.api.control.IControlPointSensorDataListener-long-long-">subscribeControlSensorData</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPointSensorDataListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPointSensorDataListener</a>&nbsp;listener,
174 181
long&nbsp;fromTime,
... ...
@@ -177,13 +184,13 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
177 184
data.</div>
178 185
</td>
179 186
</tr>
180
-<tr id="i7" class="rowColor">
187
+<tr id="i8" class="altColor">
181 188
<td class="colFirst"><code>void</code></td>
182 189
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-">subscribePositions</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionListener</a>&nbsp;listener)</code>
183 190
<div class="block">Subscribes to competitor positions for a given Race.</div>
184 191
</td>
185 192
</tr>
186
-<tr id="i8" class="altColor">
193
+<tr id="i9" class="rowColor">
187 194
<td class="colFirst"><code>void</code></td>
188 195
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-long-long-">subscribePositions</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionListener</a>&nbsp;listener,
189 196
long&nbsp;fromTime,
... ...
@@ -191,13 +198,29 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
191 198
<div class="block">Subscribes to competitor positions for a given Race.</div>
192 199
</td>
193 200
</tr>
194
-<tr id="i9" class="rowColor">
201
+<tr id="i10" class="altColor">
202
+<td class="colFirst"><code>void</code></td>
203
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-long-long-java.util.UUID...-">subscribePositions</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionListener</a>&nbsp;listener,
204
+ long&nbsp;fromTime,
205
+ long&nbsp;toTime,
206
+ java.util.UUID...&nbsp;classIds)</code>
207
+<div class="block">Subscribes to competitor positions for a given Race and class(es).</div>
208
+</td>
209
+</tr>
210
+<tr id="i11" class="rowColor">
211
+<td class="colFirst"><code>void</code></td>
212
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-java.util.UUID...-">subscribePositions</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionListener</a>&nbsp;listener,
213
+ java.util.UUID...&nbsp;classIds)</code>
214
+<div class="block">Subscribes to competitor positions for a given Race and class(es).</div>
215
+</td>
216
+</tr>
217
+<tr id="i12" class="altColor">
195 218
<td class="colFirst"><code>void</code></td>
196 219
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositionsOffset-com.tractrac.subscription.lib.api.competitor.IPositionOffsetListener-">subscribePositionsOffset</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionOffsetListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionOffsetListener</a>&nbsp;listener)</code>
197 220
<div class="block">Subscribes to offset competitor positions for a given Race.</div>
198 221
</td>
199 222
</tr>
200
-<tr id="i10" class="altColor">
223
+<tr id="i13" class="rowColor">
201 224
<td class="colFirst"><code>void</code></td>
202 225
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositionsOffset-com.tractrac.subscription.lib.api.competitor.IPositionOffsetListener-long-long-">subscribePositionsOffset</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionOffsetListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionOffsetListener</a>&nbsp;listener,
203 226
long&nbsp;fromTime,
... ...
@@ -206,13 +229,13 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
206 229
historic data.</div>
207 230
</td>
208 231
</tr>
209
-<tr id="i11" class="rowColor">
232
+<tr id="i14" class="altColor">
210 233
<td class="colFirst"><code>void</code></td>
211 234
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositionsSnapped-com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener-">subscribePositionsSnapped</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionSnappedListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionSnappedListener</a>&nbsp;listener)</code>
212 235
<div class="block">Subscribes to snapped competitor positions for a given Race.</div>
213 236
</td>
214 237
</tr>
215
-<tr id="i12" class="altColor">
238
+<tr id="i15" class="rowColor">
216 239
<td class="colFirst"><code>void</code></td>
217 240
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositionsSnapped-com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener-long-long-">subscribePositionsSnapped</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionSnappedListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionSnappedListener</a>&nbsp;listener,
218 241
long&nbsp;fromTime,
... ...
@@ -221,110 +244,113 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
221 244
historic data.</div>
222 245
</td>
223 246
</tr>
224
-<tr id="i13" class="rowColor">
247
+<tr id="i16" class="altColor">
248
+<td class="colFirst"><code>void</code></td>
249
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositionsSnapped-com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener-long-long-java.util.UUID...-">subscribePositionsSnapped</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionSnappedListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionSnappedListener</a>&nbsp;listener,
250
+ long&nbsp;fromTime,
251
+ long&nbsp;toTime,
252
+ java.util.UUID...&nbsp;classIds)</code>
253
+<div class="block">Subscribes to snapped competitor positions for a given Race and class(es), including
254
+ historic data.</div>
255
+</td>
256
+</tr>
257
+<tr id="i17" class="rowColor">
258
+<td class="colFirst"><code>void</code></td>
259
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositionsSnapped-com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener-java.util.UUID...-">subscribePositionsSnapped</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionSnappedListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionSnappedListener</a>&nbsp;listener,
260
+ java.util.UUID...&nbsp;classIds)</code>
261
+<div class="block">Subscribes to snapped competitor positions for a given Race and class(es).</div>
262
+</td>
263
+</tr>
264
+<tr id="i18" class="altColor">
225 265
<td class="colFirst"><code>void</code></td>
226 266
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeRaceCompetitor-com.tractrac.subscription.lib.api.race.IRaceCompetitorListener-">subscribeRaceCompetitor</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/race/IRaceCompetitorListener.html" title="interface in com.tractrac.subscription.lib.api.race">IRaceCompetitorListener</a>&nbsp;listener)</code>
227 267
<div class="block">Subscribes to race competitor for a given Race.</div>
228 268
</td>
229 269
</tr>
230
-<tr id="i14" class="altColor">
270
+<tr id="i19" class="rowColor">
231 271
<td class="colFirst"><code>void</code></td>
232 272
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeRaceMessages-com.tractrac.subscription.lib.api.race.IRaceMessageListener-">subscribeRaceMessages</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/race/IRaceMessageListener.html" title="interface in com.tractrac.subscription.lib.api.race">IRaceMessageListener</a>&nbsp;listener)</code>
233 273
<div class="block">Subscribe to messages for a race.</div>
234 274
</td>
235 275
</tr>
236
-<tr id="i15" class="rowColor">
276
+<tr id="i20" class="altColor">
237 277
<td class="colFirst"><code>void</code></td>
238 278
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeRaceTimesChanges-com.tractrac.subscription.lib.api.race.IRaceStartStopTimesChangeListener-">subscribeRaceTimesChanges</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/race/IRaceStartStopTimesChangeListener.html" title="interface in com.tractrac.subscription.lib.api.race">IRaceStartStopTimesChangeListener</a>&nbsp;listener)</code>
239 279
<div class="block">Subscribes to changes in race start and stop times.</div>
240 280
</td>
241 281
</tr>
242
-<tr id="i16" class="altColor">
282
+<tr id="i21" class="rowColor">
243 283
<td class="colFirst"><code>void</code></td>
244 284
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeRouteChanges-com.tractrac.subscription.lib.api.control.IControlRouteChangeListener-">subscribeRouteChanges</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlRouteChangeListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlRouteChangeListener</a>&nbsp;listener)</code>
245 285
<div class="block">Subscribes to route changes for a given Race.</div>
246 286
</td>
247 287
</tr>
248
-<tr id="i17" class="rowColor">
249
-<td class="colFirst"><code>void</code></td>
250
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeRoutes-com.tractrac.subscription.lib.api.route.IRoutesListener-">subscribeRoutes</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/route/IRoutesListener.html" title="interface in com.tractrac.subscription.lib.api.route">IRoutesListener</a>&nbsp;listener)</code>
251
-<div class="block">
252
- Subscriber to route changes.</div>
253
-</td>
254
-</tr>
255
-<tr id="i18" class="altColor">
288
+<tr id="i22" class="altColor">
256 289
<td class="colFirst"><code>void</code></td>
257 290
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribeCompetitorSensorData-com.tractrac.subscription.lib.api.competitor.ICompetitorSensorDataListener-">unsubscribeCompetitorSensorData</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/ICompetitorSensorDataListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">ICompetitorSensorDataListener</a>&nbsp;listener)</code>
258 291
<div class="block">Unsubscribes to competitor sensor data for a given Race.</div>
259 292
</td>
260 293
</tr>
261
-<tr id="i19" class="rowColor">
294
+<tr id="i23" class="rowColor">
262 295
<td class="colFirst"><code>void</code></td>
263 296
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribeControlPassings-com.tractrac.subscription.lib.api.control.IControlPassingsListener-">unsubscribeControlPassings</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPassingsListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPassingsListener</a>&nbsp;listener)</code>
264 297
<div class="block">Unsubscribes to control passing data for the specified race.</div>
265 298
</td>
266 299
</tr>
267
-<tr id="i20" class="altColor">
300
+<tr id="i24" class="altColor">
268 301
<td class="colFirst"><code>void</code></td>
269 302
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribeControlPositions-com.tractrac.subscription.lib.api.control.IControlPointPositionListener-">unsubscribeControlPositions</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPointPositionListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPointPositionListener</a>&nbsp;listener)</code>
270 303
<div class="block">Unsubscribes to control positions.</div>
271 304
</td>
272 305
</tr>
273
-<tr id="i21" class="rowColor">
306
+<tr id="i25" class="rowColor">
274 307
<td class="colFirst"><code>void</code></td>
275 308
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribeControlSensorData-com.tractrac.subscription.lib.api.control.IControlPointSensorDataListener-">unsubscribeControlSensorData</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPointSensorDataListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPointSensorDataListener</a>&nbsp;listener)</code>
276 309
<div class="block">Unsubscribes to control sensor data for a given Race.</div>
277 310
</td>
278 311
</tr>
279
-<tr id="i22" class="altColor">
312
+<tr id="i26" class="altColor">
280 313
<td class="colFirst"><code>void</code></td>
281 314
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-">unsubscribePositions</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionListener</a>&nbsp;listener)</code>
282 315
<div class="block">Unsubscribes to competitor positions for a given Race.</div>
283 316
</td>
284 317
</tr>
285
-<tr id="i23" class="rowColor">
318
+<tr id="i27" class="rowColor">
286 319
<td class="colFirst"><code>void</code></td>
287 320
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribePositionsOffset-com.tractrac.subscription.lib.api.competitor.IPositionOffsetListener-">unsubscribePositionsOffset</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionOffsetListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionOffsetListener</a>&nbsp;listener)</code>
288 321
<div class="block">Unsubscribes to competitor positions for a given Race.</div>
289 322
</td>
290 323
</tr>
291
-<tr id="i24" class="altColor">
324
+<tr id="i28" class="altColor">
292 325
<td class="colFirst"><code>void</code></td>
293 326
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribePositionsSnapped-com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener-">unsubscribePositionsSnapped</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionSnappedListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionSnappedListener</a>&nbsp;listener)</code>
294 327
<div class="block">Unsubscribes to competitor positions for a given Race.</div>
295 328
</td>
296 329
</tr>
297
-<tr id="i25" class="rowColor">
330
+<tr id="i29" class="rowColor">
298 331
<td class="colFirst"><code>void</code></td>
299 332
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribeRaceCompetitor-com.tractrac.subscription.lib.api.race.IRaceCompetitorListener-">unsubscribeRaceCompetitor</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/race/IRaceCompetitorListener.html" title="interface in com.tractrac.subscription.lib.api.race">IRaceCompetitorListener</a>&nbsp;listener)</code>
300 333
<div class="block">Unsubscribes to race competitor</div>
301 334
</td>
302 335
</tr>
303
-<tr id="i26" class="altColor">
336
+<tr id="i30" class="altColor">
304 337
<td class="colFirst"><code>void</code></td>
305 338
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribeRaceMessages-com.tractrac.subscription.lib.api.race.IRaceMessageListener-">unsubscribeRaceMessages</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/race/IRaceMessageListener.html" title="interface in com.tractrac.subscription.lib.api.race">IRaceMessageListener</a>&nbsp;listener)</code>
306 339
<div class="block">Unsubscribes to race messages</div>
307 340
</td>
308 341
</tr>
309
-<tr id="i27" class="rowColor">
342
+<tr id="i31" class="rowColor">
310 343
<td class="colFirst"><code>void</code></td>
311 344
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribeRaceTimesChanges-com.tractrac.subscription.lib.api.race.IRaceStartStopTimesChangeListener-">unsubscribeRaceTimesChanges</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/race/IRaceStartStopTimesChangeListener.html" title="interface in com.tractrac.subscription.lib.api.race">IRaceStartStopTimesChangeListener</a>&nbsp;listener)</code>
312 345
<div class="block">Unsubscribes to changes in race start and stop times.</div>
313 346
</td>
314 347
</tr>
315
-<tr id="i28" class="altColor">
348
+<tr id="i32" class="altColor">
316 349
<td class="colFirst"><code>void</code></td>
317 350
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribeRouteChanges-com.tractrac.subscription.lib.api.control.IControlRouteChangeListener-">unsubscribeRouteChanges</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlRouteChangeListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlRouteChangeListener</a>&nbsp;listener)</code>
318 351
<div class="block">Unsubscribes to route changes for a given Race.</div>
319 352
</td>
320 353
</tr>
321
-<tr id="i29" class="rowColor">
322
-<td class="colFirst"><code>void</code></td>
323
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribeRoutes-com.tractrac.subscription.lib.api.route.IRoutesListener-">unsubscribeRoutes</a></span>(<a href="../../../../../com/tractrac/subscription/lib/api/route/IRoutesListener.html" title="interface in com.tractrac.subscription.lib.api.route">IRoutesListener</a>&nbsp;listener)</code>
324
-<div class="block">
325
- Unsubscribes to route changes for a given Race.</div>
326
-</td>
327
-</tr>
328 354
</table>
329 355
<ul class="blockList">
330 356
<li class="blockList"><a name="methods.inherited.from.class.com.tractrac.subscription.lib.api.ISubscriber">
... ...
@@ -356,7 +382,28 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
356 382
<pre>void&nbsp;subscribePositions(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionListener</a>&nbsp;listener)</pre>
357 383
<div class="block">Subscribes to competitor positions for a given Race. It uses the tracking
358 384
start time and the tracking end time as time interval to receive positions.
359
-
385
+
386
+ <p>
387
+ The method returns immediately and the positions are subsequently sent to
388
+ the given listener, as they are received.
389
+ </p></div>
390
+<dl>
391
+<dt><span class="paramLabel">Parameters:</span></dt>
392
+<dd><code>listener</code> - the listener to receive the positions.</dd>
393
+</dl>
394
+</li>
395
+</ul>
396
+<a name="subscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-java.util.UUID...-">
397
+<!-- -->
398
+</a>
399
+<ul class="blockList">
400
+<li class="blockList">
401
+<h4>subscribePositions</h4>
402
+<pre>void&nbsp;subscribePositions(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionListener</a>&nbsp;listener,
403
+ java.util.UUID...&nbsp;classIds)</pre>
404
+<div class="block">Subscribes to competitor positions for a given Race and class(es). It uses the tracking
405
+ start time and the tracking end time as time interval to receive positions.
406
+
360 407
<p>
361 408
The method returns immediately and the positions are subsequently sent to
362 409
the given listener, as they are received.
... ...
@@ -364,6 +411,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
364 411
<dl>
365 412
<dt><span class="paramLabel">Parameters:</span></dt>
366 413
<dd><code>listener</code> - the listener to receive the positions.</dd>
414
+<dd><code>classIds</code> - the class ids</dd>
367 415
</dl>
368 416
</li>
369 417
</ul>
... ...
@@ -377,7 +425,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
377 425
long&nbsp;fromTime,
378 426
long&nbsp;toTime)</pre>
379 427
<div class="block">Subscribes to competitor positions for a given Race.
380
-
428
+
381 429
<p>
382 430
The method returns immediately and the positions are subsequently sent to
383 431
the given listener, as they are received.
... ...
@@ -392,6 +440,33 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
392 440
</dl>
393 441
</li>
394 442
</ul>
443
+<a name="subscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-long-long-java.util.UUID...-">
444
+<!-- -->
445
+</a>
446
+<ul class="blockList">
447
+<li class="blockList">
448
+<h4>subscribePositions</h4>
449
+<pre>void&nbsp;subscribePositions(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionListener</a>&nbsp;listener,
450
+ long&nbsp;fromTime,
451
+ long&nbsp;toTime,
452
+ java.util.UUID...&nbsp;classIds)</pre>
453
+<div class="block">Subscribes to competitor positions for a given Race and class(es).
454
+
455
+ <p>
456
+ The method returns immediately and the positions are subsequently sent to
457
+ the given listener, as they are received.
458
+ </p></div>
459
+<dl>
460
+<dt><span class="paramLabel">Parameters:</span></dt>
461
+<dd><code>listener</code> - the listener to receive the positions.</dd>
462
+<dd><code>fromTime</code> - stored positions (if supported) will be requested from this time
463
+ and forward. The value <code>0</code> is allowed and means all
464
+ historic data.</dd>
465
+<dd><code>toTime</code> - The value <code>Long.MAXVALUE</code> means all data in the future</dd>
466
+<dd><code>classIds</code> - the class ids</dd>
467
+</dl>
468
+</li>
469
+</ul>
395 470
<a name="unsubscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-">
396 471
<!-- -->
397 472
</a>
... ...
@@ -416,7 +491,29 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
416 491
<div class="block">Subscribes to snapped competitor positions for a given Race. It uses the
417 492
tracking start time and the tracking end time as time interval to receive
418 493
positions.
419
-
494
+
495
+ <p>
496
+ The method returns immediately and the positions are subsequently sent to
497
+ the given listener, as they are received.
498
+ </p></div>
499
+<dl>
500
+<dt><span class="paramLabel">Parameters:</span></dt>
501
+<dd><code>listener</code> - the listener to receive the positions.</dd>
502
+</dl>
503
+</li>
504
+</ul>
505
+<a name="subscribePositionsSnapped-com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener-java.util.UUID...-">
506
+<!-- -->
507
+</a>
508
+<ul class="blockList">
509
+<li class="blockList">
510
+<h4>subscribePositionsSnapped</h4>
511
+<pre>void&nbsp;subscribePositionsSnapped(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionSnappedListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionSnappedListener</a>&nbsp;listener,
512
+ java.util.UUID...&nbsp;classIds)</pre>
513
+<div class="block">Subscribes to snapped competitor positions for a given Race and class(es). It uses the
514
+ tracking start time and the tracking end time as time interval to receive
515
+ positions.
516
+
420 517
<p>
421 518
The method returns immediately and the positions are subsequently sent to
422 519
the given listener, as they are received.
... ...
@@ -424,6 +521,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
424 521
<dl>
425 522
<dt><span class="paramLabel">Parameters:</span></dt>
426 523
<dd><code>listener</code> - the listener to receive the positions.</dd>
524
+<dd><code>classIds</code> - the class ids</dd>
427 525
</dl>
428 526
</li>
429 527
</ul>
... ...
@@ -438,7 +536,34 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
438 536
long&nbsp;toTime)</pre>
439 537
<div class="block">Subscribes to snapped competitor positions for a given Race, including
440 538
historic data.
441
-
539
+
540
+ <p>
541
+ The method returns immediately and the positions are subsequently sent to
542
+ the given listener, as they are received.
543
+ </p></div>
544
+<dl>
545
+<dt><span class="paramLabel">Parameters:</span></dt>
546
+<dd><code>listener</code> - the listener to receive the positions.</dd>
547
+<dd><code>fromTime</code> - stored positions (if supported) will be requested from this time
548
+ and forward. The value <code>0</code> is allowed and means all
549
+ historic data.</dd>
550
+<dd><code>toTime</code> - The value <code>Long.MAXVALUE</code> means all data in the future</dd>
551
+</dl>
552
+</li>
553
+</ul>
554
+<a name="subscribePositionsSnapped-com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener-long-long-java.util.UUID...-">
555
+<!-- -->
556
+</a>
557
+<ul class="blockList">
558
+<li class="blockList">
559
+<h4>subscribePositionsSnapped</h4>
560
+<pre>void&nbsp;subscribePositionsSnapped(<a href="../../../../../com/tractrac/subscription/lib/api/competitor/IPositionSnappedListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">IPositionSnappedListener</a>&nbsp;listener,
561
+ long&nbsp;fromTime,
562
+ long&nbsp;toTime,
563
+ java.util.UUID...&nbsp;classIds)</pre>
564
+<div class="block">Subscribes to snapped competitor positions for a given Race and class(es), including
565
+ historic data.
566
+
442 567
<p>
443 568
The method returns immediately and the positions are subsequently sent to
444 569
the given listener, as they are received.
... ...
@@ -450,6 +575,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
450 575
and forward. The value <code>0</code> is allowed and means all
451 576
historic data.</dd>
452 577
<dd><code>toTime</code> - The value <code>Long.MAXVALUE</code> means all data in the future</dd>
578
+<dd><code>classIds</code> - the class ids</dd>
453 579
</dl>
454 580
</li>
455 581
</ul>
... ...
@@ -477,7 +603,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
477 603
<div class="block">Subscribes to offset competitor positions for a given Race. It uses the
478 604
tracking start time and the tracking end time as time interval to receive
479 605
positions.
480
-
606
+
481 607
<p>
482 608
The method returns immediately and the positions are subsequently sent to
483 609
the given listener, as they are received.
... ...
@@ -499,7 +625,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
499 625
long&nbsp;toTime)</pre>
500 626
<div class="block">Subscribes to offset competitor positions for a given Race, including
501 627
historic data.
502
-
628
+
503 629
<p>
504 630
The method returns immediately and the positions are subsequently sent to
505 631
the given listener, as they are received.
... ...
@@ -536,7 +662,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
536 662
<h4>subscribeControlPositions</h4>
537 663
<pre>void&nbsp;subscribeControlPositions(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPointPositionListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPointPositionListener</a>&nbsp;listener)</pre>
538 664
<div class="block">Subscribes to control positions for the race.
539
-
665
+
540 666
<p>
541 667
The method returns immediately and the positions are subsequently sent to
542 668
the given listener, as they are received.
... ...
@@ -563,7 +689,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
563 689
long&nbsp;toTime)</pre>
564 690
<div class="block">Subscribes to control positions for the race, also retrieving historic
565 691
data.
566
-
692
+
567 693
<p>
568 694
The method returns immediately and the positions are subsequently sent to
569 695
the given listener, as they are received.
... ...
@@ -605,7 +731,27 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
605 731
<h4>subscribeControlPassings</h4>
606 732
<pre>void&nbsp;subscribeControlPassings(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPassingsListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPassingsListener</a>&nbsp;listener)</pre>
607 733
<div class="block">Subscribes to control passing data for the specified race.
608
-
734
+
735
+ <p>
736
+ The method returns immediately and the positions are subsequently sent to
737
+ the given listener, as they are received.
738
+ </p></div>
739
+<dl>
740
+<dt><span class="paramLabel">Parameters:</span></dt>
741
+<dd><code>listener</code> - the listener to receive the control passings.</dd>
742
+</dl>
743
+</li>
744
+</ul>
745
+<a name="subscribeControlPassings-com.tractrac.subscription.lib.api.control.IControlPassingsListener-java.util.UUID...-">
746
+<!-- -->
747
+</a>
748
+<ul class="blockList">
749
+<li class="blockList">
750
+<h4>subscribeControlPassings</h4>
751
+<pre>void&nbsp;subscribeControlPassings(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlPassingsListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlPassingsListener</a>&nbsp;listener,
752
+ java.util.UUID...&nbsp;classIds)</pre>
753
+<div class="block">Subscribes to control passing data for the specified race and a class(es)
754
+
609 755
<p>
610 756
The method returns immediately and the positions are subsequently sent to
611 757
the given listener, as they are received.
... ...
@@ -613,6 +759,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
613 759
<dl>
614 760
<dt><span class="paramLabel">Parameters:</span></dt>
615 761
<dd><code>listener</code> - the listener to receive the control passings.</dd>
762
+<dd><code>classIds</code> - the class ids</dd>
616 763
</dl>
617 764
</li>
618 765
</ul>
... ...
@@ -638,7 +785,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
638 785
<h4>subscribeRaceTimesChanges</h4>
639 786
<pre>void&nbsp;subscribeRaceTimesChanges(<a href="../../../../../com/tractrac/subscription/lib/api/race/IRaceStartStopTimesChangeListener.html" title="interface in com.tractrac.subscription.lib.api.race">IRaceStartStopTimesChangeListener</a>&nbsp;listener)</pre>
640 787
<div class="block">Subscribes to changes in race start and stop times.
641
-
788
+
642 789
<p>
643 790
The method returns immediately and the changes are subsequently sent to the
644 791
given listener, as they are received.
... ...
@@ -663,24 +810,6 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
663 810
</dl>
664 811
</li>
665 812
</ul>
666
-<a name="subscribeRoutes-com.tractrac.subscription.lib.api.route.IRoutesListener-">
667
-<!-- -->
668
-</a>
669
-<ul class="blockList">
670
-<li class="blockList">
671
-<h4>subscribeRoutes</h4>
672
-<pre>void&nbsp;subscribeRoutes(<a href="../../../../../com/tractrac/subscription/lib/api/route/IRoutesListener.html" title="interface in com.tractrac.subscription.lib.api.route">IRoutesListener</a>&nbsp;listener)</pre>
673
-<div class="block"><p>
674
- Subscriber to route changes. A race change happens when an static property
675
- of the route changes.
676
-
677
- </p></div>
678
-<dl>
679
-<dt><span class="paramLabel">Parameters:</span></dt>
680
-<dd><code>listener</code> - the listener used in the subscribe method</dd>
681
-</dl>
682
-</li>
683
-</ul>
684 813
<a name="subscribeRouteChanges-com.tractrac.subscription.lib.api.control.IControlRouteChangeListener-">
685 814
<!-- -->
686 815
</a>
... ...
@@ -689,7 +818,7 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
689 818
<h4>subscribeRouteChanges</h4>
690 819
<pre>void&nbsp;subscribeRouteChanges(<a href="../../../../../com/tractrac/subscription/lib/api/control/IControlRouteChangeListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlRouteChangeListener</a>&nbsp;listener)</pre>
691 820
<div class="block">Subscribes to route changes for a given Race.
692
-
821
+
693 822
<p>
694 823
The method returns immediately and the positions are subsequently sent to
695 824
the given listener, as they are received.
... ...
@@ -700,22 +829,6 @@ extends <a href="../../../../../com/tractrac/subscription/lib/api/ISubscriber.ht
700 829
</dl>
701 830
</li>
702 831
</ul>
703
-<a name="unsubscribeRoutes-com.tractrac.subscription.lib.api.route.IRoutesListener-">
704
-<!-- -->
705
-</a>
706
-<ul class="blockList">
707
-<li class="blockList">
708
-<h4>unsubscribeRoutes</h4>
709
-<pre>void&nbsp;unsubscribeRoutes(<a href="../../../../../com/tractrac/subscription/lib/api/route/IRoutesListener.html" title="interface in com.tractrac.subscription.lib.api.route">IRoutesListener</a>&nbsp;listener)</pre>
710
-<div class="block"><p>
711
- Unsubscribes to route changes for a given Race.
712
- </p></div>
713
-<dl>
714
-<dt><span class="paramLabel">Parameters:</span></dt>
715
-<dd><code>listener</code> - the listener used in the subscribe method</dd>
716
-</dl>
717
-</li>
718
-</ul>
719 832
<a name="unsubscribeRouteChanges-com.tractrac.subscription.lib.api.control.IControlRouteChangeListener-">
720 833
<!-- -->
721 834
</a>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/ISubscriber.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>ISubscriber</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/ISubscriberFactory.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>ISubscriberFactory</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/ISubscriberListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>ISubscriberListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/SubscriberInitializationException.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>SubscriberInitializationException</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
... ...
@@ -149,6 +149,9 @@ extends java.lang.Exception</pre>
149 149
<tr class="altColor">
150 150
<td class="colOne"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/SubscriberInitializationException.html#SubscriberInitializationException-java.lang.Exception-">SubscriberInitializationException</a></span>(java.lang.Exception&nbsp;ex)</code>&nbsp;</td>
151 151
</tr>
152
+<tr class="rowColor">
153
+<td class="colOne"><code><span class="memberNameLink"><a href="../../../../../com/tractrac/subscription/lib/api/SubscriberInitializationException.html#SubscriberInitializationException-java.lang.String-">SubscriberInitializationException</a></span>(java.lang.String&nbsp;message)</code>&nbsp;</td>
154
+</tr>
152 155
</table>
153 156
</li>
154 157
</ul>
... ...
@@ -197,6 +200,15 @@ extends java.lang.Exception</pre>
197 200
<!-- -->
198 201
</a>
199 202
<h3>Constructor Detail</h3>
203
+<a name="SubscriberInitializationException-java.lang.String-">
204
+<!-- -->
205
+</a>
206
+<ul class="blockList">
207
+<li class="blockList">
208
+<h4>SubscriberInitializationException</h4>
209
+<pre>public&nbsp;SubscriberInitializationException(java.lang.String&nbsp;message)</pre>
210
+</li>
211
+</ul>
200 212
<a name="SubscriberInitializationException-java.lang.Exception-">
201 213
<!-- -->
202 214
</a>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/SubscriptionLocator.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>SubscriptionLocator</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/competitor/ICompetitorSensorDataListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>ICompetitorSensorDataListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/competitor/ICompetitorsListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>ICompetitorsListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/competitor/IPositionListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IPositionListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/competitor/IPositionOffsetListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IPositionOffsetListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/competitor/IPositionSnappedListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IPositionSnappedListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/competitor/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.competitor</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/competitor/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.competitor</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/competitor/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.competitor Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/control/IControlPassingsListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IControlPassingsListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/control/IControlPointPositionListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IControlPointPositionListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/control/IControlPointSensorDataListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IControlPointSensorDataListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/control/IControlRouteChangeListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IControlRouteChangeListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
... ...
@@ -18,7 +18,7 @@
18 18
catch(err) {
19 19
}
20 20
//-->
21
-var methods = {"i0":6};
21
+var methods = {"i0":6,"i1":6};
22 22
var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],4:["t3","Abstract Methods"]};
23 23
var altColor = "altColor";
24 24
var rowColor = "rowColor";
... ...
@@ -133,7 +133,14 @@ extends <a href="../../../../../../com/tractrac/subscription/lib/api/ISubscriber
133 133
<td class="colFirst"><code>void</code></td>
134 134
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../com/tractrac/subscription/lib/api/control/IControlRouteChangeListener.html#gotRouteChange-com.tractrac.model.lib.api.route.IControlRoute-long-">gotRouteChange</a></span>(<a href="../../../../../../com/tractrac/model/lib/api/route/IControlRoute.html" title="interface in com.tractrac.model.lib.api.route">IControlRoute</a>&nbsp;controlRoute,
135 135
long&nbsp;timeStamp)</code>
136
-<div class="block">Invoked when updates to a route arrives</div>
136
+<div class="block">Invoked when updates to a control route arrives</div>
137
+</td>
138
+</tr>
139
+<tr id="i1" class="rowColor">
140
+<td class="colFirst"><code>void</code></td>
141
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../com/tractrac/subscription/lib/api/control/IControlRouteChangeListener.html#gotRouteChange-com.tractrac.model.lib.api.route.IPathRoute-long-">gotRouteChange</a></span>(<a href="../../../../../../com/tractrac/model/lib/api/route/IPathRoute.html" title="interface in com.tractrac.model.lib.api.route">IPathRoute</a>&nbsp;pathRoute,
142
+ long&nbsp;timeStamp)</code>
143
+<div class="block">Invoked when updates to a path route arrives</div>
137 144
</td>
138 145
</tr>
139 146
</table>
... ...
@@ -154,12 +161,12 @@ extends <a href="../../../../../../com/tractrac/subscription/lib/api/ISubscriber
154 161
<a name="gotRouteChange-com.tractrac.model.lib.api.route.IControlRoute-long-">
155 162
<!-- -->
156 163
</a>
157
-<ul class="blockListLast">
164
+<ul class="blockList">
158 165
<li class="blockList">
159 166
<h4>gotRouteChange</h4>
160 167
<pre>void&nbsp;gotRouteChange(<a href="../../../../../../com/tractrac/model/lib/api/route/IControlRoute.html" title="interface in com.tractrac.model.lib.api.route">IControlRoute</a>&nbsp;controlRoute,
161 168
long&nbsp;timeStamp)</pre>
162
-<div class="block">Invoked when updates to a route arrives</div>
169
+<div class="block">Invoked when updates to a control route arrives</div>
163 170
<dl>
164 171
<dt><span class="paramLabel">Parameters:</span></dt>
165 172
<dd><code>controlRoute</code> - the new configuration of the route.</dd>
... ...
@@ -167,6 +174,22 @@ extends <a href="../../../../../../com/tractrac/subscription/lib/api/ISubscriber
167 174
</dl>
168 175
</li>
169 176
</ul>
177
+<a name="gotRouteChange-com.tractrac.model.lib.api.route.IPathRoute-long-">
178
+<!-- -->
179
+</a>
180
+<ul class="blockListLast">
181
+<li class="blockList">
182
+<h4>gotRouteChange</h4>
183
+<pre>void&nbsp;gotRouteChange(<a href="../../../../../../com/tractrac/model/lib/api/route/IPathRoute.html" title="interface in com.tractrac.model.lib.api.route">IPathRoute</a>&nbsp;pathRoute,
184
+ long&nbsp;timeStamp)</pre>
185
+<div class="block">Invoked when updates to a path route arrives</div>
186
+<dl>
187
+<dt><span class="paramLabel">Parameters:</span></dt>
188
+<dd><code>pathRoute</code> - the new configuration of the route.</dd>
189
+<dd><code>timeStamp</code> - a time stamp when the new route is valid.</dd>
190
+</dl>
191
+</li>
192
+</ul>
170 193
</li>
171 194
</ul>
172 195
</li>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/control/IControlsListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IControlsListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/control/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.control</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/control/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.control</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/control/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.control Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/IConnectionStatusListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IConnectionStatusListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/IEventMessageListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IEventMessageListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/ILiveDataEvent.StatusType.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>ILiveDataEvent.StatusType</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/ILiveDataEvent.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>ILiveDataEvent</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/IMessage.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IMessage</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/IServerTimeListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IServerTimeListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/IStoredDataEvent.Type.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IStoredDataEvent.Type</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/IStoredDataEvent.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IStoredDataEvent</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.event</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.event</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/event/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.event Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
... ...
@@ -95,8 +95,8 @@
95 95
<ul>
96 96
<li type="circle">java.lang.Enum&lt;E&gt; (implements java.lang.Comparable&lt;T&gt;, java.io.Serializable)
97 97
<ul>
98
-<li type="circle">com.tractrac.subscription.lib.api.event.<a href="../../../../../../com/tractrac/subscription/lib/api/event/IStoredDataEvent.Type.html" title="enum in com.tractrac.subscription.lib.api.event"><span class="typeNameLink">IStoredDataEvent.Type</span></a></li>
99 98
<li type="circle">com.tractrac.subscription.lib.api.event.<a href="../../../../../../com/tractrac/subscription/lib/api/event/ILiveDataEvent.StatusType.html" title="enum in com.tractrac.subscription.lib.api.event"><span class="typeNameLink">ILiveDataEvent.StatusType</span></a></li>
99
+<li type="circle">com.tractrac.subscription.lib.api.event.<a href="../../../../../../com/tractrac/subscription/lib/api/event/IStoredDataEvent.Type.html" title="enum in com.tractrac.subscription.lib.api.event"><span class="typeNameLink">IStoredDataEvent.Type</span></a></li>
100 100
</ul>
101 101
</li>
102 102
</ul>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/race/IRaceCompetitorListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IRaceCompetitorListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/race/IRaceMessageListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IRaceMessageListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/race/IRaceStartStopTimesChangeListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IRaceStartStopTimesChangeListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/race/IRacesListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IRacesListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/race/IStartStopTimesChangeListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:08 UTC 2018 -->
6 6
<title>IStartStopTimesChangeListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/race/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.race</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/race/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.race</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/race/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.race Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/route/IRoutesListener.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>IRoutesListener</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/route/package-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.route</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/route/package-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.route</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/com/tractrac/subscription/lib/api/route/package-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>com.tractrac.subscription.lib.api.route Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../../../../../../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/constant-values.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>Constant Field Values</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/deprecated-list.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>Deprecated List</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/help-doc.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>API Help</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-1.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>A-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-10.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>L-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-11.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>M-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-12.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>N-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-13.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>O-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-14.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>R-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-15.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>S-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
... ...
@@ -161,6 +161,10 @@
161 161
<dd>
162 162
<div class="block">Subscribes to control passing data for the specified race.</div>
163 163
</dd>
164
+<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeControlPassings-com.tractrac.subscription.lib.api.control.IControlPassingsListener-java.util.UUID...-">subscribeControlPassings(IControlPassingsListener, UUID...)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
165
+<dd>
166
+<div class="block">Subscribes to control passing data for the specified race and a class(es)</div>
167
+</dd>
164 168
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeControlPositions-com.tractrac.subscription.lib.api.control.IControlPointPositionListener-">subscribeControlPositions(IControlPointPositionListener)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
165 169
<dd>
166 170
<div class="block">Subscribes to control positions for the race.</div>
... ...
@@ -196,10 +200,18 @@
196 200
<dd>
197 201
<div class="block">Subscribes to competitor positions for a given Race.</div>
198 202
</dd>
203
+<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-java.util.UUID...-">subscribePositions(IPositionListener, UUID...)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
204
+<dd>
205
+<div class="block">Subscribes to competitor positions for a given Race and class(es).</div>
206
+</dd>
199 207
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-long-long-">subscribePositions(IPositionListener, long, long)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
200 208
<dd>
201 209
<div class="block">Subscribes to competitor positions for a given Race.</div>
202 210
</dd>
211
+<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositions-com.tractrac.subscription.lib.api.competitor.IPositionListener-long-long-java.util.UUID...-">subscribePositions(IPositionListener, long, long, UUID...)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
212
+<dd>
213
+<div class="block">Subscribes to competitor positions for a given Race and class(es).</div>
214
+</dd>
203 215
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositionsOffset-com.tractrac.subscription.lib.api.competitor.IPositionOffsetListener-">subscribePositionsOffset(IPositionOffsetListener)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
204 216
<dd>
205 217
<div class="block">Subscribes to offset competitor positions for a given Race.</div>
... ...
@@ -213,11 +225,20 @@
213 225
<dd>
214 226
<div class="block">Subscribes to snapped competitor positions for a given Race.</div>
215 227
</dd>
228
+<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositionsSnapped-com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener-java.util.UUID...-">subscribePositionsSnapped(IPositionSnappedListener, UUID...)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
229
+<dd>
230
+<div class="block">Subscribes to snapped competitor positions for a given Race and class(es).</div>
231
+</dd>
216 232
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositionsSnapped-com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener-long-long-">subscribePositionsSnapped(IPositionSnappedListener, long, long)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
217 233
<dd>
218 234
<div class="block">Subscribes to snapped competitor positions for a given Race, including
219 235
historic data.</div>
220 236
</dd>
237
+<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribePositionsSnapped-com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener-long-long-java.util.UUID...-">subscribePositionsSnapped(IPositionSnappedListener, long, long, UUID...)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
238
+<dd>
239
+<div class="block">Subscribes to snapped competitor positions for a given Race and class(es), including
240
+ historic data.</div>
241
+</dd>
221 242
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeRaceCompetitor-com.tractrac.subscription.lib.api.race.IRaceCompetitorListener-">subscribeRaceCompetitor(IRaceCompetitorListener)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
222 243
<dd>
223 244
<div class="block">Subscribes to race competitor for a given Race.</div>
... ...
@@ -239,17 +260,14 @@
239 260
<dd>
240 261
<div class="block">This exception is thrown when it is not possible to create a susbcriber.</div>
241 262
</dd>
263
+<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/SubscriberInitializationException.html#SubscriberInitializationException-java.lang.String-">SubscriberInitializationException(String)</a></span> - Constructor for exception com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/SubscriberInitializationException.html" title="class in com.tractrac.subscription.lib.api">SubscriberInitializationException</a></dt>
264
+<dd>&nbsp;</dd>
242 265
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/SubscriberInitializationException.html#SubscriberInitializationException-java.lang.Exception-">SubscriberInitializationException(Exception)</a></span> - Constructor for exception com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/SubscriberInitializationException.html" title="class in com.tractrac.subscription.lib.api">SubscriberInitializationException</a></dt>
243 266
<dd>&nbsp;</dd>
244 267
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeRouteChanges-com.tractrac.subscription.lib.api.control.IControlRouteChangeListener-">subscribeRouteChanges(IControlRouteChangeListener)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
245 268
<dd>
246 269
<div class="block">Subscribes to route changes for a given Race.</div>
247 270
</dd>
248
-<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#subscribeRoutes-com.tractrac.subscription.lib.api.route.IRoutesListener-">subscribeRoutes(IRoutesListener)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
249
-<dd>
250
-<div class="block">
251
- Subscriber to route changes.</div>
252
-</dd>
253 271
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IEventSubscriber.html#subscribeServerTime-com.tractrac.subscription.lib.api.event.IServerTimeListener-">subscribeServerTime(IServerTimeListener)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IEventSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IEventSubscriber</a></dt>
254 272
<dd>
255 273
<div class="block">Subscribe to messages for the server time.</div>
java/com.tractrac.clientmodule/javadoc/index-files/index-16.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>T-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-17.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>U-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
... ...
@@ -144,11 +144,6 @@
144 144
<dd>
145 145
<div class="block">Unsubscribes to route changes for a given Race.</div>
146 146
</dd>
147
-<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html#unsubscribeRoutes-com.tractrac.subscription.lib.api.route.IRoutesListener-">unsubscribeRoutes(IRoutesListener)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IRaceSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IRaceSubscriber</a></dt>
148
-<dd>
149
-<div class="block">
150
- Unsubscribes to route changes for a given Race.</div>
151
-</dd>
152 147
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/IEventSubscriber.html#unsubscribeServerTime-com.tractrac.subscription.lib.api.event.IServerTimeListener-">unsubscribeServerTime(IServerTimeListener)</a></span> - Method in interface com.tractrac.subscription.lib.api.<a href="../com/tractrac/subscription/lib/api/IEventSubscriber.html" title="interface in com.tractrac.subscription.lib.api">IEventSubscriber</a></dt>
153 148
<dd>
154 149
<div class="block">Unsubscribes to messages for the server time.</div>
java/com.tractrac.clientmodule/javadoc/index-files/index-18.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>V-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-2.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>B-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-3.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>C-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-4.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>D-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-5.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>E-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-6.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>F-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-7.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>G-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
... ...
@@ -406,7 +406,7 @@
406 406
<dt><span class="memberNameLink"><a href="../com/tractrac/model/lib/api/data/IControlPassings.html#getPassings--">getPassings()</a></span> - Method in interface com.tractrac.model.lib.api.data.<a href="../com/tractrac/model/lib/api/data/IControlPassings.html" title="interface in com.tractrac.model.lib.api.data">IControlPassings</a></dt>
407 407
<dd>
408 408
<div class="block">
409
- Returns a list of control passings.</div>
409
+ Returns a list of control passings sorted by time.</div>
410 410
</dd>
411 411
<dt><span class="memberNameLink"><a href="../com/tractrac/model/lib/api/ModelLocator.html#getPathRouteFactory--">getPathRouteFactory()</a></span> - Static method in class com.tractrac.model.lib.api.<a href="../com/tractrac/model/lib/api/ModelLocator.html" title="class in com.tractrac.model.lib.api">ModelLocator</a></dt>
412 412
<dd>
... ...
@@ -753,7 +753,11 @@
753 753
</dd>
754 754
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/control/IControlRouteChangeListener.html#gotRouteChange-com.tractrac.model.lib.api.route.IControlRoute-long-">gotRouteChange(IControlRoute, long)</a></span> - Method in interface com.tractrac.subscription.lib.api.control.<a href="../com/tractrac/subscription/lib/api/control/IControlRouteChangeListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlRouteChangeListener</a></dt>
755 755
<dd>
756
-<div class="block">Invoked when updates to a route arrives</div>
756
+<div class="block">Invoked when updates to a control route arrives</div>
757
+</dd>
758
+<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/control/IControlRouteChangeListener.html#gotRouteChange-com.tractrac.model.lib.api.route.IPathRoute-long-">gotRouteChange(IPathRoute, long)</a></span> - Method in interface com.tractrac.subscription.lib.api.control.<a href="../com/tractrac/subscription/lib/api/control/IControlRouteChangeListener.html" title="interface in com.tractrac.subscription.lib.api.control">IControlRouteChangeListener</a></dt>
759
+<dd>
760
+<div class="block">Invoked when updates to a path route arrives</div>
757 761
</dd>
758 762
<dt><span class="memberNameLink"><a href="../com/tractrac/subscription/lib/api/competitor/ICompetitorSensorDataListener.html#gotSensorData-com.tractrac.model.lib.api.event.IRaceCompetitor-com.tractrac.model.lib.api.sensor.ISensorData-">gotSensorData(IRaceCompetitor, ISensorData)</a></span> - Method in interface com.tractrac.subscription.lib.api.competitor.<a href="../com/tractrac/subscription/lib/api/competitor/ICompetitorSensorDataListener.html" title="interface in com.tractrac.subscription.lib.api.competitor">ICompetitorSensorDataListener</a></dt>
759 763
<dd>
java/com.tractrac.clientmodule/javadoc/index-files/index-8.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>H-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index-files/index-9.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>I-Index</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="../script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/index.html
... ...
@@ -2,7 +2,7 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>Generated Documentation (Untitled)</title>
7 7
<script type="text/javascript">
8 8
tmpTargetPage = "" + window.location.search;
java/com.tractrac.clientmodule/javadoc/overview-frame.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>Overview List</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/overview-summary.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>Overview</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/javadoc/overview-tree.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>Class Hierarchy</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="script.js"></script>
10 10
</head>
... ...
@@ -337,12 +337,12 @@
337 337
<ul>
338 338
<li type="circle">java.lang.Enum&lt;E&gt; (implements java.lang.Comparable&lt;T&gt;, java.io.Serializable)
339 339
<ul>
340
-<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/RaceVisibilityType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">RaceVisibilityType</span></a></li>
341
-<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/RaceCompetitorStatusType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">RaceCompetitorStatusType</span></a></li>
342
-<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/DataSource.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">DataSource</span></a></li>
343
-<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/StartTimeType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">StartTimeType</span></a></li>
344
-<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/EventType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">EventType</span></a></li>
345 340
<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/RaceStatusType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">RaceStatusType</span></a></li>
341
+<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/EventType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">EventType</span></a></li>
342
+<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/StartTimeType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">StartTimeType</span></a></li>
343
+<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/DataSource.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">DataSource</span></a></li>
344
+<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/RaceCompetitorStatusType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">RaceCompetitorStatusType</span></a></li>
345
+<li type="circle">com.tractrac.model.lib.api.event.<a href="com/tractrac/model/lib/api/event/RaceVisibilityType.html" title="enum in com.tractrac.model.lib.api.event"><span class="typeNameLink">RaceVisibilityType</span></a></li>
346 346
<li type="circle">com.tractrac.subscription.lib.api.event.<a href="com/tractrac/subscription/lib/api/event/IStoredDataEvent.Type.html" title="enum in com.tractrac.subscription.lib.api.event"><span class="typeNameLink">IStoredDataEvent.Type</span></a></li>
347 347
<li type="circle">com.tractrac.subscription.lib.api.event.<a href="com/tractrac/subscription/lib/api/event/ILiveDataEvent.StatusType.html" title="enum in com.tractrac.subscription.lib.api.event"><span class="typeNameLink">ILiveDataEvent.StatusType</span></a></li>
348 348
</ul>
java/com.tractrac.clientmodule/javadoc/serialized-form.html
... ...
@@ -2,9 +2,9 @@
2 2
<!-- NewPage -->
3 3
<html lang="en">
4 4
<head>
5
-<!-- Generated by javadoc (1.8.0_161) on Fri Mar 02 11:40:31 UTC 2018 -->
5
+<!-- Generated by javadoc (1.8.0_161) on Mon Jul 30 09:28:09 UTC 2018 -->
6 6
<title>Serialized Form</title>
7
-<meta name="date" content="2018-03-02">
7
+<meta name="date" content="2018-07-30">
8 8
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
9 9
<script type="text/javascript" src="script.js"></script>
10 10
</head>
java/com.tractrac.clientmodule/lib/TracAPI-src.jar
java/com.tractrac.clientmodule/pom.xml
... ...
@@ -8,6 +8,6 @@
8 8
<version>1.0.0-SNAPSHOT</version>
9 9
</parent>
10 10
<artifactId>com.tractrac.clientmodule</artifactId>
11
- <version>3.10.1</version>
11
+ <version>3.11.0</version>
12 12
<packaging>eclipse-plugin</packaging>
13 13
</project>
java/com.tractrac.clientmodule/src/com/tractrac/subscription/app/tracapi/AbstractListener.java
... ...
@@ -0,0 +1,190 @@
1
+package com.tractrac.subscription.app.tracapi;
2
+
3
+import java.net.URI;
4
+import java.util.UUID;
5
+
6
+import com.tractrac.model.lib.api.data.IControlPassings;
7
+import com.tractrac.model.lib.api.data.IMessageData;
8
+import com.tractrac.model.lib.api.data.IPosition;
9
+import com.tractrac.model.lib.api.data.IPositionOffset;
10
+import com.tractrac.model.lib.api.data.IPositionSnapped;
11
+import com.tractrac.model.lib.api.data.IStartStopData;
12
+import com.tractrac.model.lib.api.event.DataSource;
13
+import com.tractrac.model.lib.api.event.ICompetitor;
14
+import com.tractrac.model.lib.api.event.IEvent;
15
+import com.tractrac.model.lib.api.event.IRace;
16
+import com.tractrac.model.lib.api.event.IRaceCompetitor;
17
+import com.tractrac.model.lib.api.route.IControl;
18
+import com.tractrac.model.lib.api.route.IControlRoute;
19
+import com.tractrac.model.lib.api.route.IPathRoute;
20
+import com.tractrac.model.lib.api.sensor.ISensorData;
21
+import com.tractrac.subscription.lib.api.competitor.ICompetitorSensorDataListener;
22
+import com.tractrac.subscription.lib.api.competitor.ICompetitorsListener;
23
+import com.tractrac.subscription.lib.api.competitor.IPositionListener;
24
+import com.tractrac.subscription.lib.api.competitor.IPositionOffsetListener;
25
+import com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener;
26
+import com.tractrac.subscription.lib.api.control.IControlPassingsListener;
27
+import com.tractrac.subscription.lib.api.control.IControlPointPositionListener;
28
+import com.tractrac.subscription.lib.api.control.IControlRouteChangeListener;
29
+import com.tractrac.subscription.lib.api.control.IControlsListener;
30
+import com.tractrac.subscription.lib.api.event.IConnectionStatusListener;
31
+import com.tractrac.subscription.lib.api.event.IEventMessageListener;
32
+import com.tractrac.subscription.lib.api.event.ILiveDataEvent;
33
+import com.tractrac.subscription.lib.api.event.IStoredDataEvent;
34
+import com.tractrac.subscription.lib.api.race.IRaceMessageListener;
35
+import com.tractrac.subscription.lib.api.race.IRaceStartStopTimesChangeListener;
36
+import com.tractrac.subscription.lib.api.race.IRacesListener;
37
+
38
+/**
39
+ * @author <a href="mailto:jorge@tractrac.dk">Jorge Piera Llodr&aacute;</a>
40
+ */
41
+public abstract class AbstractListener implements IEventMessageListener,
42
+ IRaceMessageListener, IPositionListener, IPositionOffsetListener,
43
+ IPositionSnappedListener, IConnectionStatusListener, IControlPointPositionListener,
44
+ IControlPassingsListener, IRaceStartStopTimesChangeListener,
45
+ IControlRouteChangeListener, ICompetitorSensorDataListener,
46
+ IRacesListener, ICompetitorsListener, IControlsListener {
47
+
48
+ @Override
49
+ public void gotStoredDataEvent(IStoredDataEvent storedDataEvent) {
50
+
51
+ }
52
+
53
+ @Override
54
+ public void gotLiveDataEvent(ILiveDataEvent liveDataEvent) {
55
+
56
+ }
57
+
58
+ @Override
59
+ public void gotRouteChange(IControlRoute controlRoute, long timeStamp) {
60
+
61
+ }
62
+
63
+ @Override
64
+ public void gotRouteChange(IPathRoute controlRoute, long timeStamp) {
65
+
66
+ }
67
+
68
+ @Override
69
+ public void gotControlPassings(IRaceCompetitor raceCompetitor,
70
+ IControlPassings markPassings) {
71
+
72
+ }
73
+
74
+ @Override
75
+ public void gotControlPointPosition(IControl control, IPosition position, int markNumber) {
76
+
77
+ }
78
+
79
+ @Override
80
+ public void gotPositionSnapped(IRaceCompetitor raceCompetitor,
81
+ IPositionSnapped positionSnapped) {
82
+
83
+ }
84
+
85
+ @Override
86
+ public void gotPositionOffset(IRaceCompetitor raceCompetitor,
87
+ IPositionOffset position) {
88
+
89
+ }
90
+
91
+ @Override
92
+ public void gotPosition(IRaceCompetitor raceCompetitor, IPosition position) {
93
+
94
+ }
95
+
96
+ @Override
97
+ public void gotRaceStartStopTime(IRace race, IStartStopData startStopData) {
98
+
99
+ }
100
+
101
+ @Override
102
+ public void gotTrackingStartStopTime(IRace race, IStartStopData startStopData) {
103
+
104
+ }
105
+
106
+ @Override
107
+ public void gotRaceMessage(IRace race, IMessageData messageData) {
108
+
109
+ }
110
+
111
+ @Override
112
+ public void stopped(Object object) {
113
+
114
+ }
115
+
116
+ @Override
117
+ public void gotEventMessage(IEvent event, IMessageData messageData) {
118
+
119
+ }
120
+
121
+ @Override
122
+ public void gotSensorData(IRaceCompetitor raceCompetitor, ISensorData sensorData) {
123
+
124
+ }
125
+
126
+ @Override
127
+ public void updateCompetitor(ICompetitor competitor) {
128
+
129
+ }
130
+
131
+ @Override
132
+ public void addCompetitor(ICompetitor competitor) {
133
+
134
+ }
135
+
136
+ @Override
137
+ public void deleteCompetitor(UUID competitorId) {
138
+
139
+ }
140
+
141
+ @Override
142
+ public void updateControl(IControl control) {
143
+
144
+ }
145
+
146
+ @Override
147
+ public void addControl(IControl control) {
148
+
149
+ }
150
+
151
+ @Override
152
+ public void deleteControl(UUID controlId) {
153
+
154
+ }
155
+
156
+ @Override
157
+ public void updateRace(IRace race) {
158
+
159
+ }
160
+
161
+ @Override
162
+ public void addRace(IRace race) {
163
+
164
+ }
165
+
166
+ @Override
167
+ public void deleteRace(UUID raceId) {
168
+
169
+ }
170
+
171
+ @Override
172
+ public void reloadRace(UUID raceId) {
173
+
174
+ }
175
+
176
+ @Override
177
+ public void abandonRace(UUID raceId) {
178
+
179
+ }
180
+
181
+ @Override
182
+ public void startTracking(UUID raceId) {
183
+
184
+ }
185
+
186
+ @Override
187
+ public void dataSourceChanged(IRace race, DataSource oldDataSource, URI oldLiveURI, URI oldStoredURI) {
188
+
189
+ }
190
+}
java/com.tractrac.clientmodule/src/com/tractrac/subscription/app/tracapi/DelayListener.java
... ...
@@ -0,0 +1,55 @@
1
+package com.tractrac.subscription.app.tracapi;
2
+
3
+import com.tractrac.model.lib.api.data.*;
4
+import com.tractrac.model.lib.api.event.*;
5
+import com.tractrac.model.lib.api.route.IControl;
6
+import com.tractrac.util.lib.api.TimeUtils;
7
+
8
+import java.util.Date;
9
+
10
+/**
11
+ * @author <a href="mailto:jorge@tractrac.dk">Jorge Piera Llodr&aacute;</a>
12
+ */
13
+public class DelayListener extends AbstractListener {
14
+
15
+ @Override
16
+ public void gotControlPointPosition(IControl control, IPosition position, int markNumber) {
17
+ //printDelay(position.getTimestamp(), control.getName());
18
+ }
19
+
20
+ @Override
21
+ public void gotPosition(IRaceCompetitor raceCompetitor, IPosition position) {
22
+ if (!raceCompetitor.getCompetitor().isNonCompeting()) {
23
+ printDelay(position.getTimestamp(), raceCompetitor.getCompetitor().getName());
24
+ }
25
+ }
26
+
27
+ private void printDelay(long sampleTime, String name) {
28
+ long now = new Date().getTime();
29
+ long diff = now - sampleTime;
30
+ int steps = Math.round(diff/100);
31
+ StringBuilder delay = new StringBuilder();
32
+ for (int i = 0 ; i<steps ; i++) {
33
+ delay.append("*");
34
+ }
35
+
36
+ System.out.println(
37
+ String.valueOf(TimeUtils.formatDateInMillis(now)) + ": " +
38
+ String.valueOf(TimeUtils.formatDateInMillis(sampleTime)) + ": " +
39
+ fillString(name, 25) + "-> " +
40
+ delay.toString()
41
+ );
42
+ }
43
+
44
+ public String fillString(String string, int count){
45
+ if (string.length() > count) {
46
+ return string.substring(0, count);
47
+ }
48
+ String out = string;
49
+ for (int i=string.length() ;i<count ; i++) {
50
+ out = out + "-";
51
+ }
52
+ return out;
53
+ }
54
+}
55
+
java/com.tractrac.clientmodule/src/com/tractrac/subscription/app/tracapi/EventListener.java
... ...
@@ -7,42 +7,36 @@
7 7
*/
8 8
package com.tractrac.subscription.app.tracapi;
9 9
10
+import java.net.URI;
11
+import java.util.Date;
12
+import java.util.UUID;
13
+
10 14
import com.tractrac.model.lib.api.data.IControlPassings;
11 15
import com.tractrac.model.lib.api.data.IMessageData;
12 16
import com.tractrac.model.lib.api.data.IPosition;
13 17
import com.tractrac.model.lib.api.data.IPositionOffset;
14 18
import com.tractrac.model.lib.api.data.IPositionSnapped;
15 19
import com.tractrac.model.lib.api.data.IStartStopData;
20
+import com.tractrac.model.lib.api.event.DataSource;
21
+import com.tractrac.model.lib.api.event.ICompetitor;
16 22
import com.tractrac.model.lib.api.event.IEvent;
17 23
import com.tractrac.model.lib.api.event.IRace;
18 24
import com.tractrac.model.lib.api.event.IRaceCompetitor;
19 25
import com.tractrac.model.lib.api.route.IControl;
20 26
import com.tractrac.model.lib.api.route.IControlRoute;
21
-import com.tractrac.subscription.lib.api.competitor.IPositionListener;
22
-import com.tractrac.subscription.lib.api.competitor.IPositionOffsetListener;
23
-import com.tractrac.subscription.lib.api.competitor.IPositionSnappedListener;
24
-import com.tractrac.subscription.lib.api.control.IControlPassingsListener;
25
-import com.tractrac.subscription.lib.api.control.IControlPointPositionListener;
26
-import com.tractrac.subscription.lib.api.control.IControlRouteChangeListener;
27
-import com.tractrac.subscription.lib.api.event.IConnectionStatusListener;
28
-import com.tractrac.subscription.lib.api.event.IEventMessageListener;
27
+import com.tractrac.model.lib.api.sensor.ISensorData;
29 28
import com.tractrac.subscription.lib.api.event.ILiveDataEvent;
30 29
import com.tractrac.subscription.lib.api.event.IStoredDataEvent;
31
-import com.tractrac.subscription.lib.api.race.IRaceMessageListener;
32
-import com.tractrac.subscription.lib.api.race.IRaceStartStopTimesChangeListener;
30
+import com.tractrac.util.lib.api.TimeUtils;
33 31
34 32
/**
35 33
*
36
- * @author <a href="mailto:jorge@tractrac.dk">Jorge Piera Llodr&aacute</a>
34
+ * @author <a href="mailto:jorge@tractrac.dk">Jorge Piera Llodr&aacute;</a>
37 35
*/
38
-public class EventListener implements IEventMessageListener,
39
- IRaceMessageListener, IPositionListener, IPositionOffsetListener,
40
- IPositionSnappedListener, IConnectionStatusListener, IControlPointPositionListener,
41
- IControlPassingsListener, IRaceStartStopTimesChangeListener,
42
- IControlRouteChangeListener {
36
+public class EventListener extends AbstractListener {
43 37
44 38
private static void show(Object obj) {
45
- System.out.println(Thread.currentThread().getName() + ": " + obj);
39
+ System.out.println(String.valueOf(TimeUtils.formatDateInMillis(new Date().getTime())) + ": " + obj);
46 40
}
47 41
48 42
@Override
... ...
@@ -57,7 +51,13 @@ public class EventListener implements IEventMessageListener,
57 51
58 52
@Override
59 53
public void gotRouteChange(IControlRoute controlRoute, long timeStamp) {
60
- show("New route at " + timeStamp + ": " + controlRoute.toString());
54
+ StringBuilder message = new StringBuilder();
55
+ message.append("New route at " + timeStamp + ": " + controlRoute.toString());
56
+ for (int i=0 ; i<controlRoute.getControls().size() ; i++) {
57
+ message.append("\n\t" + i + ": " + controlRoute.getControls().get(i).getName());
58
+ }
59
+ message.append("\n\t" + controlRoute.getMetadata().getText());
60
+ show(message);
61 61
}
62 62
63 63
@Override
... ...
@@ -68,7 +68,11 @@ public class EventListener implements IEventMessageListener,
68 68
69 69
@Override
70 70
public void gotControlPointPosition(IControl control, IPosition position, int markNumber) {
71
- show("New position " + position + " for the mark " + control + ", " + markNumber);
71
+ StringBuilder message = new StringBuilder();
72
+ message.append("COTRLPOS " + markNumber);
73
+ message.append("\t").append(control.getShortName()).append("\t");
74
+ message.append(position.toString());
75
+ show(message.toString());
72 76
}
73 77
74 78
@Override
... ...
@@ -85,7 +89,13 @@ public class EventListener implements IEventMessageListener,
85 89
86 90
@Override
87 91
public void gotPosition(IRaceCompetitor raceCompetitor, IPosition position) {
88
- show("New position " + position + " for the competitor " + raceCompetitor.getCompetitor().toString());
92
+ StringBuilder message = new StringBuilder();
93
+ message.append("POSITION");
94
+ if (raceCompetitor != null) {
95
+ message.append("\t").append(raceCompetitor.getCompetitor().getShortName()).append("\t");
96
+ }
97
+ message.append(position.toString());
98
+ show(message.toString());
89 99
}
90 100
91 101
@Override
... ...
@@ -112,4 +122,85 @@ public class EventListener implements IEventMessageListener,
112 122
public void gotEventMessage(IEvent event, IMessageData messageData) {
113 123
show("New event message " + messageData.toString());
114 124
}
125
+
126
+ @Override
127
+ public void gotSensorData(IRaceCompetitor raceCompetitor, ISensorData sensorData) {
128
+ StringBuilder message = new StringBuilder();
129
+ message.append("SENSOR");
130
+ if (raceCompetitor != null) {
131
+ message.append("\t").append(raceCompetitor.getCompetitor().getShortName()).append("\t");
132
+ }
133
+ message.append(sensorData.toString());
134
+ show(message.toString());
135
+ }
136
+
137
+ @Override
138
+ public void updateCompetitor(ICompetitor competitor) {
139
+ show("UPDATE COMPETITOR " + competitor.toString());
140
+ }
141
+
142
+ @Override
143
+ public void addCompetitor(ICompetitor competitor) {
144
+ show("ADD COMPETITOR " + competitor.toString());
145
+ }
146
+
147
+ @Override
148
+ public void deleteCompetitor(UUID competitorId) {
149
+ show("DELETE COMPETITOR");
150
+ }
151
+
152
+ @Override
153
+ public void updateControl(IControl control) {
154
+ show("UPDATE CONTROL " + control.toString());
155
+ }
156
+
157
+ @Override
158
+ public void addControl(IControl control) {
159
+ show("ADD CONTROL " + control.toString());
160
+ }
161
+
162
+ @Override
163
+ public void deleteControl(UUID controlId) {
164
+ show("DELETE CONTROL " + controlId);
165
+ }
166
+
167
+ @Override
168
+ public void updateRace(IRace race) {
169
+ show("UPDATE RACE " + race.toString() +
170
+ "[" + TimeUtils.formatDate(race.getTrackingStartTime()) +
171
+ "," + TimeUtils.formatDate(race.getTrackingEndTime()) + "] - " +
172
+ TimeUtils.formatDate(race.getRaceStartTime()) +
173
+ " liveDelay = " + race.getLiveDelay()
174
+ );
175
+ }
176
+
177
+ @Override
178
+ public void addRace(IRace race) {
179
+ show("ADD RACE " + race.toString());
180
+ }
181
+
182
+ @Override
183
+ public void deleteRace(UUID raceId) {
184
+ show("DELETE RACE " + raceId);
185
+ }
186
+
187
+ @Override
188
+ public void reloadRace(UUID raceId) {
189
+ show("RELOAD RACE " + raceId);
190
+ }
191
+
192
+ @Override
193
+ public void abandonRace(UUID raceId) {
194
+ show("ABANDON RACE " + raceId);
195
+ }
196
+
197
+ @Override
198
+ public void startTracking(UUID raceId) {
199
+ show("START TRACKING " + raceId);
200
+ }
201
+
202
+ @Override
203
+ public void dataSourceChanged(IRace race, DataSource oldDataSource, URI oldLiveURI, URI oldStoredURI) {
204
+ show("DATA SOURCE CHANGE " + race);
205
+ }
115 206
}
java/com.tractrac.clientmodule/src/com/tractrac/subscription/app/tracapi/Main.java
... ...
@@ -22,21 +22,23 @@ import java.net.URI;
22 22
import java.net.URISyntaxException;
23 23
24 24
/**
25
- *
26
- * @author <a href="mailto:jorge@tractrac.dk">Jorge Piera Llodr&aacute</a>
25
+ *
26
+ * @author <a href="mailto:jorge@tractrac.dk">Jorge Piera Llodr&aacute;</a>
27 27
*/
28 28
public class Main {
29 29
30 30
/**
31 31
* @param args
32 32
* the command line arguments
33
- * @throws CreateModelException
33
+ * @throws CreateModelException
34 34
*/
35 35
public static void main(String[] args) throws URISyntaxException,
36 36
MalformedURLException, FileNotFoundException, IOException,
37 37
SubscriberInitializationException, CreateModelException, TimeOutException {
38 38
39
- URI paramURI = parseArguments(args);
39
+ Object[] myArgs = parseArguments(args);
40
+ URI paramURI = (URI)myArgs[0];
41
+ boolean measureDelay = (boolean)myArgs[1];;
40 42
41 43
// Create the event object
42 44
IEventFactory eventFactory = ModelLocator.getEventFactory();
... ...
@@ -46,44 +48,55 @@ public class Main {
46 48
ISubscriberFactory subscriberFactory = SubscriptionLocator.getSusbcriberFactory();
47 49
IEventSubscriber eventSubscriber = subscriberFactory.createEventSubscriber(race.getEvent());
48 50
49
- EventListener eventListener = new EventListener();
50
- eventSubscriber.subscribeConnectionStatus(eventListener);
51
- eventSubscriber.subscribeEventMessages(eventListener);
52
-
51
+ AbstractListener listener;
52
+ if (measureDelay) {
53
+ listener = new DelayListener();
54
+ } else {
55
+ listener = new EventListener();
56
+ }
57
+
58
+ eventSubscriber.subscribeConnectionStatus(listener);
59
+ eventSubscriber.subscribeEventMessages(listener);
60
+ eventSubscriber.subscribeRaces(listener);
61
+ eventSubscriber.subscribeControls(listener);
62
+ eventSubscriber.subscribeCompetitors(listener);
63
+
53 64
IRaceSubscriber raceSubscriber = subscriberFactory.createRaceSubscriber(race);
54
- raceSubscriber.subscribeConnectionStatus(eventListener);
55
- raceSubscriber.subscribeControlPositions(eventListener);
56
- raceSubscriber.subscribePositions(eventListener);
57
- raceSubscriber.subscribePositionsSnapped(eventListener);
58
- raceSubscriber.subscribeControlPassings(eventListener);
59
- raceSubscriber.subscribeRaceMessages(eventListener);
60
- raceSubscriber.subscribeRaceMessages(eventListener);
61
- raceSubscriber.subscribeRaceTimesChanges(eventListener);
62
- raceSubscriber.subscribeRouteChanges(eventListener);
63
- raceSubscriber.start();
64
- eventSubscriber.start();
65
-
65
+ raceSubscriber.subscribeConnectionStatus(listener);
66
+ raceSubscriber.subscribeControlPositions(listener);
67
+ raceSubscriber.subscribePositions(listener);
68
+// raceSubscriber.subscribePositionsSnapped(listener);
69
+ raceSubscriber.subscribeControlPassings(listener);
70
+ raceSubscriber.subscribeCompetitorSensorData(listener);
71
+ raceSubscriber.subscribeRaceMessages(listener);
72
+ raceSubscriber.subscribeRaceTimesChanges(listener);
73
+ raceSubscriber.subscribeRouteChanges(listener);
74
+ raceSubscriber.start();
75
+ eventSubscriber.start();
76
+
66 77
// Go ahead with GUI or other stuff in main thread
67 78
System.out.println("Press key to cancel live data stream");
68 79
System.in.read();
69 80
System.out.println("Cancelling data stream");
70
-
81
+
71 82
// Stop data streams
72
- eventSubscriber.stop();
73
- raceSubscriber.stop();
83
+ eventSubscriber.stop();
84
+ raceSubscriber.stop();
74 85
}
75 86
76
- private static URI parseArguments(String[] args) {
77
- if (args.length != 1) {
78
- System.out.println("Usage: java -jar TracAPI.jar parametersfile");
87
+ private static Object[] parseArguments(String[] args) {
88
+ if (args.length < 1) {
89
+ System.out.println("Usage: java -jar TracAPI.jar parametersfile measureDelay");
79 90
System.exit(0);
80 91
}
92
+ Object[] myArgs = new Object[2];
81 93
try {
82
- return new URI(args[0]);
94
+ myArgs[0] = new URI(args[0]);
95
+ myArgs[1] = args.length >= 2 && args[1].equals("1");
83 96
} catch (URISyntaxException ex) {
84 97
System.out.println("Malformed URL " + ex.getMessage());
85 98
System.exit(0);
86 99
}
87
- return null;
100
+ return myArgs;
88 101
}
89 102
}
java/org.openqa.selenium.osgi/.classpath
... ...
@@ -1,9 +1,18 @@
1 1
<?xml version="1.0" encoding="UTF-8"?>
2 2
<classpath>
3
- <classpathentry exported="true" kind="lib" path="lib/guava-15.0.jar"/>
4
- <classpathentry exported="true" kind="lib" path="selenium-java-2.40.0.jar" sourcepath="C:/data/java/selenium-selenium-2.40.0/java/client/src"/>
3
+ <classpathentry exported="true" kind="lib" path="lib/byte-buddy-1.8.3.jar"/>
4
+ <classpathentry exported="true" kind="lib" path="lib/commons-codec-1.10.jar"/>
5
+ <classpathentry exported="true" kind="lib" path="lib/commons-exec-1.3.jar"/>
6
+ <classpathentry exported="true" kind="lib" path="lib/commons-logging-1.2.jar"/>
7
+ <classpathentry exported="true" kind="lib" path="lib/gson-2.8.4.jar"/>
8
+ <classpathentry exported="true" kind="lib" path="lib/guava-25.0-jre.jar"/>
9
+ <classpathentry exported="true" kind="lib" path="lib/httpclient-4.5.5.jar"/>
10
+ <classpathentry exported="true" kind="lib" path="lib/httpcore-4.4.9.jar"/>
11
+ <classpathentry exported="true" kind="lib" path="lib/okhttp-3.10.0.jar"/>
12
+ <classpathentry exported="true" kind="lib" path="lib/okio-1.14.1.jar"/>
13
+ <classpathentry exported="true" kind="lib" path="client-combined-3.13.0.jar" sourcepath="client-combined-3.13.0-sources.jar"/>
14
+ <classpathentry exported="true" kind="lib" path="lib/json-20080701.jar"/>
5 15
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
6 16
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
7
- <classpathentry exported="true" kind="lib" path="lib/json-20080701.jar"/>
8 17
<classpathentry kind="output" path="bin"/>
9 18
</classpath>
java/org.openqa.selenium.osgi/META-INF/MANIFEST.MF
... ...
@@ -2,92 +2,49 @@ Manifest-Version: 1.0
2 2
Bundle-ManifestVersion: 2
3 3
Bundle-Name: Selenium
4 4
Bundle-SymbolicName: org.openqa.selenium.osgi
5
-Bundle-Version: 2.40.0
6
-Bundle-ClassPath: lib/apache-mime4j-0.6.jar,
7
- lib/bsh-1.3.0.jar,
8
- lib/cglib-nodep-2.1_3.jar,
9
- lib/commons-codec-1.8.jar,
10
- lib/commons-collections-3.2.1.jar,
11
- lib/commons-exec-1.1.jar,
12
- lib/commons-io-2.2.jar,
13
- lib/commons-jxpath-1.3.jar,
14
- lib/commons-lang3-3.1.jar,
15
- lib/commons-logging-1.1.1.jar,
16
- lib/cssparser-0.9.11.jar,
17
- lib/hamcrest-core-1.3.jar,
18
- lib/hamcrest-library-1.3.jar,
19
- lib/htmlunit-2.13.jar,
20
- lib/htmlunit-core-js-2.13.jar,
21
- lib/httpclient-4.3.1.jar,
22
- lib/httpcore-4.3.jar,
23
- lib/httpmime-4.3.1.jar,
24
- lib/ini4j-0.5.2.jar,
25
- lib/jcommander-1.29.jar,
26
- lib/jetty-websocket-8.1.8.jar,
27
- lib/jna-3.4.0.jar,
28
- lib/jna-platform-3.4.0.jar,
29
- lib/json-20080701.jar,
30
- lib/junit-dep-4.11.jar,
31
- lib/nekohtml-1.9.19.jar,
32
- lib/netty-3.5.7.Final.jar,
33
- lib/operadriver-1.5.jar,
34
- lib/phantomjsdriver-1.1.0.jar,
35
- lib/protobuf-java-2.4.1.jar,
36
- lib/sac-1.3.jar,
37
- lib/serializer-2.7.1.jar,
38
- lib/testng-6.8.5.jar,
39
- lib/xalan-2.7.1.jar,
40
- lib/xercesImpl-2.10.0.jar,
41
- selenium-java-2.40.0.jar,
42
- lib/guava-15.0.jar
5
+Bundle-Version: 3.13.0
6
+Bundle-ClassPath: lib/json-20080701.jar,
7
+ client-combined-3.13.0.jar,
8
+ lib/commons-codec-1.10.jar,
9
+ lib/byte-buddy-1.8.3.jar,
10
+ lib/commons-exec-1.3.jar,
11
+ lib/commons-logging-1.2.jar,
12
+ lib/gson-2.8.4.jar,
13
+ lib/guava-25.0-jre.jar,
14
+ lib/httpclient-4.5.5.jar,
15
+ lib/httpcore-4.4.9.jar,
16
+ lib/okhttp-3.10.0.jar,
17
+ lib/okio-1.14.1.jar
43 18
Bundle-Vendor: openqa
44 19
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
45
-Export-Package: com.google.common.annotations,
46
- com.google.common.base,
47
- com.google.common.base.internal,
48
- com.google.common.cache,
20
+Export-Package: com.google.common.base,
49 21
com.google.common.collect,
50
- com.google.common.escape,
51
- com.google.common.eventbus,
52
- com.google.common.hash,
53
- com.google.common.html,
54
- com.google.common.io,
55
- com.google.common.math,
56
- com.google.common.net,
57
- com.google.common.primitives,
58
- com.google.common.reflect,
59
- com.google.common.util.concurrent,
60
- com.google.common.xml,
61
- com.thoughtworks.selenium,
62
- com.thoughtworks.selenium.condition,
63 22
org.json,
64 23
org.openqa.selenium,
65
- org.openqa.selenium.browserlaunchers,
66
- org.openqa.selenium.browserlaunchers.locators,
67 24
org.openqa.selenium.chrome,
25
+ org.openqa.selenium.edge,
68 26
org.openqa.selenium.firefox,
69 27
org.openqa.selenium.firefox.internal,
70 28
org.openqa.selenium.html5,
71
- org.openqa.selenium.htmlunit,
72 29
org.openqa.selenium.ie,
73 30
org.openqa.selenium.interactions,
74 31
org.openqa.selenium.interactions.internal,
75 32
org.openqa.selenium.interactions.touch,
76 33
org.openqa.selenium.internal,
77 34
org.openqa.selenium.io,
78
- org.openqa.selenium.lift,
79
- org.openqa.selenium.lift.find,
80
- org.openqa.selenium.lift.match,
81 35
org.openqa.selenium.logging,
82 36
org.openqa.selenium.logging.profiler,
37
+ org.openqa.selenium.mobile,
83 38
org.openqa.selenium.net,
39
+ org.openqa.selenium.opera,
84 40
org.openqa.selenium.os,
85 41
org.openqa.selenium.remote,
86 42
org.openqa.selenium.remote.html5,
43
+ org.openqa.selenium.remote.http,
87 44
org.openqa.selenium.remote.internal,
45
+ org.openqa.selenium.remote.mobile,
88 46
org.openqa.selenium.remote.service,
89 47
org.openqa.selenium.safari,
90
- org.openqa.selenium.security,
91 48
org.openqa.selenium.support,
92 49
org.openqa.selenium.support.events,
93 50
org.openqa.selenium.support.events.internal,
java/org.openqa.selenium.osgi/build.properties
... ...
@@ -1,38 +1,13 @@
1 1
bin.includes = META-INF/,\
2
- lib/apache-mime4j-0.6.jar,\
3
- lib/bsh-1.3.0.jar,\
4
- lib/cglib-nodep-2.1_3.jar,\
5
- lib/commons-codec-1.8.jar,\
6
- lib/commons-collections-3.2.1.jar,\
7
- lib/commons-exec-1.1.jar,\
8
- lib/commons-io-2.2.jar,\
9
- lib/commons-jxpath-1.3.jar,\
10
- lib/commons-lang3-3.1.jar,\
11
- lib/commons-logging-1.1.1.jar,\
12
- lib/cssparser-0.9.11.jar,\
13
- lib/hamcrest-core-1.3.jar,\
14
- lib/hamcrest-library-1.3.jar,\
15
- lib/htmlunit-2.13.jar,\
16
- lib/htmlunit-core-js-2.13.jar,\
17
- lib/httpclient-4.3.1.jar,\
18
- lib/httpcore-4.3.jar,\
19
- lib/httpmime-4.3.1.jar,\
20
- lib/ini4j-0.5.2.jar,\
21
- lib/jcommander-1.29.jar,\
22
- lib/jetty-websocket-8.1.8.jar,\
23
- lib/jna-3.4.0.jar,\
24
- lib/jna-platform-3.4.0.jar,\
25 2
lib/json-20080701.jar,\
26
- lib/junit-dep-4.11.jar,\
27
- lib/nekohtml-1.9.19.jar,\
28
- lib/netty-3.5.7.Final.jar,\
29
- lib/operadriver-1.5.jar,\
30
- lib/protobuf-java-2.4.1.jar,\
31
- lib/sac-1.3.jar,\
32
- lib/serializer-2.7.1.jar,\
33
- lib/testng-6.8.5.jar,\
34
- lib/xalan-2.7.1.jar,\
35
- lib/xercesImpl-2.10.0.jar,\
36
- lib/phantomjsdriver-1.1.0.jar,\
37
- selenium-java-2.40.0.jar,\
38
- lib/guava-15.0.jar
3
+ client-combined-3.13.0.jar,\
4
+ lib/byte-buddy-1.8.3.jar,\
5
+ lib/commons-codec-1.10.jar,\
6
+ lib/commons-exec-1.3.jar,\
7
+ lib/commons-logging-1.2.jar,\
8
+ lib/gson-2.8.4.jar,\
9
+ lib/guava-25.0-jre.jar,\
10
+ lib/httpclient-4.5.5.jar,\
11
+ lib/httpcore-4.4.9.jar,\
12
+ lib/okhttp-3.10.0.jar,\
13
+ lib/okio-1.14.1.jar
java/org.openqa.selenium.osgi/client-combined-3.13.0-sources.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/client-combined-3.13.0-sources.jar differ
java/org.openqa.selenium.osgi/client-combined-3.13.0.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/client-combined-3.13.0.jar differ
java/org.openqa.selenium.osgi/lib/byte-buddy-1.8.3.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/lib/byte-buddy-1.8.3.jar differ
java/org.openqa.selenium.osgi/lib/commons-codec-1.10.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/lib/commons-codec-1.10.jar differ
java/org.openqa.selenium.osgi/lib/commons-exec-1.3.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/lib/commons-exec-1.3.jar differ
java/org.openqa.selenium.osgi/lib/commons-logging-1.2.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/lib/commons-logging-1.2.jar differ
java/org.openqa.selenium.osgi/lib/gson-2.8.4.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/lib/gson-2.8.4.jar differ
java/org.openqa.selenium.osgi/lib/guava-25.0-jre.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/lib/guava-25.0-jre.jar differ
java/org.openqa.selenium.osgi/lib/httpclient-4.5.5.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/lib/httpclient-4.5.5.jar differ
java/org.openqa.selenium.osgi/lib/httpcore-4.4.9.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/lib/httpcore-4.4.9.jar differ
java/org.openqa.selenium.osgi/lib/okhttp-3.10.0.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/lib/okhttp-3.10.0.jar differ
java/org.openqa.selenium.osgi/lib/okio-1.14.1.jar
... ...
Binary files /dev/null and b/java/org.openqa.selenium.osgi/lib/okio-1.14.1.jar differ
java/org.openqa.selenium.osgi/pom.xml
... ...
@@ -8,6 +8,6 @@
8 8
<version>1.0.0-SNAPSHOT</version>
9 9
</parent>
10 10
<artifactId>org.openqa.selenium.osgi</artifactId>
11
- <version>2.40.0</version>
11
+ <version>3.13.0</version>
12 12
<packaging>eclipse-plugin</packaging>
13 13
</project>
orchestration/Makefile
... ...
@@ -72,7 +72,7 @@ build:
72 72
$(foreach GOARCH, $(ARCHITECTURES), cd ${PREFIX}/src/sapsailing.com/orchestrator; GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) ${LDFLAGS} -v -o $${PREFIX}/bin/orchestrator-$(GOOS)-$(GOARCH)))
73 73
$(foreach GOOS, $(PLATFORMS),\
74 74
$(foreach GOARCH, $(ARCHITECTURES), cd ${PREFIX}/src/sapsailing.com/agent; GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) ${LDFLAGS} -v -o $${PREFIX}/bin/agent-$(GOOS)-$(GOARCH)))
75
- @/usr/bin/chmod +x $${PREFIX}/bin/*
75
+ @chmod +x $${PREFIX}/bin/*
76 76
@echo "done."
77 77
78 78
clean:
wiki/howto/development/orchestration.md
... ...
@@ -0,0 +1,127 @@
1
+## Architecture
2
+
3
+### Overview
4
+The orchestration project consists out of two components. The orchestrator on the one hand and the agent on the other.
5
+The orchestrator takes care on all actions in regards of AWS and to execute the agent. The agent will be copied via ssh to a target system and then called with a subset of stages to execute. The actual implementation of e.g. handling apache2, is done inside the agent. Once the agent execution of a stage is finished the return will be transferred back to the orchestrator, who continues with the workflow.
6
+
7
+![architecture](https://wiki.sapsailing.com/wiki/images/orchestration/architecture.png)
8
+
9
+### Build and Test
10
+Currently we provide a Makefile, which implements all required steps to build and test the software. Optionally you can of course also use `go test` directly. Just make sure that the `PREFIX` enviroment is set and points to the project directory (contains `configs` and `bin` subdirectories). You can also use `source env.sh` to do this, which on top sets the `GOPATH` correctly. By default, all go dependencies should be downloaded to `$HOME/.go`. They should not be stored in the git project location.
11
+
12
+To build the software, just call `make build`. Make sure that all dependencies are downloaded before via `make dep`.
13
+To test the software, just call `make test` and to check the tests, call `make checktest`. There are also make steps for `fmt` and others. Just check out the Makefile in the project root.
14
+The verbose output of the test logs is written to a folder called `testlogs` (which initially needs to be created).
15
+
16
+### Develop
17
+As the only Plugin for Eclipse is not really maintained anymore, we do not recommend to use it (goclipse). There is actually also no reason for it, as we are using Go and not Java or any OSGI features.
18
+As go is pretty simple and straight forward, you can use any Go supported IDE as stated on https://golang.org/doc/editors.html.
19
+
20
+Anyways, we recommend either using Goland (from IntelliJ), VS Code or Atom with respective go-plus Plugin.
21
+All you need to do after [installing go](https://golang.org/doc/install) and the IDE, is to make sure to set the above mentioned environment variable `PREFIX` to the code directory inside your IDE, so that tests can be successfully executed. Furthermore make sure to set the `GOPATH` correctly, create a directory (outside of the git workspace) and point the `GOPATH` to it. Then, add the code directory from git also to the `GOPATH`. This will result in the fact, that go will download all external dependencies with e.g. `make dep` or `go get` to the first folder and not put everything into the code directories. You will find all dependencies needed for the project inside the top lines for the `makefile`.
22
+
23
+An example for a correct `GOPATH` could be: `GOPATH=/home/steffen/.godep:/home/steffen/sailing-automation/`
24
+
25
+Happy Coding!
26
+
27
+## Get and prepare the software
28
+You can get the current release of the orchestration software currently from [here](http://static.sapsailing.com/orchestration-0.0.1_7f7e4e40d30f21ffeb8495a370a540c23c496745.tgz) until a release model is decided. The releases of each build can be downloaded directly on hudson via archived artifacts. The currently set up hudson job is called `orchestration-master` and can be started manually (runs on the archive failover, where go is installed).
29
+
30
+![hudson artifacts](https://wiki.sapsailing.com/wiki/images/orchestration/hudson-artifacts.png)
31
+
32
+Once downloaded, you just need to extract the archive locally to your machine. You will find the orchestrator and agent binaries in `bin` and all configurations in `configs` (like the instance templates or secrets).
33
+To get going, place your private key inside the secrets folder and name it `id_rsa`. This key must be pre-deployed in the used AWS AMI image. Furthermore, create a file called `conf_aws.json` (copy `conf_aws.json.sample` and fill in the values). A good example is
34
+
35
+```
36
+{
37
+ "AWS_ACCESS_KEY_ID": "<your access key id>,
38
+ "AWS_SECRET_ACCESS_KEY": "<your secret access key>",
39
+ "AWS_DEFAULT_REGION": "eu-west-1",
40
+ "AWS_ELB_NAME": "Sailing-eu-west-1",
41
+ "AWS_SNS_TOPIC_ARN": "arn:aws:sns:eu-west-1:017363970217:SAPSailing-General-Alerting"
42
+}
43
+```
44
+
45
+Inside the `config` folder you will find a folder called `instance_templates`. You can pre-define variables for launching EC2 instances. A valid example is
46
+
47
+```
48
+{
49
+ "image": "ami-839f8769",
50
+ "instance-type": "t2.medium",
51
+ "vpc": "vpc-14b3477f",
52
+ "subnet": "subnet-eab34781",
53
+ "count": 1,
54
+ "security-groups": [
55
+ "sg-eaf31e85"
56
+ ],
57
+ "tags": {
58
+ }
59
+}
60
+
61
+```
62
+
63
+You are ready to use the orchestration tool! Please note, that currently only linux-amd64 versions are built. Windows versions can be easily added, as go can also run under Windows and the project currently does not have any dependencies to linux.
64
+
65
+## Run the software
66
+You can run the orchestrator using
67
+
68
+```
69
+./bin/orchestrator-linux-amd64 <commands>
70
+```
71
+
72
+As we use log levels, you can increase logging verbosity to a different level by specifying a ENV variable in front of the orchestrator command, like:
73
+
74
+```
75
+LOG=DEBUG ./bin/orchestrator-linux-amd64 <commands>
76
+```
77
+We offer the following log levels: `DEBUG`, `INFO` (default), `WARNING`, `PANIC`, `FATAL`. If execution fails, you may re-execute the orchestrator using a higher log level to get more insights, what has happened.
78
+
79
+### General
80
+In general, the orchestrator accepts a set of arguments. The first level of parameters describe the type of action to be executed (basically a use-case). The following arguments are used to specify the use-case specific parameters.
81
+
82
+To show all available commands just call the orchestrator without any parameters.
83
+
84
+Non use-case specific commands are example commands like the `version` of the orchestrator. To do so, just use
85
+
86
+```
87
+./bin/orchestrator-linux-amd64 version
88
+```
89
+
90
+It will show the `version`, `build revision` (git commit) and the `branch`, from where the software was built. The agent should have the same version as the orchestrator and will be transferred to a target at each execution to make sure the target has the correct version.
91
+
92
+If you want to skip some steps done by the orchestrator on AWS level, you can use a command called `agent-only` as parameter. This will require a empty EC2 instance, where only agent actions (like bootstrapping,...) are executed. This step helps do debug actions of the agent, as you do not need to fire up a new EC2 instance all the time, but can use a already existing one. A sample call of this command looks like
93
+
94
+```
95
+./bin/orchestrator-linux-amd64 agent-only event="test-steffen123-1:1. Steffen Liga" servername=test-steffen123-1 internalhostname=ec2-34-242-13-180.eu-west-1.compute.amazonaws.com externalip=34.242.13.180 internalip=172.31.22.105 scenario=master analyticsenvironment=live-master-server analyticsrelease=build-201807231413
96
+```
97
+
98
+### Use case: Create Master Server
99
+This is the first ready to use and implemented use-case. It will spawn a new EC2 instance (you need to use an AMI in your instance template from the "NEXTGEN" base using Ubuntu 16 with systemd) and spawn/configure a new java instance on it. Furthermore it makes sure, that apache2 is configured correctly and if so the workflow continues to create target groups (default and master), attach the just created EC2 instance, create according rules in the load balancer and finally create an Cloudwatch alarm for all target groups to get notified, if a failure occurs inside a target group.
100
+
101
+If a step during execution fails, the orchestrator decides if it can continue or not. If not the execution is stopped and actions done via the agent are rolled back. Rollback of AWS features is not yet implemented.
102
+
103
+The workflow can create multiple events on a java instance and configure apache2, EC2 load balancing and the java application itself (event creation, user creation, password changes, ...).
104
+
105
+To use the use-case you simply use the orchestrator command `master`. An example could look like:
106
+
107
+```
108
+./bin/orchestrator-linux-amd64 master event="steffen2018:1. Steffen Liga" admin-password=supersicher123 user-name=steffen user-password=supersicher123 env=live-master-server release=build-201807231413
109
+```
110
+
111
+The following parameters are required for this use-case:
112
+
113
+```
114
+- event=<hostname>:<eventname> (the command can be repeated to create multiple events on the java server)
115
+- admin-password=<password of default admin account>
116
+- user-name=<name of the new user>
117
+- user-password=<password of the new user>
118
+- env=<environment for env.sh from releases.sapsailing.com>
119
+```
120
+
121
+Optionally you can specify the following parameters:
122
+
123
+```
124
+- template-file=<path to template file>
125
+- release=<release to use from releases.sapsailing.com, default: get latest>
126
+- notify=<email for notify parameter in env.sh>
127
+```
wiki/howto/development/selenium-ui-tests.md
... ...
@@ -4,19 +4,19 @@
4 4
5 5
## Quick Start: How to run tests locally in Eclipse
6 6
7
-There are two ways to run the Selenium tests locally on your computer. Either, you compile the GWT UI using our build script and run the tests based on the compiled UI, or you run the tests using the GWT hosted mode.
7
+There are two ways to run the Selenium tests locally on your computer. Either, you compile the GWT UI using our build script and run the tests based on the compiled UI, or you run the tests using the GWT super dev mode.
8 8
9 9
### Firefox Prerequisites
10 10
11
-!Since old Firefox version do not work with WindowScaling, ensure that in windows the Font Scaling is set to 100%, else Firefox will not be able to click buttons. You can find this setting at "Settings>Display Settings>Change the size of text, apps and other items". Also make sure that Firefox is running maximized (at least at Windows) as per default it is not running maximized!
11
+Running Selenium tests with FireFox requires to use GeckoDriver. You need to download a current version of GeckoDriver from [the download page](https://github.com/mozilla/geckodriver/releases) and unzip it on your system. At the time this was written, the current version was 0.21.0 and it worked best with FireFox versions 57-61 but other versions of both, GeckoDriver and FireFox should also work. In the file "/com.sap.sailing.selenium.test/local-test-environment.xml" you need to adjust the property "webdriver.gecko.driver" to point to the unzipped GeckoDriver executable. If you have a version of FixeFox globally installed on your system, GeckoDriver will use this one. If you do not have an installed version of FireFox or need to use a different version, you can set the property "webdriver.firefox.bin" in "/com.sap.sailing.selenium.test/local-test-environment.xml" to point to the specific firefox executable. When using a portable version, it is not the "FirefoxPortable.exe" but "App/Firefox/firefox.exe".
12 12
13
-You have to ensure that your Firefox browser has a profile called "Selenium" and that in this profile the latest version of the GWT plugin is installed. To ensure this, launch the server by choosing the "Sailing Server (Proxy)" or "Sailing Server (No Proxy)" launch config. Then, run the "SailingGWT" launch to start the GWT UI in hosted / development mode. Afterwards you can launch Firefox from the command line with the -p option. On Windows machines, you can do this by pressing the Windows key, then typing "firefox.exe -p". In the profile manager create a profile called Selenium and start Firefow with that profile. Hit the entry page of the AdminConsole by entering `http://127.0.0.1:8888/gwt/AdminConsole.html?gwt.codesvr=127.0.0.1:9997` into the address bar. This will ask you to install the GWT plugin into your Selenium profile. When done, exit the browser. You may use the profile manager again to set your default profile to your original profile.
13
+In older versions of Selenium, you needed to configure a special user profile in FireFox. With GeckoDriver, this isn't needed anymore.
14 14
15
-### Running the tests with GWT hosted mode
15
+### Running the tests with GWT super dev mode
16 16
17
-Launch the server by choosing the "Sailing Server (Proxy, winddbTest)" or "Sailing Server (No Proxy, winddbTest)" launch config. Then, run the "SailingGWT" launch to start the GWT UI in hosted / development mode.
17
+Launch the server by choosing the "Sailing Server (Proxy, winddbTest)" or "Sailing Server (No Proxy, winddbTest)" launch config. Then, run the "GWT Sailing SDM" launch to start the GWT UI in super dev mode (SDM).
18 18
19
-When the GWT development mode has finished its initialization as indicated by the "Development Mode" view showing the entry point URLs, launch the "com.sap.sailing.senelium.test (Proxy)" or "com.sap.sailing.senelium.test (No Proxy)" launch. This will then pop up Firefox windows using the "Selenium" profile and run the tests.
19
+When the GWT SDM has finished its initialization as indicated by the "Development Mode" view showing the entry point URLs, launch the "com.sap.sailing.senelium.test (Proxy)" or "com.sap.sailing.senelium.test (No Proxy)" launch. This will then pop up Firefox and run the tests.
20 20
21 21
### Running the tests after a successful local GWT compile
22 22
... ...
@@ -111,9 +111,11 @@ For a more practical example of how to write page objects and test you should ta
111 111
112 112
While our build environment is stable regarding to the used browser version, this may not be the case in your development environment, where you have the newest browser version installed probably. The short release cycles of the browsers often bring changes in the implementation, which are incompatible with Selenium. Therefore you have to update the used Selenium version by performing the following steps to be able to run the tests local.
113 113
114
-* Download the latest _Client & WebDriver Bindings_ for Java from the official [Selenium](http://docs.seleniumhq.org/download/) website
115
-* Delete the _selenium-java-<version>.jar_ in the root directory of the project _org.openqa.selenium.osgi_ as well as all libraries in the _lib_ directory and copy the new versions from the downloaded file in the appropriate folders
114
+* Download the latest _Client_ for Java from the official [Selenium](http://docs.seleniumhq.org/download/) website
115
+* Delete the _client-combined-<version>.jar_ (plus the _client-combined-<version>-sources.jar_) in the root directory of the project _org.openqa.selenium.osgi_ as well as all libraries in the _lib_ directory and copy the new versions from the downloaded file in the appropriate folders
116 116
* Open the _MANIFEST.MF_ with the Plug-in Manifest Editor and switch to the _Runtime_ tab
117 117
* Remove all the old libraries from the _Classpath_ section and add all new versions
118 118
* Add all new packages that start with _org.openqa.selenium_ to the _Exported Packages_ section in the case there were packages added
119
-* Updated the version number in the _MANIFEST.MF_ and in the _pom.xml_
... ...
\ No newline at end of file
0
+* Updated the version number in the _MANIFEST.MF_ and in the _pom.xml_
1
+* update build.properties to reflect the changed *.jar files
2
+* Update the version number in _MANIFEST.MF_ files referencing the _org.openqa.selenium_ bundle (e.g in _com.sap.sailing.selenium.test_)
wiki/images/orchestration/architecture.png
... ...
Binary files /dev/null and b/wiki/images/orchestration/architecture.png differ
wiki/images/orchestration/hudson-artifacts.png
... ...
Binary files /dev/null and b/wiki/images/orchestration/hudson-artifacts.png differ
wiki/info/landscape/amazon-ec2.md
... ...
@@ -514,6 +514,7 @@ Follow these steps to upgrade the AMI:
514 514
* Check the sizes of the mounted partitions by doing `df; swapon -s`. These will come in handy after creating the new AMI in order to tag the new volume snapshots accordingly
515 515
* Update any keys in `/root/.ssh/authorized_keys` and `/home/sailing/.ssh/authorized_keys`
516 516
* Remove created http rewrite entries in `/etc/httpd/conf.d/001-events.conf`
517
+* Edit /etc/update-motd.d/30-banner to set the current version
517 518
* In the EC2 administration console go to the "Instances" tab, select your running instance and from the "Actions" drop-down select "Create Image". Give the image the name "SAP Sailing Analytics App x.y" where "x.y" is the updated version number of the image. Just make sure it's greater than the previous one. If you feel like it, you may provide a short description telling the most important features of the image.
518 519
* Once the image creation has completed, go to the Snapshots list in the "Elastic Block Store" category and name the new snapshots appropriately. Now the information about the device sizes obtained earlier from the `df` and `swapon` commands will help you to identify which snapshot is which. Usually, the three snapshots would be something like AMI Analytics Home x.y, AMI Analytics System x.y and AMI Analytics Swap x.y with "x.y" being the version number matching that of your image.
519 520
* Now you can remove any earlier Sailing Server AMI version and the corresponding snapshots.