diff --git a/configuration/buildAndUpdateProduct.sh b/configuration/buildAndUpdateProduct.sh index 31784594d9b..a8d771d1529 100755 --- a/configuration/buildAndUpdateProduct.sh +++ b/configuration/buildAndUpdateProduct.sh @@ -95,7 +95,7 @@ parallelexecution=0 p2local=0 if [ $# -eq 0 ]; then - echo "buildAndUpdateProduct [-b -u -g -t -a -r -o -c -p -v -m -n -l -x ] [build|install|all|hot-deploy|remote-deploy|local-deploy|release]" + echo "buildAndUpdateProduct [-b -u -g -t -a -r -o -c -p -v -m -n -l -x -j ] [build|install|all|hot-deploy|remote-deploy|local-deploy|release]" echo "" echo "-g Disable GWT compile, no gwt files will be generated, old ones will be preserved." echo "-b Build GWT permutation only for one browser and English language." @@ -115,6 +115,7 @@ if [ $# -eq 0 ]; then echo "-u Run without confirmation messages. Use with extreme care." echo "-v Build local p2 respository, and use this instead of p2.sapsailing.com" echo "-x use this many worker threads for building GWT permutations (default: 2)." + echo "-j only execute the provided test package during tests" echo "" echo "build: builds the server code using Maven to $PROJECT_HOME (log to $START_DIR/build.log)" echo "" @@ -151,7 +152,7 @@ echo SERVERS_HOME is $SERVERS_HOME echo BRANCH is $active_branch echo VERSION is $VERSION_INFO -options=':bgtocparvm:n:l:s:w:x:u' +options=':bgtocparvm:n:l:s:w:x:j:u' while getopts $options option do case $option in @@ -172,6 +173,7 @@ do u) suppress_confirmation=1;; v) p2local=1;; x) GWT_WORKERS=$OPTARG;; + j) TESTCASE_TO_EXECUTE=$OPTARG;; \?) echo "Invalid option" exit 4;; esac @@ -259,7 +261,7 @@ if [[ "$@" == "release" ]]; then cp -v $PROJECT_HOME/java/target/configuration/jetty/etc/jetty-deployer.xml configuration/jetty/etc cp -v $PROJECT_HOME/java/target/configuration/jetty/etc/realm.properties configuration/jetty/etc cp -v $PROJECT_HOME/java/target/configuration/monitoring.properties configuration/ - cp -v $PROJECT_HOME/java/target/configuration/security.properties configuration/ + cp -v $PROJECT_HOME/java/target/configuration/mail.properties configuration/ cp -v $PROJECT_HOME/configuration/mongodb.cfg $ACDIR/ cp -v $PROJECT_HOME/java/target/udpmirror $ACDIR/ cp -v $PROJECT_HOME/java/target/http2udpmirror $ACDIR @@ -535,7 +537,7 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then fi cd $PROJECT_HOME/java - if [ $gwtcompile -eq 1 ]; then + if [ $gwtcompile -eq 1 ] && [[ "$clean" == "clean" ]]; then echo "INFO: Compiling GWT (rm -rf com.sap.$PROJECT_TYPE.gwt.ui/com.sap.$PROJECT_TYPE.*)" rm -rf com.sap.$PROJECT_TYPE.gwt.ui/com.sap.$PROJECT_TYPE.* GWT_XML_FILES=`find com.sap.$PROJECT_TYPE.gwt.ui/src/main/resources -name '*.gwt.xml'` @@ -587,6 +589,11 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then else extra="$extra -DskipTests=false" # TODO: Think about http://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html + if [[ "$TESTCASE_TO_EXECUTE" != "" ]]; then + # http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html + echo "Running only testcase $TESTCASE_TO_EXECUTE" + extra="$extra -Dtest=$TESTCASE_TO_EXECUTE" + fi fi if [ $android -eq 0 ] && [ $gwtcompile -eq 0 ] && [ $testing -eq 0 ]; then @@ -728,7 +735,7 @@ if [[ "$@" == "install" ]] || [[ "$@" == "all" ]]; then if [ ! -f "$ACDIR/env.sh" ]; then cp -v $PROJECT_HOME/java/target/env.sh $ACDIR/ cp -v $PROJECT_HOME/java/target/configuration/monitoring.properties $ACDIR/configuration/ - cp -v $PROJECT_HOME/java/target/configuration/security.properties $ACDIR/configuration/ + cp -v $PROJECT_HOME/java/target/configuration/mail.properties $ACDIR/configuration/ cp -v $PROJECT_HOME/java/target/configuration/logging.properties $ACDIR/configuration/ fi @@ -809,7 +816,7 @@ if [[ "$@" == "remote-deploy" ]]; then $SCP_CMD $PROJECT_HOME/java/target/configuration/jetty/etc/jetty-deployer.xml $REMOTE_SERVER_LOGIN:$REMOTE_SERVER/configuration/jetty/etc $SCP_CMD $PROJECT_HOME/java/target/configuration/jetty/etc/realm.properties $REMOTE_SERVER_LOGIN:$REMOTE_SERVER/configuration/jetty/etc $SCP_CMD $PROJECT_HOME/java/target/configuration/monitoring.properties $REMOTE_SERVER_LOGIN:$REMOTE_SERVER/configuration/ - $SCP_CMD $PROJECT_HOME/java/target/configuration/security.properties $REMOTE_SERVER_LOGIN:$REMOTE_SERVER/configuration/ + $SCP_CMD $PROJECT_HOME/java/target/configuration/mail.properties $REMOTE_SERVER_LOGIN:$REMOTE_SERVER/configuration/ $SCP_CMD $PROJECT_HOME/java/target/env.sh $REMOTE_SERVER_LOGIN:$REMOTE_SERVER/ $SCP_CMD $PROJECT_HOME/java/target/start $REMOTE_SERVER_LOGIN:$REMOTE_SERVER/ diff --git a/java/com.googlecode.mgwt/META-INF/MANIFEST.MF b/java/com.googlecode.mgwt/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index cbad3b64500..8f2067ad1ea --- a/java/com.googlecode.mgwt/META-INF/MANIFEST.MF +++ b/java/com.googlecode.mgwt/META-INF/MANIFEST.MF @@ -1,95 +1,95 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: mgwt -Bundle-SymbolicName: com.googlecode.mgwt -Bundle-Version: 2.0.0.qualifier -Bundle-Vendor: GOOGLE -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Bundle-ClassPath: lib/mgwt-2.0.0.jar, - . -Export-Package: com.googlecode.mgwt.collection.client, - com.googlecode.mgwt.collection.shared, - com.googlecode.mgwt.collection.shared.java, - com.googlecode.mgwt.css.client.updater, - com.googlecode.mgwt.css.rebind, - com.googlecode.mgwt.dom.client.event.animation, - com.googlecode.mgwt.dom.client.event.mouse, - com.googlecode.mgwt.dom.client.event.orientation, - com.googlecode.mgwt.dom.client.event.tap, - com.googlecode.mgwt.dom.client.event.touch, - com.googlecode.mgwt.dom.client.recognizer, - com.googlecode.mgwt.dom.client.recognizer.longtap, - com.googlecode.mgwt.dom.client.recognizer.pinch, - com.googlecode.mgwt.dom.client.recognizer.swipe, - com.googlecode.mgwt.dom.client.recognizer.tap, - com.googlecode.mgwt.image.client, - com.googlecode.mgwt.linker.client.cache, - com.googlecode.mgwt.linker.client.cache.event, - com.googlecode.mgwt.linker.client.cache.html5, - com.googlecode.mgwt.linker.linker, - com.googlecode.mgwt.linker.server, - com.googlecode.mgwt.linker.server.propertyprovider, - com.googlecode.mgwt.mvp.client, - com.googlecode.mgwt.mvp.client.history, - com.googlecode.mgwt.ui.client, - com.googlecode.mgwt.ui.client.animation, - com.googlecode.mgwt.ui.client.editor, - com.googlecode.mgwt.ui.client.theme.platform.button, - com.googlecode.mgwt.ui.client.theme.platform.buttonbar, - com.googlecode.mgwt.ui.client.theme.platform.carousel, - com.googlecode.mgwt.ui.client.theme.platform.dialog.options, - com.googlecode.mgwt.ui.client.theme.platform.dialog.panel, - com.googlecode.mgwt.ui.client.theme.platform.form, - com.googlecode.mgwt.ui.client.theme.platform.header, - com.googlecode.mgwt.ui.client.theme.platform.input, - com.googlecode.mgwt.ui.client.theme.platform.input.checkbox, - com.googlecode.mgwt.ui.client.theme.platform.input.listbox, - com.googlecode.mgwt.ui.client.theme.platform.input.radio, - com.googlecode.mgwt.ui.client.theme.platform.input.search, - com.googlecode.mgwt.ui.client.theme.platform.input.slider, - com.googlecode.mgwt.ui.client.theme.platform.list.celllist, - com.googlecode.mgwt.ui.client.theme.platform.list.widgetlist, - com.googlecode.mgwt.ui.client.theme.platform.main, - com.googlecode.mgwt.ui.client.theme.platform.panel, - com.googlecode.mgwt.ui.client.theme.platform.panel.pull, - com.googlecode.mgwt.ui.client.theme.platform.progress, - com.googlecode.mgwt.ui.client.theme.platform.tabbar, - com.googlecode.mgwt.ui.client.util, - com.googlecode.mgwt.ui.client.util.impl, - com.googlecode.mgwt.ui.client.widget.animation, - com.googlecode.mgwt.ui.client.widget.animation.bundle, - com.googlecode.mgwt.ui.client.widget.animation.impl, - com.googlecode.mgwt.ui.client.widget.base, - com.googlecode.mgwt.ui.client.widget.button, - com.googlecode.mgwt.ui.client.widget.button.image, - com.googlecode.mgwt.ui.client.widget.buttonbar, - com.googlecode.mgwt.ui.client.widget.carousel, - com.googlecode.mgwt.ui.client.widget.dialog, - com.googlecode.mgwt.ui.client.widget.dialog.options, - com.googlecode.mgwt.ui.client.widget.dialog.overlay, - com.googlecode.mgwt.ui.client.widget.dialog.panel, - com.googlecode.mgwt.ui.client.widget.form, - com.googlecode.mgwt.ui.client.widget.header, - com.googlecode.mgwt.ui.client.widget.image, - com.googlecode.mgwt.ui.client.widget.input, - com.googlecode.mgwt.ui.client.widget.input.checkbox, - com.googlecode.mgwt.ui.client.widget.input.listbox, - com.googlecode.mgwt.ui.client.widget.input.radio, - com.googlecode.mgwt.ui.client.widget.input.search, - com.googlecode.mgwt.ui.client.widget.input.slider, - com.googlecode.mgwt.ui.client.widget.list.celllist, - com.googlecode.mgwt.ui.client.widget.list.widgetlist, - com.googlecode.mgwt.ui.client.widget.main, - com.googlecode.mgwt.ui.client.widget.menu.overlay, - com.googlecode.mgwt.ui.client.widget.menu.swipe, - com.googlecode.mgwt.ui.client.widget.panel, - com.googlecode.mgwt.ui.client.widget.panel.flex, - com.googlecode.mgwt.ui.client.widget.panel.pull, - com.googlecode.mgwt.ui.client.widget.panel.scroll, - com.googlecode.mgwt.ui.client.widget.panel.scroll.impl, - com.googlecode.mgwt.ui.client.widget.progress, - com.googlecode.mgwt.ui.client.widget.tabbar, - com.googlecode.mgwt.ui.client.widget.tabbar.resources, - com.googlecode.mgwt.ui.client.widget.touch, - com.googlecode.mgwt.ui.generator, - com.googlecode.mgwt.ui.server.util +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: mgwt +Bundle-SymbolicName: com.googlecode.mgwt +Bundle-Version: 2.0.0.qualifier +Bundle-Vendor: GOOGLE +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ClassPath: lib/mgwt-2.0.0.jar, + . +Export-Package: com.googlecode.mgwt.collection.client, + com.googlecode.mgwt.collection.shared, + com.googlecode.mgwt.collection.shared.java, + com.googlecode.mgwt.css.client.updater, + com.googlecode.mgwt.css.rebind, + com.googlecode.mgwt.dom.client.event.animation, + com.googlecode.mgwt.dom.client.event.mouse, + com.googlecode.mgwt.dom.client.event.orientation, + com.googlecode.mgwt.dom.client.event.tap, + com.googlecode.mgwt.dom.client.event.touch, + com.googlecode.mgwt.dom.client.recognizer, + com.googlecode.mgwt.dom.client.recognizer.longtap, + com.googlecode.mgwt.dom.client.recognizer.pinch, + com.googlecode.mgwt.dom.client.recognizer.swipe, + com.googlecode.mgwt.dom.client.recognizer.tap, + com.googlecode.mgwt.image.client, + com.googlecode.mgwt.linker.client.cache, + com.googlecode.mgwt.linker.client.cache.event, + com.googlecode.mgwt.linker.client.cache.html5, + com.googlecode.mgwt.linker.linker, + com.googlecode.mgwt.linker.server, + com.googlecode.mgwt.linker.server.propertyprovider, + com.googlecode.mgwt.mvp.client, + com.googlecode.mgwt.mvp.client.history, + com.googlecode.mgwt.ui.client, + com.googlecode.mgwt.ui.client.animation, + com.googlecode.mgwt.ui.client.editor, + com.googlecode.mgwt.ui.client.theme.platform.button, + com.googlecode.mgwt.ui.client.theme.platform.buttonbar, + com.googlecode.mgwt.ui.client.theme.platform.carousel, + com.googlecode.mgwt.ui.client.theme.platform.dialog.options, + com.googlecode.mgwt.ui.client.theme.platform.dialog.panel, + com.googlecode.mgwt.ui.client.theme.platform.form, + com.googlecode.mgwt.ui.client.theme.platform.header, + com.googlecode.mgwt.ui.client.theme.platform.input, + com.googlecode.mgwt.ui.client.theme.platform.input.checkbox, + com.googlecode.mgwt.ui.client.theme.platform.input.listbox, + com.googlecode.mgwt.ui.client.theme.platform.input.radio, + com.googlecode.mgwt.ui.client.theme.platform.input.search, + com.googlecode.mgwt.ui.client.theme.platform.input.slider, + com.googlecode.mgwt.ui.client.theme.platform.list.celllist, + com.googlecode.mgwt.ui.client.theme.platform.list.widgetlist, + com.googlecode.mgwt.ui.client.theme.platform.main, + com.googlecode.mgwt.ui.client.theme.platform.panel, + com.googlecode.mgwt.ui.client.theme.platform.panel.pull, + com.googlecode.mgwt.ui.client.theme.platform.progress, + com.googlecode.mgwt.ui.client.theme.platform.tabbar, + com.googlecode.mgwt.ui.client.util, + com.googlecode.mgwt.ui.client.util.impl, + com.googlecode.mgwt.ui.client.widget.animation, + com.googlecode.mgwt.ui.client.widget.animation.bundle, + com.googlecode.mgwt.ui.client.widget.animation.impl, + com.googlecode.mgwt.ui.client.widget.base, + com.googlecode.mgwt.ui.client.widget.button, + com.googlecode.mgwt.ui.client.widget.button.image, + com.googlecode.mgwt.ui.client.widget.buttonbar, + com.googlecode.mgwt.ui.client.widget.carousel, + com.googlecode.mgwt.ui.client.widget.dialog, + com.googlecode.mgwt.ui.client.widget.dialog.options, + com.googlecode.mgwt.ui.client.widget.dialog.overlay, + com.googlecode.mgwt.ui.client.widget.dialog.panel, + com.googlecode.mgwt.ui.client.widget.form, + com.googlecode.mgwt.ui.client.widget.header, + com.googlecode.mgwt.ui.client.widget.image, + com.googlecode.mgwt.ui.client.widget.input, + com.googlecode.mgwt.ui.client.widget.input.checkbox, + com.googlecode.mgwt.ui.client.widget.input.listbox, + com.googlecode.mgwt.ui.client.widget.input.radio, + com.googlecode.mgwt.ui.client.widget.input.search, + com.googlecode.mgwt.ui.client.widget.input.slider, + com.googlecode.mgwt.ui.client.widget.list.celllist, + com.googlecode.mgwt.ui.client.widget.list.widgetlist, + com.googlecode.mgwt.ui.client.widget.main, + com.googlecode.mgwt.ui.client.widget.menu.overlay, + com.googlecode.mgwt.ui.client.widget.menu.swipe, + com.googlecode.mgwt.ui.client.widget.panel, + com.googlecode.mgwt.ui.client.widget.panel.flex, + com.googlecode.mgwt.ui.client.widget.panel.pull, + com.googlecode.mgwt.ui.client.widget.panel.scroll, + com.googlecode.mgwt.ui.client.widget.panel.scroll.impl, + com.googlecode.mgwt.ui.client.widget.progress, + com.googlecode.mgwt.ui.client.widget.tabbar, + com.googlecode.mgwt.ui.client.widget.tabbar.resources, + com.googlecode.mgwt.ui.client.widget.touch, + com.googlecode.mgwt.ui.generator, + com.googlecode.mgwt.ui.server.util diff --git a/java/com.mongodb.driver/.gitignore b/java/com.mongodb.driver/.gitignore deleted file mode 100644 index 44519b5db33..00000000000 --- a/java/com.mongodb.driver/.gitignore +++ /dev/null @@ -1 +0,0 @@ -bin/ diff --git a/java/com.mongodb.driver/.settings/org.eclipse.m2e.core.prefs b/java/com.mongodb.driver/.settings/org.eclipse.m2e.core.prefs deleted file mode 100755 index d5b0da240e7..00000000000 --- a/java/com.mongodb.driver/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,5 +0,0 @@ -#Fri Jul 29 09:33:56 CEST 2011 -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/java/com.mongodb.driver/META-INF/MANIFEST.MF b/java/com.mongodb.driver/META-INF/MANIFEST.MF deleted file mode 100644 index b7992ad8bd7..00000000000 --- a/java/com.mongodb.driver/META-INF/MANIFEST.MF +++ /dev/null @@ -1,18 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Driver -Bundle-SymbolicName: com.mongodb.driver -Bundle-Version: 2.6.2 -Bundle-Vendor: MONGODB -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Bundle-ActivationPolicy: lazy -Bundle-ClassPath: lib/mongo-2.6.2.jar, - . -Export-Package: com.mongodb, - com.mongodb.gridfs, - com.mongodb.io, - com.mongodb.util, - org.bson, - org.bson.io, - org.bson.types, - org.bson.util diff --git a/java/com.mongodb.driver/build.properties b/java/com.mongodb.driver/build.properties deleted file mode 100755 index 1957d654bdf..00000000000 --- a/java/com.mongodb.driver/build.properties +++ /dev/null @@ -1,3 +0,0 @@ -bin.includes = META-INF/,\ - .,\ - lib/mongo-2.6.2.jar diff --git a/java/com.mongodb.driver/lib/mongo-2.6.2.jar b/java/com.mongodb.driver/lib/mongo-2.6.2.jar deleted file mode 100755 index 3f64a8991bb..00000000000 Binary files a/java/com.mongodb.driver/lib/mongo-2.6.2.jar and /dev/null differ diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/compass.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/compass.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/compass.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/compass.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/dashboardicon.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/dashboardicon.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/dashboardicon.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/dashboardicon.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/hourwatch.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/hourwatch.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/hourwatch.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/hourwatch.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/leftarrow.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/leftarrow.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/leftarrow.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/leftarrow.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/leftarrow_disabled.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/leftarrow_disabled.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/leftarrow_disabled.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/leftarrow_disabled.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/logo_sap.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/logo_sap.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/logo_sap.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/logo_sap.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/logoess.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/logoess.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/logoess.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/logoess.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/nointernet.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/nointernet.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/nointernet.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/nointernet.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/rightarrow.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/rightarrow.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/rightarrow.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/rightarrow.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/rightarrow_disabled.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/rightarrow_disabled.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/rightarrow_disabled.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/rightarrow_disabled.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/settings.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/settings.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/settings.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/settings.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/watch.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/watch.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/watch.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/watch.png diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/resources/images/windarrow.png b/java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/windarrow.png similarity index 100% rename from java/com.sap.sailing.dashboards.gwt/src/main/resources/images/windarrow.png rename to java/com.sap.sailing.dashboards.gwt/src/main/resources/com/sap/sailing/dashboards/gwt/client/images/windarrow.png diff --git a/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index 59848e02ac8..7bd94febbcb --- a/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF @@ -1,25 +1,25 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: SAP Sailing Common -Bundle-SymbolicName: com.sap.sailing.domain.common -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Bundle-ActivationPolicy: lazy -Export-Package: com.sap.sailing.domain.common, - com.sap.sailing.domain.common.abstractlog, - com.sap.sailing.domain.common.confidence, - com.sap.sailing.domain.common.confidence.impl, - com.sap.sailing.domain.common.configuration, - com.sap.sailing.domain.common.dto, - com.sap.sailing.domain.common.impl, - com.sap.sailing.domain.common.media, - com.sap.sailing.domain.common.quadtree, - com.sap.sailing.domain.common.quadtree.impl;x-friends:="com.sap.sailing.domain.test", - com.sap.sailing.domain.common.racelog, - com.sap.sailing.domain.common.racelog.tracking, - com.sap.sailing.domain.common.racelog.utils, - com.sap.sailing.domain.common.scalablevalue.impl, - com.sap.sailing.domain.common.trackfiles -Require-Bundle: com.sap.sse.datamining.shared, - com.sap.sse.common +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: SAP Sailing Common +Bundle-SymbolicName: com.sap.sailing.domain.common +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-ActivationPolicy: lazy +Export-Package: com.sap.sailing.domain.common, + com.sap.sailing.domain.common.abstractlog, + com.sap.sailing.domain.common.confidence, + com.sap.sailing.domain.common.confidence.impl, + com.sap.sailing.domain.common.configuration, + com.sap.sailing.domain.common.dto, + com.sap.sailing.domain.common.impl, + com.sap.sailing.domain.common.media, + com.sap.sailing.domain.common.quadtree, + com.sap.sailing.domain.common.quadtree.impl;x-friends:="com.sap.sailing.domain.test", + com.sap.sailing.domain.common.racelog, + com.sap.sailing.domain.common.racelog.tracking, + com.sap.sailing.domain.common.racelog.utils, + com.sap.sailing.domain.common.scalablevalue.impl, + com.sap.sailing.domain.common.trackfiles +Require-Bundle: com.sap.sse.datamining.shared, + com.sap.sse.common diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java index 7691619ac39..e6e2d7c78ca 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java @@ -22,6 +22,10 @@ public interface CompetitorDTO extends Serializable, MappableToDevice { String getName(); Color getColor(); + + String getEmail(); + + boolean hasEmail(); /** * A regular instance will simply return this object. A compacted version may compute the result by looking it up diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java index 96d77c6614a..6c0cee85da9 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java @@ -19,16 +19,18 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial private String twoLetterIsoCountryCode; private String threeLetterIocCountryCode; private Color color; + private String email; private String sailID; private String idAsString; private BoatClassDTO boatClass; public CompetitorDTOImpl() {} - public CompetitorDTOImpl(String name, Color color, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, + public CompetitorDTOImpl(String name, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, String countryName, String sailID, String idAsString, BoatClassDTO boatClass) { super(name); this.color = color; + this.email = email; this.twoLetterIsoCountryCode = twoLetterIsoCountryCode; this.threeLetterIocCountryCode = threeLetterIocCountryCode; this.countryName = countryName; @@ -45,6 +47,7 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode()); result = prime * result + ((sailID == null) ? 0 : sailID.hashCode()); result = prime * result + ((color == null) ? 0 : color.hashCode()); + result = prime * result + ((email == null) ? 0 : email.hashCode()); result = prime * result + ((threeLetterIocCountryCode == null) ? 0 : threeLetterIocCountryCode.hashCode()); return result; } @@ -83,6 +86,11 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial return false; } else if (!color.equals(other.color)) return false; + if (email == null) { + if (other.email != null) + return false; + } else if (!email.equals(other.email)) + return false; return true; } @@ -124,4 +132,17 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial public Color getColor() { return color; } + + public String getEmail() { + return email; + } + + public String email(){ + return email; + } + + @Override + public boolean hasEmail() { + return email != null && !email.isEmpty(); + } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java index 0cee29c1a92..77ae9538d86 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java @@ -92,9 +92,20 @@ public class PreviousCompetitorDTOImpl implements CompetitorDTO { throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+ " need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization"); } + + @Override + public String getEmail() { + throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+ + " need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization"); + } @Override public CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion) { return previousVersion.competitors.get(indexInPreviousCompetitorList); } + + @Override + public boolean hasEmail() { + return false; + } } \ No newline at end of file diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/DeviceMappingConstants.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/DeviceMappingConstants.java index affb0ce5572..5e468744ffb 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/DeviceMappingConstants.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/DeviceMappingConstants.java @@ -1,5 +1,8 @@ package com.sap.sailing.domain.common.racelog.tracking; +import com.sap.sailing.domain.common.racelog.RaceLogServletConstants; +import com.sap.sse.common.util.UrlHelper; + /** * Shared between GWT and Android. Used for creating and deciphering the URL encoded by the QRCode, which gives the * tracking app all necessary information for creating the device mapping of either the race or leaderboard/regatta. @@ -13,28 +16,50 @@ package com.sap.sailing.domain.common.racelog.tracking; * * @author Fredrik Teschke */ -public interface DeviceMappingConstants { +public class DeviceMappingConstants { // According to the HTTP protocol definition (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.2.3), only // schema and host are case insensitive. // But to adhere to best practices, and due to the deficiencies of some web servers and clients, // all URL components should be treated as case insensitive, preferring _underscores_ to CamelCase. - static final String URL_BASE = "/tracking/checkin"; - static final String URL_EVENT_ID = "event_id"; - static final String URL_LEADERBOARD_NAME = "leaderboard_name"; - static final String URL_COMPETITOR_ID_AS_STRING = "competitor_id"; - static final String URL_MARK_ID_AS_STRING = "mark_id"; - static final String URL_FROM_MILLIS = "from_millis"; - static final String URL_TO_MILLIS = "to_millis"; + public static final String URL_BASE = "/tracking/checkin"; + public static final String URL_EVENT_ID = "event_id"; + public static final String URL_LEADERBOARD_NAME = "leaderboard_name"; + public static final String URL_COMPETITOR_ID_AS_STRING = "competitor_id"; + public static final String URL_MARK_ID_AS_STRING = "mark_id"; + public static final String URL_FROM_MILLIS = "from_millis"; + public static final String URL_TO_MILLIS = "to_millis"; - static final String JSON_COMPETITOR_ID_AS_STRING = "competitorId"; - static final String JSON_MARK_ID_AS_STRING = "markId"; - static final String JSON_DEVICE_UUID = "deviceUuid"; - static final String JSON_DEVICE_TYPE = "deviceType"; - static final String JSON_PUSH_DEVICE_ID = "pushDeviceId"; - static final String JSON_FROM_MILLIS = "fromMillis"; - static final String JSON_TO_MILLIS = "toMillis"; - static final String JSON_TEAM_IMAGE_URI = "teamImageUri"; + public static final String JSON_COMPETITOR_ID_AS_STRING = "competitorId"; + public static final String JSON_MARK_ID_AS_STRING = "markId"; + public static final String JSON_DEVICE_UUID = "deviceUuid"; + public static final String JSON_DEVICE_TYPE = "deviceType"; + public static final String JSON_PUSH_DEVICE_ID = "pushDeviceId"; + public static final String JSON_FROM_MILLIS = "fromMillis"; + public static final String JSON_TO_MILLIS = "toMillis"; + public static final String JSON_TEAM_IMAGE_URI = "teamImageUri"; @Deprecated static final String APK_PATH = "/apps/com.sap.sailing.android.tracking.app.apk"; + + public static String getDeviceMappingForRegattaLogUrl(String serverUrlWithoutTrailingSlash, String eventId, + String leaderboardName, String mappedItemType, String mappedItemId, UrlHelper helper) { + return helper.encodeUrl(serverUrlWithoutTrailingSlash + URL_BASE + "?" + URL_EVENT_ID + "=" + eventId + "&" + + URL_LEADERBOARD_NAME + "=" + leaderboardName + "&" + mappedItemType + "=" + + mappedItemId); + } + + @Deprecated + public static String getDeviceMappingForRaceLogUrl(String serverUrlWithoutTrailingSlash, String leaderboardName, + String raceColumnName, String fleetName, String mappedItemType, String mappedItemId, long fromMillis, + long toMillis, UrlHelper helper) throws QRCodeURLCreationException { + if (fromMillis > toMillis) { + throw new QRCodeURLCreationException("from can't lie after to"); + } + return helper.encodeUrl(serverUrlWithoutTrailingSlash + DeviceMappingConstants.APK_PATH + "?" + + RaceLogServletConstants.PARAMS_LEADERBOARD_NAME + "=" + leaderboardName + "&" + + RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME + "=" + raceColumnName + "&" + + RaceLogServletConstants.PARAMS_RACE_FLEET_NAME + "=" + fleetName + "&" + mappedItemType + "=" + + mappedItemId + "&" + DeviceMappingConstants.URL_FROM_MILLIS + "=" + fromMillis + "&" + + DeviceMappingConstants.URL_TO_MILLIS + "=" + toMillis); + } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/QRCodeURLCreationException.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/QRCodeURLCreationException.java new file mode 100644 index 00000000000..aa2e0847644 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/QRCodeURLCreationException.java @@ -0,0 +1,9 @@ +package com.sap.sailing.domain.common.racelog.tracking; + +public class QRCodeURLCreationException extends Exception { + private static final long serialVersionUID = -8243995470804772458L; + + public QRCodeURLCreationException(String message) { + super(message); + } +} diff --git a/java/com.sap.sailing.domain.igtimiadapter.persistence/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.igtimiadapter.persistence/META-INF/MANIFEST.MF index 58103f9a1ff..e13bab9db78 100644 --- a/java/com.sap.sailing.domain.igtimiadapter.persistence/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.igtimiadapter.persistence/META-INF/MANIFEST.MF @@ -6,7 +6,7 @@ Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: com.sap.sse.mongodb, - com.mongodb.driver;bundle-version="2.6.2" + org.mongodb.mongo-java-driver;bundle-version="2.13.0" Export-Package: com.sap.sailing.domain.igtimiadapter.persistence Import-Package: org.osgi.framework Bundle-Activator: com.sap.sailing.domain.igtimiadapter.persistence.impl.Activator diff --git a/java/com.sap.sailing.domain.igtimiadapter.persistence/src/com/sap/sailing/domain/igtimiadapter/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.igtimiadapter.persistence/src/com/sap/sailing/domain/igtimiadapter/persistence/impl/DomainObjectFactoryImpl.java index 5c7dad552b8..45f79453834 100644 --- a/java/com.sap.sailing.domain.igtimiadapter.persistence/src/com/sap/sailing/domain/igtimiadapter/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.igtimiadapter.persistence/src/com/sap/sailing/domain/igtimiadapter/persistence/impl/DomainObjectFactoryImpl.java @@ -19,7 +19,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { public Iterable getAccessTokens() { List result = new ArrayList<>(); final DBCollection accessTokenCollection = db.getCollection(CollectionNames.IGTIMI_ACCESS_TOKENS.name()); - accessTokenCollection.ensureIndex(new BasicDBObject(FieldNames.IGTIMI_ACCESS_TOKENS_ACCESS_TOKEN.name(), 1)); + accessTokenCollection.createIndex(new BasicDBObject(FieldNames.IGTIMI_ACCESS_TOKENS_ACCESS_TOKEN.name(), 1)); for (Object o : accessTokenCollection.find()) { result.add((String) ((DBObject) o).get(FieldNames.IGTIMI_ACCESS_TOKENS_ACCESS_TOKEN.name())); } diff --git a/java/com.sap.sailing.domain.igtimiadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.igtimiadapter/META-INF/MANIFEST.MF index bfc38039265..daaa255460c 100644 --- a/java/com.sap.sailing.domain.igtimiadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.igtimiadapter/META-INF/MANIFEST.MF @@ -27,7 +27,8 @@ Import-Package: javax.ws.rs;version="1.1.1", org.eclipse.jetty.websocket.api.extensions;version="9.0.0", org.eclipse.jetty.websocket.client;version="9.0.0", org.eclipse.jetty.websocket.common;version="9.0.0", - org.osgi.framework;version="1.7.0" + org.osgi.framework;version="1.7.0", + org.codehaus.jackson.jaxrs;version="1.9.13" Web-ContextPath: /igtimi Bundle-Activator: com.sap.sailing.domain.igtimiadapter.impl.Activator Export-Package: com.sap.sailing.domain.igtimiadapter, diff --git a/java/com.sap.sailing.domain.persistence/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.persistence/META-INF/MANIFEST.MF index a36a2c2895d..c169680edd6 100644 --- a/java/com.sap.sailing.domain.persistence/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.persistence/META-INF/MANIFEST.MF @@ -8,7 +8,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-Activator: com.sap.sailing.domain.persistence.impl.Activator Require-Bundle: com.sap.sse.mongodb, com.sap.sailing.domain, - com.mongodb.driver;bundle-version="2.6.2", + org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sailing.domain.common, com.sap.sailing.domain.shared.android, com.sap.sailing.server.gateway.serialization, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index c93c16eca94..d5523dd550d 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -277,14 +277,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } private void ensureIndicesOnWindTracks(DBCollection windTracks) { - windTracks.ensureIndex(FieldNames.RACE_ID.name()); // for new programmatic access - windTracks.ensureIndex(FieldNames.REGATTA_NAME.name()); // for export or human look-up + windTracks.createIndex(new BasicDBObject(FieldNames.RACE_ID.name(), 1)); // for new programmatic access + windTracks.createIndex(new BasicDBObject(FieldNames.REGATTA_NAME.name(), 1)); // for export or human look-up // for legacy access to not yet migrated fixes - windTracks.ensureIndex(new BasicDBObjectBuilder().add(FieldNames.EVENT_NAME.name(), 1) + windTracks.createIndex(new BasicDBObjectBuilder().add(FieldNames.EVENT_NAME.name(), 1) .add(FieldNames.RACE_NAME.name(), 1).get()); // Unique index try { - windTracks.ensureIndex( + windTracks.createIndex( new BasicDBObjectBuilder().add(FieldNames.RACE_ID.name(), 1) .add(FieldNames.WIND_SOURCE_NAME.name(), 1).add(FieldNames.WIND_SOURCE_ID.name(), 1) .add(FieldNames.WIND.name() + "." + FieldNames.TIME_AS_MILLIS.name(), 1).get(), diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 98c9abff2bf..64e3e014fcf 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -201,7 +201,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { public DBCollection getWindTrackCollection() { DBCollection result = database.getCollection(CollectionNames.WIND_TRACKS.name()); - result.ensureIndex(new BasicDBObject(FieldNames.REGATTA_NAME.name(), null)); + result.createIndex(new BasicDBObject(FieldNames.REGATTA_NAME.name(), null)); return result; } @@ -210,7 +210,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { DBObject index = new BasicDBObject(); index.put(FieldNames.DEVICE_ID.name(), null); index.put(FieldNames.TIME_AS_MILLIS.name(), null); - gpsFixCollection.ensureIndex(index); + gpsFixCollection.createIndex(index); return gpsFixCollection; } @@ -218,7 +218,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { DBCollection collection = database.getCollection(CollectionNames.GPS_FIXES_METADATA.name()); DBObject index = new BasicDBObject(); index.put(FieldNames.DEVICE_ID.name(), null); - collection.ensureIndex(index); + collection.createIndex(index); return collection; } @@ -263,7 +263,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { public void storeLeaderboard(Leaderboard leaderboard) { DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); try { - leaderboardCollection.ensureIndex(FieldNames.LEADERBOARD_NAME.name()); + leaderboardCollection.createIndex(new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), 1)); } catch (NullPointerException npe) { // sometimes, for reasons yet to be clarified, ensuring an index on the name field causes an NPE logger.log(Level.SEVERE, "storeLeaderboard", npe); @@ -438,7 +438,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); try { - leaderboardGroupCollection.ensureIndex(FieldNames.LEADERBOARD_GROUP_NAME.name()); + leaderboardGroupCollection.createIndex(new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), 1)); } catch (NullPointerException npe) { // sometimes, for reasons yet to be clarified, ensuring an index on the name field causes an NPE logger.log(Level.SEVERE, "storeLeaderboardGroup", npe); @@ -494,7 +494,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void storeSailingServer(RemoteSailingServerReference server) { DBCollection serverCollection = database.getCollection(CollectionNames.SAILING_SERVERS.name()); - serverCollection.ensureIndex(FieldNames.SERVER_NAME.name()); + serverCollection.createIndex(new BasicDBObject(FieldNames.SERVER_NAME.name(), 1)); DBObject query = new BasicDBObject(); query.put(FieldNames.SERVER_NAME.name(), server.getName()); DBObject serverDBObject = new BasicDBObject(); @@ -513,7 +513,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void storeEvent(Event event) { DBCollection eventCollection = database.getCollection(CollectionNames.EVENTS.name()); - eventCollection.ensureIndex(FieldNames.EVENT_ID.name()); + eventCollection.createIndex(new BasicDBObject(FieldNames.EVENT_ID.name(), 1)); DBObject query = new BasicDBObject(); query.put(FieldNames.EVENT_ID.name(), event.getId()); DBObject eventDBObject = new BasicDBObject(); @@ -545,7 +545,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { eventCollection.update(query, eventDBObject, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); // now store the links to the leaderboard groups DBCollection linksCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUP_LINKS_FOR_EVENTS.name()); - linksCollection.ensureIndex(FieldNames.EVENT_ID.name()); + linksCollection.createIndex(new BasicDBObject(FieldNames.EVENT_ID.name(), 1)); BasicDBList lgUUIDs = new BasicDBList(); for (LeaderboardGroup lg : event.getLeaderboardGroups()) { lgUUIDs.add(lg.getId()); @@ -588,8 +588,8 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void storeRegatta(Regatta regatta) { DBCollection regattasCollection = database.getCollection(CollectionNames.REGATTAS.name()); - regattasCollection.ensureIndex(FieldNames.REGATTA_NAME.name()); - regattasCollection.ensureIndex(FieldNames.REGATTA_ID.name()); + regattasCollection.createIndex(new BasicDBObject(FieldNames.REGATTA_NAME.name(), 1)); + regattasCollection.createIndex(new BasicDBObject(FieldNames.REGATTA_ID.name(), 1)); DBObject dbRegatta = new BasicDBObject(); DBObject query = new BasicDBObject(FieldNames.REGATTA_NAME.name(), regatta.getName()); dbRegatta.put(FieldNames.REGATTA_NAME.name(), regatta.getName()); @@ -690,7 +690,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { public DBCollection getRaceLogCollection() { DBCollection result = database.getCollection(CollectionNames.RACE_LOGS.name()); - result.ensureIndex(new BasicDBObject(FieldNames.RACE_LOG_IDENTIFIER.name(), null)); + result.createIndex(new BasicDBObject(FieldNames.RACE_LOG_IDENTIFIER.name(), null)); return result; } @@ -1279,7 +1279,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { DBCollection result = database.getCollection(CollectionNames.REGATTA_LOGS.name()); DBObject index = new BasicDBObject(FieldNames.REGATTA_LOG_IDENTIFIER_TYPE.name(), null); index.put(FieldNames.REGATTA_LOG_IDENTIFIER_NAME.name(), null); - result.ensureIndex(index); + result.createIndex(index); return result; } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/media/impl/MediaDBImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/media/impl/MediaDBImpl.java index c56a1b970f6..2fbd5ba854c 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/media/impl/MediaDBImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/media/impl/MediaDBImpl.java @@ -14,7 +14,7 @@ import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; -import com.mongodb.MongoException; +import com.mongodb.DuplicateKeyException; import com.mongodb.WriteConcern; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaNameAndRaceName; @@ -70,7 +70,7 @@ public class MediaDBImpl implements MediaDB { dbMediaTrack.put(DbNames.Fields.ASSIGNED_RACES.name(), assignedRacesDb); DBCollection dbVideos = getVideoCollection(); dbVideos.insert(dbMediaTrack); - return ((ObjectId) dbMediaTrack.get(DbNames.Fields._id.name())).toStringMongod(); + return ((ObjectId) dbMediaTrack.get(DbNames.Fields._id.name())).toHexString(); } @Override @@ -99,7 +99,7 @@ public class MediaDBImpl implements MediaDB { DBCollection dbVideos = getVideoCollection(); try { dbVideos.insert(dbMediaTrack); - } catch (MongoException.DuplicateKey e) { + } catch (DuplicateKeyException e) { throw new IllegalArgumentException("Duplicate key '" + dbId + "' caused an error when importing media (title: '" + title + "')", e); } @@ -109,7 +109,7 @@ public class MediaDBImpl implements MediaDB { try { DBCollection dbVideos = database.getCollection(DbNames.Collections.VIDEOS.name()); dbVideos.setWriteConcern(WriteConcern.FSYNC_SAFE); - dbVideos.ensureIndex(DbNames.Collections.VIDEOS.name()); + dbVideos.createIndex(new BasicDBObject(DbNames.Collections.VIDEOS.name(), 1)); return dbVideos; } catch (NullPointerException e) { // sometimes, for reasons yet to be clarified, ensuring an index on the name field causes an NPE @@ -118,7 +118,7 @@ public class MediaDBImpl implements MediaDB { } private MediaTrack createMediaTrackFromDb(DBObject dbObject) { - String dbId = ((ObjectId) dbObject.get(DbNames.Fields._id.name())).toStringMongod(); + String dbId = ((ObjectId) dbObject.get(DbNames.Fields._id.name())).toHexString(); String title = (String) dbObject.get(DbNames.Fields.MEDIA_TITLE.name()); String url = (String) dbObject.get(DbNames.Fields.MEDIA_URL.name()); Date startTime = (Date) dbObject.get(DbNames.Fields.STARTTIME.name()); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.racelogtrackingadapter.test/META-INF/MANIFEST.MF index 0fa0ba74d6f..eb7048450f1 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/META-INF/MANIFEST.MF @@ -11,7 +11,7 @@ Require-Bundle: org.junit4;bundle-version="4.8.2", org.mockito.mockito-core;bundle-version="1.9.5", org.objenesis;bundle-version="1.3.0", org.hamcrest;bundle-version="1.1.0", - com.mongodb.driver;bundle-version="2.6.2", + org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sse.common Import-Package: com.sap.sailing.domain.abstractlog.regatta.events, com.sap.sailing.domain.persistence.impl, diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java index e15e16f2a28..e6cb2e8c28c 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java @@ -40,7 +40,7 @@ public class AbstractGPSFixStoreTest { protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a"); protected RaceLog raceLog; protected GPSFixStore store; - protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null); + protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null); protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); private final AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java index bff12901d90..f124610bc27 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java @@ -168,7 +168,7 @@ public class CreateAndTrackWithRaceLogTest { assertFalse(raceLog.isEmpty()); // add a mapping and one fix in, one out of mapping - Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null); + Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null, null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); raceLog.add(factory.createDeviceCompetitorMappingEvent(t(), author, dev1, comp1, 0, t(0), t(10))); addFixes0(dev1); @@ -202,7 +202,7 @@ public class CreateAndTrackWithRaceLogTest { adapter.denoteRaceForRaceLogTracking(service, leaderboard, column, fleet, "race"); // add a mapping and one fix in, one out of mapping - Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null); + Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null, null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), author, t(), UUID.randomUUID(), comp1, dev1, t(0), t(10))); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java index 0647e02d62a..e4c276dd8ce 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java @@ -49,7 +49,7 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { @Test public void areFixesStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null); + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); DeviceIdentifier device2 = new SmartphoneImeiIdentifier("imei2"); DeviceIdentifier device3 = new SmartphoneImeiIdentifier("imei3"); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.testsupport/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.racelogtrackingadapter.testsupport/META-INF/MANIFEST.MF index ccd9c941566..ab5f50f9c87 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.testsupport/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.testsupport/META-INF/MANIFEST.MF @@ -1,21 +1,21 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Testsupport -Bundle-SymbolicName: com.sap.sailing.domain.racelogtrackingadapter.testsupport -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: com.sap.sailing.domain.shared.android, - com.sap.sailing.domain, - com.sap.sailing.domain.common, - com.mongodb.driver, - com.sap.sailing.domain.persistence, - com.sap.sailing.domain.racelogtrackingadapter, - com.sap.sailing.server.gateway.serialization;bundle-version="1.0.0", - org.json.simple;bundle-version="1.1.0", - org.mockito.mockito-core;bundle-version="1.9.5", - org.hamcrest;bundle-version="1.1.0", - org.junit4;bundle-version="4.8.2", - com.sap.sse.common, - com.sap.sailing.server.gateway.serialization.shared.android -Export-Package: com.sap.sailing.domain.racelog.tracking.test.mock +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Testsupport +Bundle-SymbolicName: com.sap.sailing.domain.racelogtrackingadapter.testsupport +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: com.sap.sailing.domain.shared.android, + com.sap.sailing.domain, + com.sap.sailing.domain.common, + org.mongodb.mongo-java-driver;bundle-version="2.13.0", + com.sap.sailing.domain.persistence, + com.sap.sailing.domain.racelogtrackingadapter, + com.sap.sailing.server.gateway.serialization;bundle-version="1.0.0", + org.json.simple;bundle-version="1.1.0", + org.mockito.mockito-core;bundle-version="1.9.5", + org.hamcrest;bundle-version="1.1.0", + org.junit4;bundle-version="4.8.2", + com.sap.sse.common, + com.sap.sailing.server.gateway.serialization.shared.android +Export-Package: com.sap.sailing.domain.racelog.tracking.test.mock diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/.classpath b/java/com.sap.sailing.domain.racelogtrackingadapter/.classpath index 4f83b2397ec..03c4ce9fdd8 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/.classpath +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/.classpath @@ -2,6 +2,7 @@ + diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/.settings/org.eclipse.core.resources.prefs b/java/com.sap.sailing.domain.racelogtrackingadapter/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..1b6fd8593f0 --- /dev/null +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding//resources/stringmessages/TrackingStringMessages_de.properties=UTF-8 diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.racelogtrackingadapter/META-INF/MANIFEST.MF index 8e31d895c72..5133df9643f 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/META-INF/MANIFEST.MF @@ -13,12 +13,17 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.domain.persistence, com.sap.sailing.server, com.googlecode.java-diff-utils;bundle-version="1.3.0", - com.mongodb.driver, + org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sse.common, com.sap.sse.replication, com.sap.sse, - com.sap.sailing.server.gateway.serialization.shared.android -Import-Package: com.mongodb, + com.sap.sailing.server.gateway.serialization.shared.android, + com.sap.sse.mail +Import-Package: com.google.zxing;version="3.1.0", + com.mongodb, + javax.mail;version="1.4.0", + javax.mail.internet;version="1.4.0", + javax.mail.util;version="1.4.0", javax.servlet;version="2.6.0", org.json.simple, org.json.simple.parser, diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/build.properties b/java/com.sap.sailing.domain.racelogtrackingadapter/build.properties index 34d2e4d2dad..f11210d3f2c 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/build.properties +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/build.properties @@ -1,4 +1,5 @@ -source.. = src/ +source.. = src/,\ + resources/ output.. = bin/ bin.includes = META-INF/,\ . diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_de.properties b/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_de.properties new file mode 100644 index 00000000000..21a7ad3191e --- /dev/null +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_de.properties @@ -0,0 +1,4 @@ +trackingInvitationFor=Einladung zum Tracken für +scanQRCodeOrVisitUrlToRegisterAs=Scanne den QRCode oder klicke den Link mit deinem Smartphone an um dich zu registrieren als +welcomeTo=Willkommen zu +alternativelyVisitThisLink=Alternativ kannst du diesen Link anklicken \ No newline at end of file diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_en.properties b/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_en.properties new file mode 100644 index 00000000000..4edebbdcda5 --- /dev/null +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages_en.properties @@ -0,0 +1,4 @@ +trackingInvitationFor=Tracking Invitation for +scanQRCodeOrVisitUrlToRegisterAs=Scan the following QRCode or click the link using your smartphone to register as +welcomeTo=Welcome to +alternativelyVisitThisLink=Alternatively, you can click this Link \ No newline at end of file diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/RaceLogTrackingAdapter.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/RaceLogTrackingAdapter.java index 56b300f4aca..b6efc960f89 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/RaceLogTrackingAdapter.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/RaceLogTrackingAdapter.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.racelogtracking; +import java.util.Locale; import java.util.Set; import com.sap.sailing.domain.abstractlog.race.RaceLog; @@ -10,6 +11,7 @@ import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEven import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; +import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceColumn; @@ -24,12 +26,14 @@ import com.sap.sailing.domain.racelogtracking.impl.RaceLogRaceTracker; import com.sap.sailing.domain.tracking.GPSFix; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.server.RacingEventService; +import com.sap.sse.common.mail.MailException; -public interface RaceLogTrackingAdapter { +public interface RaceLogTrackingAdapter { /** - * Performs the necessary steps to ensure that the race is tracked (aka that a {@link TrackedRace} - * is created from the data in this {@code RaceLog}).

- * The following steps are performed to achieve this: + * Performs the necessary steps to ensure that the race is tracked (aka that a {@link TrackedRace} is created from + * the data in this {@code RaceLog}). + *

+ * The following steps are performed to achieve this: *

    *
  • Is the racelog denoted for tracking? If not, throw exception.
  • *
  • Is a {@link RaceLogRaceTracker} already listening for this racelog? If not, add one.
  • @@ -38,7 +42,7 @@ public interface RaceLogTrackingAdapter { */ void startTracking(RacingEventService service, Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet) throws NotDenotedForRaceLogTrackingException, Exception; - + RaceLogTrackingState getRaceLogTrackingState(RacingEventService service, RaceColumn raceColumn, Fleet fleet); /** @@ -51,16 +55,15 @@ public interface RaceLogTrackingAdapter { * * @throws NotDenotableForRaceLogTrackingException * Fails, if no {@link RaceLog}, or a non-empty {@link RaceLog}, or one with attached - * {@link TrackedRace} is found already in place. - * Also fails, if the {@code leaderboard} is not a {@link RegattaLeaderboard}. + * {@link TrackedRace} is found already in place. Also fails, if the {@code leaderboard} is not a + * {@link RegattaLeaderboard}. */ void denoteRaceForRaceLogTracking(RacingEventService service, Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet, String raceName) throws NotDenotableForRaceLogTrackingException; - + /** - * Revoke the {@link RaceLogDenoteForTrackingEvent}, and if it exists the {@link RaceLogStartTrackingEvent}. - * This does not affect existing an {@link RaceLogRaceTracker} - * or {@link TrackedRace} for this {@code RaceLog}. + * Revoke the {@link RaceLogDenoteForTrackingEvent}, and if it exists the {@link RaceLogStartTrackingEvent}. This + * does not affect existing an {@link RaceLogRaceTracker} or {@link TrackedRace} for this {@code RaceLog}. */ void removeDenotationForRaceLogTracking(RacingEventService service, RaceLog raceLog); @@ -71,30 +74,35 @@ public interface RaceLogTrackingAdapter { */ void denoteAllRacesForRaceLogTracking(RacingEventService service, Leaderboard leaderboard) throws NotDenotableForRaceLogTrackingException; - + /** * Add a fix to the {@link GPSFixStore}, and create a mapping with a virtual device for exactly that timepoint. */ void pingMark(RaceLog raceLogToAddTo, Mark mark, GPSFix gpsFix, RacingEventService service); - + /** - * Duplicate the course and competitor registrations in the newest {@link RaceLogCourseDesignChangedEvent} - * in {@code from} race log to the {@code to} race logs. - * The {@link Mark}s and {@link ControlPoint}s are duplicated and not reused. This also inserts the necessary - * {@link RaceLogDefineMarkEvent}s into the {@code to} race logs. + * Duplicate the course and competitor registrations in the newest {@link RaceLogCourseDesignChangedEvent} in + * {@code from} race log to the {@code to} race logs. The {@link Mark}s and {@link ControlPoint}s are duplicated and + * not reused. This also inserts the necessary {@link RaceLogDefineMarkEvent}s into the {@code to} race logs. */ void copyCourseAndCompetitors(RaceLog from, Set to, SharedDomainFactory baseDomainFactory, RacingEventService service); - + /** - * If not yet registered, register the competitors in {@code competitors}, - * and unregister all already registered competitors not in {@code competitors}. + * If not yet registered, register the competitors in {@code competitors}, and unregister all already registered + * competitors not in {@code competitors}. */ void registerCompetitors(RacingEventService service, RaceLog raceLog, Set competitors); - + /** - * If not yet registered, register the competitors in {@code competitors}, - * and unregister all already registered competitors not in {@code competitors}. + * If not yet registered, register the competitors in {@code competitors}, and unregister all already registered + * competitors not in {@code competitors}. */ void registerCompetitors(RacingEventService service, RegattaLog regattaLog, Set competitors); + + /** + * Invite competitors for tracking via the Tracking App by sending out emails. + */ + void inviteCompetitorsForTrackingViaEmail(Event event, Leaderboard leaderboard, + String serverUrlWithoutTrailingSlash, Set competitors, Locale locale) throws MailException; } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/Activator.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/Activator.java index c66d80ac9c5..e26a03e2f62 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/Activator.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/Activator.java @@ -36,6 +36,12 @@ import com.sap.sse.common.TypeBasedServiceFinder; public class Activator implements BundleActivator { private static final Logger logger = Logger.getLogger(Activator.class.getName()); + + private static BundleContext context; + + public static BundleContext getContext() { + return context; + } private Set> registrations = new HashSet<>(); @@ -53,6 +59,8 @@ public class Activator implements BundleActivator { @Override public void start(BundleContext context) throws Exception { + Activator.context = context; + registrations.add(context.registerService(DeviceIdentifierMongoHandler.class, new SmartphoneUUIDMongoHandler(), getDict(SmartphoneUUIDIdentifier.TYPE))); registrations.add(context.registerService(DeviceIdentifierJsonHandler.class, new SmartphoneUUIDJsonHandler(), getDict(SmartphoneUUIDIdentifier.TYPE))); registrations.add(context.registerService(DeviceIdentifierStringSerializationHandler.class, new SmartphoneUUIDStringSerializationHandler(), getDict(SmartphoneUUIDIdentifier.TYPE))); @@ -75,6 +83,8 @@ public class Activator implements BundleActivator { @Override public void stop(BundleContext context) throws Exception { + Activator.context = null; + for (ServiceRegistration reg : registrations) { reg.unregister(); } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java index 07317ec94ed..c321270dc4d 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java @@ -1,8 +1,11 @@ package com.sap.sailing.domain.racelogtracking.impl; +import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -10,6 +13,17 @@ import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; +import javax.activation.DataHandler; +import javax.activation.DataSource; +import javax.mail.BodyPart; +import javax.mail.MessagingException; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMultipart; +import javax.mail.util.ByteArrayDataSource; + +import org.osgi.framework.ServiceReference; + +import com.google.zxing.WriterException; import com.sap.sailing.domain.abstractlog.AbstractLog; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; @@ -32,6 +46,7 @@ import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceColumn; @@ -42,6 +57,7 @@ import com.sap.sailing.domain.base.impl.CourseDataImpl; import com.sap.sailing.domain.common.PassingInstruction; import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; +import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException; import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException; import com.sap.sailing.domain.common.racelog.tracking.RaceLogRaceTrackerExistsException; @@ -61,6 +77,10 @@ import com.sap.sse.common.NoCorrespondingServiceRegisteredException; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.common.mail.MailException; +import com.sap.sse.mail.MailService; +import com.sap.sse.qrcode.QRCodeGenerationUtil; +import com.sap.sse.util.impl.NonGwtUrlHelper; public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { private static final Logger logger = Logger.getLogger(RaceLogTrackingAdapterImpl.class.getName()); @@ -325,4 +345,66 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { c -> new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), service.getServerAuthor(), MillisecondsTimePoint.now(), UUID.randomUUID(), c)); } + + private MailService getMailService() { + ServiceReference ref = Activator.getContext() + .getServiceReference(MailService.class); + if (ref == null) { + logger.warning("No file storage management service registered"); + return null; + } + return Activator.getContext().getService(ref); + } + + @Override + public void inviteCompetitorsForTrackingViaEmail(Event event, Leaderboard leaderboard, + String serverUrlWithoutTrailingSlash, Set competitors, Locale locale) throws MailException { + StringBuilder occuredExceptions = new StringBuilder(); + + for (Competitor competitor : competitors){ + final String toAddress = competitor.getEmail(); + if (toAddress != null) { + String leaderboardName = leaderboard.getName(); + String competitorName = competitor.getName(); + + String url = DeviceMappingConstants.getDeviceMappingForRegattaLogUrl(serverUrlWithoutTrailingSlash, + event.getId().toString(), leaderboardName, DeviceMappingConstants.URL_COMPETITOR_ID_AS_STRING, + competitor.getId().toString(), NonGwtUrlHelper.INSTANCE); + String subject = String.format("%s %s", + RaceLogTrackingI18n.STRING_MESSAGES.get(locale, "trackingInvitationFor"), competitorName); + + // taken from http://www.tutorialspoint.com/javamail_api/javamail_api_send_inlineimage_in_email.htm + BodyPart messageTextPart = new MimeBodyPart(); + String htmlText = String.format("

    %s %s

    " + "

    %s %s

    " + + "
    " + + "%s", + RaceLogTrackingI18n.STRING_MESSAGES.get(locale, "welcomeTo"), leaderboardName, + RaceLogTrackingI18n.STRING_MESSAGES.get(locale, "scanQRCodeOrVisitUrlToRegisterAs"), competitorName, + url, url, RaceLogTrackingI18n.STRING_MESSAGES.get(locale, "alternativelyVisitThisLink")); + + try { + messageTextPart.setContent(htmlText, "text/html"); + + BodyPart messageImagePart = new MimeBodyPart(); + InputStream imageIs = QRCodeGenerationUtil.create(url, 250); + DataSource imageDs = new ByteArrayDataSource(imageIs, "image/png"); + messageImagePart.setDataHandler(new DataHandler(imageDs)); + messageImagePart.setHeader("Content-ID", ""); + + MimeMultipart multipart = new MimeMultipart(); + multipart.addBodyPart(messageTextPart); + multipart.addBodyPart(messageImagePart); + + getMailService().sendMail(toAddress, subject, multipart); + } catch (MessagingException | MailException | WriterException | IOException e) { + logger.log(Level.SEVERE, "Error trying to send mail to " + competitor.getName() + + " with e-mail address " + toAddress, e); + occuredExceptions.append(e.getMessage()+"\r\n"); + } + } + } + if (!(occuredExceptions.length() == 0)){ + throw new MailException(occuredExceptions.toString()); + } + } } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingI18n.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingI18n.java new file mode 100644 index 00000000000..0a3fa3a6876 --- /dev/null +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingI18n.java @@ -0,0 +1,11 @@ +package com.sap.sailing.domain.racelogtracking.impl; + +import com.sap.sse.i18n.ResourceBundleStringMessages; +import com.sap.sse.i18n.impl.ResourceBundleStringMessagesImpl; + +public class RaceLogTrackingI18n { + private static final String RESOURCE_BASE_NAME = "stringmessages/TrackingStringMessages"; + + public static final ResourceBundleStringMessages STRING_MESSAGES = new ResourceBundleStringMessagesImpl( + RESOURCE_BASE_NAME, RaceLogTrackingI18n.class.getClassLoader()); +} diff --git a/java/com.sap.sailing.domain.shared.android.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.shared.android.test/META-INF/MANIFEST.MF index 3a9de8a9222..1b6d41de6cb 100644 --- a/java/com.sap.sailing.domain.shared.android.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.shared.android.test/META-INF/MANIFEST.MF @@ -1,18 +1,18 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: com.sap.sailing.domain.shared.android.test -Bundle-SymbolicName: com.sap.sailing.domain.shared.android.test -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: com.sap.sailing.domain.common;bundle-version="1.0.0", - com.sap.sailing.domain.shared.android;bundle-version="1.0.0", - org.hamcrest;bundle-version="1.1.0", - org.junit4;bundle-version="4.8.2", - org.objenesis;bundle-version="1.3.0", - org.mockito.mockito-core;bundle-version="1.9.5", - com.sap.sailing.domain.test, - com.sap.sailing.domain.racelogtrackingadapter.testsupport;bundle-version="1.0.0", - com.sap.sse.common, - com.sap.sse, - com.sap.sse.shared.android +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: com.sap.sailing.domain.shared.android.test +Bundle-SymbolicName: com.sap.sailing.domain.shared.android.test +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: com.sap.sailing.domain.common;bundle-version="1.0.0", + com.sap.sailing.domain.shared.android;bundle-version="1.0.0", + org.hamcrest;bundle-version="1.1.0", + org.junit4;bundle-version="4.8.2", + org.objenesis;bundle-version="1.3.0", + org.mockito.mockito-core;bundle-version="1.9.5", + com.sap.sailing.domain.test, + com.sap.sailing.domain.racelogtrackingadapter.testsupport;bundle-version="1.0.0", + com.sap.sse.common, + com.sap.sse, + com.sap.sse.shared.android diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/MultiLogAnalyzerTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/MultiLogAnalyzerTest.java index 60dbfaa4d6d..fe618620b4c 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/MultiLogAnalyzerTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/MultiLogAnalyzerTest.java @@ -52,7 +52,7 @@ public class MultiLogAnalyzerTest { private AbstractLogEventAuthor author; private static Competitor createCompetitor(int n) { - return new CompetitorImpl(n, n + "", null, null, null); + return new CompetitorImpl(n, n + "", null, null, null, null); } private static DeviceIdentifier createDevice() { diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/DeviceMappingFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/DeviceMappingFinderTest.java index b564043ec86..8eb28322665 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/DeviceMappingFinderTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/DeviceMappingFinderTest.java @@ -22,8 +22,8 @@ import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; public class DeviceMappingFinderTest extends AbstractRaceLogTrackingTest { - private final Competitor competitor = new CompetitorImpl("comp", "Comp", null, null, null); - private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", null, null, null); + private final Competitor competitor = new CompetitorImpl("comp", "Comp", null, null, null, null); + private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", null, null, null, null); private final DeviceIdentifier device = new SmartphoneImeiIdentifier("imei"); private int time = 0; diff --git a/java/com.sap.sailing.domain.shared.android/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.shared.android/META-INF/MANIFEST.MF index faa0eb1a9b0..6431fe5e794 100644 --- a/java/com.sap.sailing.domain.shared.android/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.shared.android/META-INF/MANIFEST.MF @@ -1,50 +1,50 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: com.sap.sailing.domain.shared.android -Bundle-SymbolicName: com.sap.sailing.domain.shared.android -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Require-Bundle: com.sap.sailing.domain.common, - com.sap.sse.datamining.shared, - com.sap.sse.common, - com.sap.sse.shared.android -Export-Package: com.sap.sailing.domain.abstractlog, - com.sap.sailing.domain.abstractlog.impl, - com.sap.sailing.domain.abstractlog.race, - com.sap.sailing.domain.abstractlog.race.analyzing.impl, - com.sap.sailing.domain.abstractlog.race.impl, - com.sap.sailing.domain.abstractlog.race.scoring, - com.sap.sailing.domain.abstractlog.race.scoring.impl, - com.sap.sailing.domain.abstractlog.race.state, - com.sap.sailing.domain.abstractlog.race.state.impl, - com.sap.sailing.domain.abstractlog.race.state.racingprocedure, - com.sap.sailing.domain.abstractlog.race.state.racingprocedure.basic, - com.sap.sailing.domain.abstractlog.race.state.racingprocedure.basic.impl, - com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ess, - com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ess.impl, - com.sap.sailing.domain.abstractlog.race.state.racingprocedure.gate, - com.sap.sailing.domain.abstractlog.race.state.racingprocedure.gate.impl, - com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl, - com.sap.sailing.domain.abstractlog.race.state.racingprocedure.rrs26, - com.sap.sailing.domain.abstractlog.race.state.racingprocedure.rrs26.impl, - com.sap.sailing.domain.abstractlog.race.tracking, - com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl, - com.sap.sailing.domain.abstractlog.race.tracking.impl, - com.sap.sailing.domain.abstractlog.regatta, - com.sap.sailing.domain.abstractlog.regatta.events, - com.sap.sailing.domain.abstractlog.regatta.events.impl, - com.sap.sailing.domain.abstractlog.regatta.impl, - com.sap.sailing.domain.abstractlog.shared.analyzing, - com.sap.sailing.domain.abstractlog.shared.events, - com.sap.sailing.domain.base, - com.sap.sailing.domain.base.configuration, - com.sap.sailing.domain.base.configuration.impl, - com.sap.sailing.domain.base.configuration.procedures, - com.sap.sailing.domain.base.impl, - com.sap.sailing.domain.base.racegroup, - com.sap.sailing.domain.base.racegroup.impl, - com.sap.sailing.domain.racelogtracking, - com.sap.sailing.domain.racelogtracking.impl, - com.sap.sailing.domain.tracking, - com.sap.sailing.domain.tracking.impl +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: com.sap.sailing.domain.shared.android +Bundle-SymbolicName: com.sap.sailing.domain.shared.android +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Require-Bundle: com.sap.sailing.domain.common, + com.sap.sse.datamining.shared, + com.sap.sse.common, + com.sap.sse.shared.android +Export-Package: com.sap.sailing.domain.abstractlog, + com.sap.sailing.domain.abstractlog.impl, + com.sap.sailing.domain.abstractlog.race, + com.sap.sailing.domain.abstractlog.race.analyzing.impl, + com.sap.sailing.domain.abstractlog.race.impl, + com.sap.sailing.domain.abstractlog.race.scoring, + com.sap.sailing.domain.abstractlog.race.scoring.impl, + com.sap.sailing.domain.abstractlog.race.state, + com.sap.sailing.domain.abstractlog.race.state.impl, + com.sap.sailing.domain.abstractlog.race.state.racingprocedure, + com.sap.sailing.domain.abstractlog.race.state.racingprocedure.basic, + com.sap.sailing.domain.abstractlog.race.state.racingprocedure.basic.impl, + com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ess, + com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ess.impl, + com.sap.sailing.domain.abstractlog.race.state.racingprocedure.gate, + com.sap.sailing.domain.abstractlog.race.state.racingprocedure.gate.impl, + com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl, + com.sap.sailing.domain.abstractlog.race.state.racingprocedure.rrs26, + com.sap.sailing.domain.abstractlog.race.state.racingprocedure.rrs26.impl, + com.sap.sailing.domain.abstractlog.race.tracking, + com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl, + com.sap.sailing.domain.abstractlog.race.tracking.impl, + com.sap.sailing.domain.abstractlog.regatta, + com.sap.sailing.domain.abstractlog.regatta.events, + com.sap.sailing.domain.abstractlog.regatta.events.impl, + com.sap.sailing.domain.abstractlog.regatta.impl, + com.sap.sailing.domain.abstractlog.shared.analyzing, + com.sap.sailing.domain.abstractlog.shared.events, + com.sap.sailing.domain.base, + com.sap.sailing.domain.base.configuration, + com.sap.sailing.domain.base.configuration.impl, + com.sap.sailing.domain.base.configuration.procedures, + com.sap.sailing.domain.base.impl, + com.sap.sailing.domain.base.racegroup, + com.sap.sailing.domain.base.racegroup.impl, + com.sap.sailing.domain.racelogtracking, + com.sap.sailing.domain.racelogtracking.impl, + com.sap.sailing.domain.tracking, + com.sap.sailing.domain.tracking.impl diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java index fea24c2afea..8d65ec10e49 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java @@ -15,6 +15,10 @@ public interface Competitor extends Named, WithID, IsManagedByCache listeners; + private String email; - public CompetitorImpl(Serializable id, String name, Color color, DynamicTeam team, DynamicBoat boat) { + public CompetitorImpl(Serializable id, String name, Color color, String email, DynamicTeam team, DynamicBoat boat) { this.id = id; this.name = name; this.team = team; this.boat = boat; this.color = color; + this.email = email; this.listeners = new HashSet(); } @@ -73,7 +75,7 @@ public class CompetitorImpl implements DynamicCompetitor { @Override public Competitor resolve(SharedDomainFactory domainFactory) { - Competitor result = domainFactory.getOrCreateCompetitor(getId(), getName(), getColor(), getTeam(), getBoat()); + Competitor result = domainFactory.getOrCreateCompetitor(getId(), getName(), getColor(), getEmail(), getTeam(), getBoat()); return result; } @@ -114,4 +116,22 @@ public class CompetitorImpl implements DynamicCompetitor { return new HashSet(listeners); } } + + public String getEmail() { + return email; + } + + public void setEmail(String newEmail) { + final String oldEmail = this.email; + if (!Util.equalsWithNull(oldEmail, newEmail)) { + this.email = newEmail; + for (CompetitorChangeListener listener : getListeners()) { + listener.emailChanged(oldEmail, newEmail); + } + } + } + + public boolean hasEmail(){ + return email != null && !email.isEmpty(); + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java index 768c6f15255..4b6a86578f0 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java @@ -6,7 +6,10 @@ import com.sap.sse.common.Color; public interface DynamicCompetitor extends Competitor, Renamable { DynamicBoat getBoat(); + DynamicTeam getTeam(); - + void setColor(Color displayColor); + + void setEmail(String email); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java index 0d6a8cd5f42..3e6a0ecf5d0 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java @@ -332,11 +332,11 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { } @Override - public Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, DynamicTeam team, DynamicBoat boat) { + public Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email, DynamicTeam team, DynamicBoat boat) { if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, "getting or creating competitor "+name+" with ID "+competitorId+" in domain factory "+this); } - return getCompetitorStore().getOrCreateCompetitor(competitorId, name, displayColor, team, boat); + return getCompetitorStore().getOrCreateCompetitor(competitorId, name, displayColor, email, team, boat); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 16051ae3835..7c9f8395f45 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -68,8 +68,8 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab listeners.remove(listener); } - private Competitor createCompetitor(Serializable id, String name, Color displayColor, DynamicTeam team, DynamicBoat boat) { - Competitor result = new CompetitorImpl(id, name, displayColor, team, boat); + private Competitor createCompetitor(Serializable id, String name, Color displayColor, String email, DynamicTeam team, DynamicBoat boat) { + Competitor result = new CompetitorImpl(id, name, displayColor, email, team, boat); addNewCompetitor(id, result); if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, "Created competitor "+name+" with ID "+id, new Exception("Here is where it happened")); @@ -93,20 +93,20 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } @Override - public Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, DynamicTeam team, DynamicBoat boat) { + public Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email, DynamicTeam team, DynamicBoat boat) { Competitor result = getExistingCompetitorById(competitorId); // avoid synchronization for successful read access if (result == null) { LockUtil.lockForWrite(lock); try { result = getExistingCompetitorById(competitorId); // try again, now while holding the write lock if (result == null) { - result = createCompetitor(competitorId, name, displayColor, team, boat); + result = createCompetitor(competitorId, name, displayColor, email, team, boat); } } finally { LockUtil.unlockAfterWrite(lock); } } else if (isCompetitorToUpdateDuringGetOrCreate(result)) { - updateCompetitor(result.getId().toString(), name, displayColor, boat.getSailID(), team.getNationality(), + updateCompetitor(result.getId().toString(), name, displayColor, email, boat.getSailID(), team.getNationality(), team.getImage()); competitorNoLongerToUpdateDuringGetOrCreate(result); } @@ -191,7 +191,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } @Override - public Competitor updateCompetitor(String idAsString, String newName, Color newDisplayColor, String newSailId, + public Competitor updateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail, String newSailId, Nationality newNationality, URI newTeamImageUri) { DynamicCompetitor competitor = (DynamicCompetitor) getExistingCompetitorByIdAsString(idAsString); if (competitor != null) { @@ -199,6 +199,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab try { competitor.setName(newName); competitor.setColor(newDisplayColor); + competitor.setEmail(newEmail); competitor.getBoat().setSailId(newSailId); competitor.getTeam().setNationality(newNationality); competitor.getTeam().setImage(newTeamImageUri); @@ -229,7 +230,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab if (competitorDTO == null) { final Nationality nationality = c.getTeam().getNationality(); CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); - competitorDTO = new CompetitorDTOImpl(c.getName(), c.getColor(), countryCode == null ? "" + competitorDTO = new CompetitorDTOImpl(c.getName(), c.getColor(), c.getEmail(), countryCode == null ? "" : countryCode.getTwoLetterISOCode(), countryCode == null ? "" : countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(), c .getBoat().getSailID(), c.getId().toString(), new BoatClassDTO(c.getBoat().getBoatClass() diff --git a/java/com.sap.sailing.domain.swisstimingadapter.persistence/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.swisstimingadapter.persistence/META-INF/MANIFEST.MF index 8223a8c384f..e327c07a9c4 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter.persistence/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.swisstimingadapter.persistence/META-INF/MANIFEST.MF @@ -7,7 +7,7 @@ Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Require-Bundle: com.sap.sailing.domain.swisstimingadapter, - com.mongodb.driver;bundle-version="2.6.2", + org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sse.mongodb, com.sap.sailing.domain, com.sap.sailing.domain.common diff --git a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java index ed986b6c4e0..fb4d0e33ead 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java @@ -87,7 +87,7 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers @Override public void storeSwissTimingConfiguration(SwissTimingConfiguration swissTimingConfiguration) { DBCollection stConfigCollection = database.getCollection(CollectionNames.SWISSTIMING_CONFIGURATIONS.name()); - stConfigCollection.ensureIndex(CollectionNames.SWISSTIMING_CONFIGURATIONS.name()); + stConfigCollection.createIndex(new BasicDBObject(CollectionNames.SWISSTIMING_CONFIGURATIONS.name(), 1)); BasicDBObject result = new BasicDBObject(); result.put(FieldNames.ST_CONFIG_NAME.name(), swissTimingConfiguration.getName()); for (DBObject equallyNamedConfig : stConfigCollection.find(result)) { @@ -104,7 +104,7 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers public void storeSwissTimingArchiveConfiguration( SwissTimingArchiveConfiguration createSwissTimingArchiveConfiguration) { DBCollection stArchiveConfigCollection = database.getCollection(CollectionNames.SWISSTIMING_ARCHIVE_CONFIGURATIONS.name()); - stArchiveConfigCollection.ensureIndex(CollectionNames.SWISSTIMING_ARCHIVE_CONFIGURATIONS.name()); + stArchiveConfigCollection.createIndex(new BasicDBObject(CollectionNames.SWISSTIMING_ARCHIVE_CONFIGURATIONS.name(), 1)); BasicDBObject result = new BasicDBObject(); result.put(FieldNames.ST_ARCHIVE_JSON_URL.name(), createSwissTimingArchiveConfiguration.getJsonUrl()); for (DBObject equallyNamedConfig : stArchiveConfigCollection.find(result)) { diff --git a/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF index 848c68a4fe2..719c89203da 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF @@ -8,7 +8,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Fragment-Host: com.sap.sailing.domain.swisstimingadapter Require-Bundle: com.sap.sailing.domain, com.sap.sailing.udpconnector, - com.mongodb.driver;bundle-version="2.6.2", + org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sse.mongodb, com.googlecode.java-diff-utils;bundle-version="1.3.0", com.sap.sailing.server, diff --git a/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index 1098f1d683c..8f3cd37b203 --- a/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF @@ -1,21 +1,21 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Swisstimingadapter -Bundle-SymbolicName: com.sap.sailing.domain.swisstimingadapter -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Bundle-ActivationPolicy: lazy -Require-Bundle: com.sap.sailing.domain, - com.sap.sailing.udpconnector, - com.googlecode.java-diff-utils;bundle-version="1.3.0", - com.sap.sailing.domain.common, - com.sap.sailing.xrr.resultimport, - com.sap.sse.common, - com.sap.sse, - com.sap.sailing.xrr.schema -Export-Package: com.sap.sailing.domain.swisstimingadapter, - com.sap.sailing.domain.swisstimingadapter.impl;x-friends:="com.sap.sailing.server.test" -Import-Package: com.sap.sailing.xrr.schema, - org.osgi.framework -Bundle-Activator: com.sap.sailing.domain.swisstimingadapter.impl.Activator +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Swisstimingadapter +Bundle-SymbolicName: com.sap.sailing.domain.swisstimingadapter +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Require-Bundle: com.sap.sailing.domain, + com.sap.sailing.udpconnector, + com.googlecode.java-diff-utils;bundle-version="1.3.0", + com.sap.sailing.domain.common, + com.sap.sailing.xrr.resultimport, + com.sap.sse.common, + com.sap.sse, + com.sap.sailing.xrr.schema +Export-Package: com.sap.sailing.domain.swisstimingadapter, + com.sap.sailing.domain.swisstimingadapter.impl;x-friends:="com.sap.sailing.server.test" +Import-Package: com.sap.sailing.xrr.schema, + org.osgi.framework +Bundle-Activator: com.sap.sailing.domain.swisstimingadapter.impl.Activator diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index 7f4d7c96c96..673737f2f5b 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -124,7 +124,7 @@ public class DomainFactoryImpl implements DomainFactory { teamMembers.add(person); } DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null); - result = competitorStore.getOrCreateCompetitor(competitor.getID(), competitor.getName(), null /*displayColor*/, team, boat); + result = competitorStore.getOrCreateCompetitor(competitor.getID(), competitor.getName(), null /*displayColor*/, null /*email*/, team, boat); } return result; } @@ -140,7 +140,7 @@ public class DomainFactoryImpl implements DomainFactory { } DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null); result = baseDomainFactory.getCompetitorStore().getOrCreateCompetitor(getCompetitorID(competitor.getBoatID(), raceId, boatClass), - competitor.getName(), null /*displayColor*/, team, boat); + competitor.getName(), null /*displayColor*/, null /*email*/, team, boat); return result; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java index dd915231da5..724aac107ce 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java @@ -232,7 +232,7 @@ public class LeaderboardDTODiffingTest { @Test public void testCompetitorListChange() { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "DE", "GER", "Germany", "GER 1234", "912p09871203987", + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "GER 1234", "912p09871203987", new BoatClassDTO("505", 5.05)); newVersion.competitors.add(13, somebodyNew); // insert a competitor; this should mess up all others' indexes; check if this works CompetitorDTO wolfgang = getPreviousCompetitorByName("HUNGER +JESS"); @@ -252,7 +252,7 @@ public class LeaderboardDTODiffingTest { Util.addAll(newVersion.getSuppressedCompetitors(), newSuppressedCompetitors); newVersion.setSuppressedCompetitors(newSuppressedCompetitors); newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "DE", "GER", "Germany", "GER 1234", "912p09871203987", + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "GER 1234", "912p09871203987", new BoatClassDTO("505", 5.05)); newVersion.setSuppressed(newVersion.competitors.get(13), true); // suppress an existing competitor; compaction should reduce this to a single number only newVersion.setSuppressed(somebodyNew, true); // check that mixed mode with existing and new competitors works as well @@ -274,7 +274,7 @@ public class LeaderboardDTODiffingTest { @Test public void testDisplayNameChange() { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "DE", "GER", "Germany", "GER 1234", "912p09871203987", + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "GER 1234", "912p09871203987", new BoatClassDTO("505", 5.05)); newVersion.competitors.add(somebodyNew); newVersion.competitorDisplayNames = new HashMap(newVersion.competitorDisplayNames); @@ -303,7 +303,7 @@ public class LeaderboardDTODiffingTest { List newOrdering = new ArrayList(newVersion.getCompetitorsFromBestToWorst(r9)); newVersion.setCompetitorsFromBestToWorst(r9, newOrdering); newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "DE", "GER", "Germany", "GER 1234", "912p09871203987", + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "GER 1234", "912p09871203987", new BoatClassDTO("505", 5.05)); newVersion.competitors.add(somebodyNew); newOrdering.add(somebodyNew); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java index 9870f58ac90..65e0817f4ee 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java @@ -15,16 +15,16 @@ import com.sap.sse.common.Color; public abstract class AbstractLeaderboardTest { public static CompetitorImpl createCompetitor(String competitorName) { - return new CompetitorImpl(competitorName, competitorName, Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl(competitorName, new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous "+competitorName)), - new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", + return new CompetitorImpl(competitorName, competitorName, Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl(competitorName, new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous "+competitorName)), + new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null)); } public static Competitor createCompetitor(String competitorName, CompetitorFactory competitorFactory) { - return competitorFactory.getOrCreateCompetitor(competitorName, competitorName, Color.RED, new TeamImpl("STG", Collections.singleton( + return competitorFactory.getOrCreateCompetitor(competitorName, competitorName, Color.RED, "someone@nobody.de", new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), @@ -33,11 +33,11 @@ public abstract class AbstractLeaderboardTest { } public static CompetitorImpl createCompetitor(String competitorName, Serializable id) { - return new CompetitorImpl(id, competitorName, Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl(competitorName, new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous "+competitorName)), - new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", + return new CompetitorImpl(id, competitorName, Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl(competitorName, new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous "+competitorName)), + new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null)); } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java index bdef38602ad..ca8acdfaa70 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java @@ -94,6 +94,11 @@ public class CompetitorListenerTest extends AbstractSerializationTest { CompetitorListenerTest.this.oldColor = oldColor; CompetitorListenerTest.this.newColor = newColor; } + + @Override + public void emailChanged(String oldEmail, String newEmail) { + //TODO + } }; competitor.addCompetitorChangeListener(listener); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java index c6e4e4711ab..b05c4afee5e 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java @@ -157,8 +157,8 @@ public class LeaderboardCourseChangeTest { Set competitors = new HashSet<>(); DynamicBoat mockedBoat = mock(DynamicBoat.class); when(mockedBoat.getBoatClass()).thenReturn(boatClass); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "TestCompetitor", Color.BLACK, mock(DynamicTeam.class), - mockedBoat)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "TestCompetitor", Color.BLACK, null, + mock(DynamicTeam.class), mockedBoat)); return competitors; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java index 1e34a56762c..f6d164910e6 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java @@ -188,11 +188,11 @@ public class OfflineSerializationTest extends AbstractSerializationTest { DomainFactory senderDomainFactory = new DomainFactoryImpl(); DomainFactory receiverDomainFactory = new DomainFactoryImpl(); String competitorName = "Tina Maximiliane Lutz"; - Competitor sendersCompetitor1 = new CompetitorImpl(123, competitorName, Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl(competitorName, senderDomainFactory.getOrCreateNationality("GER"), - /* dateOfBirth */ null, "This is famous "+competitorName)), - new PersonImpl("Rigo van Maas", senderDomainFactory.getOrCreateNationality("GER"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", + Competitor sendersCompetitor1 = new CompetitorImpl(123, competitorName, Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl(competitorName, senderDomainFactory.getOrCreateNationality("GER"), + /* dateOfBirth */ null, "This is famous "+competitorName)), + new PersonImpl("Rigo van Maas", senderDomainFactory.getOrCreateNationality("GER"), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", senderDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61")); Competitor receiversCompetitor1 = cloneBySerialization(sendersCompetitor1, receiverDomainFactory); Competitor receiversSecondCopyOfCompetitor1 = cloneBySerialization(sendersCompetitor1, receiverDomainFactory); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java index 9b5bc2dacf6..1ca4fa9f623 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java @@ -117,7 +117,7 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest { for (String competitorName : getCompetitorNamesOfStoredTracks(KIELER_WOCHE)) { DynamicPerson p = new PersonImpl(competitorName, /* nationality */ null, /* dateOfBirth */ null, /* description */ null); DynamicTeam t = new TeamImpl(competitorName, Collections.singleton(p), /* coach */ null); - Competitor c = new CompetitorImpl(competitorName, competitorName, Color.RED, t, new BoatImpl(competitorName, + Competitor c = new CompetitorImpl(competitorName, competitorName, Color.RED, null, t, new BoatImpl(competitorName, new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); DynamicGPSFixTrack track = readTrack(c, KIELER_WOCHE); if (track != null) { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java index 414ea94a80f..fc0c6037871 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java @@ -34,11 +34,11 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace { @Override @Before public void setUp() { - competitor = new CompetitorImpl(123, "Wolfgang Hunger", Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl("Wolfgang Hunger", new NationalityImpl("GER"), - /* dateOfBirth */null, "This is famous Wolfgang Hunger")), new PersonImpl("Rigo van Maas", - new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("Wolfgang Hunger's boat", + competitor = new CompetitorImpl(123, "Wolfgang Hunger", Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl("Wolfgang Hunger", new NationalityImpl("GER"), + /* dateOfBirth */null, "This is famous Wolfgang Hunger")), new PersonImpl("Rigo van Maas", + new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", Collections.singleton(competitor), new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()))); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java index 99d8ab7bfe9..faeaca23b4e 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java @@ -60,11 +60,11 @@ public abstract class TrackBasedTest { } public static CompetitorImpl createCompetitor(String competitorName) { - return new CompetitorImpl(UUID.randomUUID(), competitorName, Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl(competitorName, new NationalityImpl("GER"), - /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", - new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", + return new CompetitorImpl(UUID.randomUUID(), competitorName, Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl(competitorName, new NationalityImpl("GER"), + /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", + new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), null)); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java index 73397e43197..64368e6e02e 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java @@ -270,11 +270,11 @@ public class WindTest { Waypoint w1 = domainFactory.createWaypoint(startFinish, /*passingInstruction*/ null); Waypoint w2 = domainFactory.createWaypoint(top, /*passingInstruction*/ null); Waypoint w3 = domainFactory.createWaypoint(startFinish, /*passingInstruction*/ null); - Competitor competitor = new CompetitorImpl(123, "Test Competitor", Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl("Test Competitor", new NationalityImpl("GER"), - /* dateOfBirth */null, "This is famous " + "Test Competitor")), new PersonImpl("Rigo van Maas", - new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("Test Competitor" + "'s boat", + Competitor competitor = new CompetitorImpl(123, "Test Competitor", Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl("Test Competitor", new NationalityImpl("GER"), + /* dateOfBirth */null, "This is famous " + "Test Competitor")), new PersonImpl("Rigo van Maas", + new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("Test Competitor" + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), null)); final BoatClass boatClass = domainFactory.getOrCreateBoatClass("ESS40"); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl( diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java index 4e636675bbd..30ce75475d8 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java @@ -45,9 +45,9 @@ import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; public class AbstractMockedRaceMarkPassingTest { - protected Competitor bob = new CompetitorImpl("Bob", "Bob", null, null, null); - protected Competitor joe = new CompetitorImpl("Joe", "Joe", null, null, null); - protected Competitor mike = new CompetitorImpl("Mike", "Mike", null, null, null); + protected Competitor bob = new CompetitorImpl("Bob", "Bob", null, null, null, null); + protected Competitor joe = new CompetitorImpl("Joe", "Joe", null, null, null, null); + protected Competitor mike = new CompetitorImpl("Mike", "Mike", null, null, null, null); protected Mark m = new MarkImpl("black"); protected Mark m2 = new MarkImpl("white 1"); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index 817943466eb..debb3bdcd57 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -13,6 +13,7 @@ import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.CourseBase; +import com.sap.sailing.domain.base.EventFetcher; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceColumnListener; @@ -290,7 +291,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { } @Override - public Iterable getCompetitors() { + public Iterable getAllCompetitors() { return null; } @@ -430,6 +431,10 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public void removeListener(RegattaLikeListener listener) { } + + @Override + public void adjustEventToRegattaAssociation(EventFetcher eventFetcher) { + } }; } diff --git a/java/com.sap.sailing.domain.tractracadapter.persistence/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.tractracadapter.persistence/META-INF/MANIFEST.MF index 953265121d1..682a42bbc63 100644 --- a/java/com.sap.sailing.domain.tractracadapter.persistence/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.tractracadapter.persistence/META-INF/MANIFEST.MF @@ -6,7 +6,7 @@ Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy -Require-Bundle: com.mongodb.driver;bundle-version="2.6.2", +Require-Bundle: org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sse.mongodb, com.sap.sailing.domain.tractracadapter, com.sap.sailing.domain, diff --git a/java/com.sap.sailing.domain.tractracadapter.persistence/src/com/sap/sailing/domain/tractracadapter/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter.persistence/src/com/sap/sailing/domain/tractracadapter/persistence/impl/MongoObjectFactoryImpl.java index 62b6fc9adc8..179886f4b48 100755 --- a/java/com.sap.sailing.domain.tractracadapter.persistence/src/com/sap/sailing/domain/tractracadapter/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter.persistence/src/com/sap/sailing/domain/tractracadapter/persistence/impl/MongoObjectFactoryImpl.java @@ -18,7 +18,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void storeTracTracConfiguration(TracTracConfiguration tracTracConfiguration) { DBCollection ttConfigCollection = database.getCollection(CollectionNames.TRACTRAC_CONFIGURATIONS.name()); - ttConfigCollection.ensureIndex(CollectionNames.TRACTRAC_CONFIGURATIONS.name()); + ttConfigCollection.createIndex(new BasicDBObject(CollectionNames.TRACTRAC_CONFIGURATIONS.name(), 1)); BasicDBObject result = new BasicDBObject(); result.put(FieldNames.TT_CONFIG_NAME.name(), tracTracConfiguration.getName()); for (DBObject equallyNamedConfig : ttConfigCollection.find(result)) { diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index 289ecceb33e..650902ae32a 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -259,7 +259,7 @@ public class DomainFactoryImpl implements DomainFactory { } DynamicTeam team = getOrCreateTeam(name, nationality, competitorId); DynamicBoat boat = new BoatImpl(shortName, boatClass, shortName); - result = competitorStore.getOrCreateCompetitor(competitorId, name, null /*displayColor*/, team, boat); + result = competitorStore.getOrCreateCompetitor(competitorId, name, null /*displayColor*/, null /*email*/, team, boat); } return result; } diff --git a/java/com.sap.sailing.domain/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index 81ee7d0a467..a9856674f3d --- a/java/com.sap.sailing.domain/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain/META-INF/MANIFEST.MF @@ -1,40 +1,40 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Domain -Bundle-SymbolicName: com.sap.sailing.domain -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Bundle-ClassPath: . -Export-Package: com.sap.sailing.domain.base, - com.sap.sailing.domain.base.impl, - com.sap.sailing.domain.confidence, - com.sap.sailing.domain.leaderboard, - com.sap.sailing.domain.leaderboard.caching, - com.sap.sailing.domain.leaderboard.impl, - com.sap.sailing.domain.leaderboard.meta, - com.sap.sailing.domain.markpassingcalculation, - com.sap.sailing.domain.markpassingcalculation.splining, - com.sap.sailing.domain.masterdataimport, - com.sap.sailing.domain.racelog, - com.sap.sailing.domain.racelog.impl, - com.sap.sailing.domain.racelog.tracking, - com.sap.sailing.domain.regattalike, - com.sap.sailing.domain.regattalog, - com.sap.sailing.domain.regattalog.impl, - com.sap.sailing.domain.trackfiles, - com.sap.sailing.domain.trackimport, - com.sap.sailing.domain.tracking, - com.sap.sailing.domain.tracking.impl, - com.sap.sailing.util, - com.sap.sailing.util.impl;x-friends:="com.sap.sailing.server.replication,com.sap.sailing.domain.test" -Bundle-ActivationPolicy: lazy -Require-Bundle: com.googlecode.java-diff-utils;bundle-version="1.3.0", - com.sap.sailing.domain.shared.android, - com.sap.sailing.domain.common, - org.json.simple;bundle-version="1.1.0", - com.sap.sailing.geocoding, - com.sap.sse.datamining.shared, - com.sap.sse.common, - com.sap.sse, - com.sap.sse.shared.android +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Domain +Bundle-SymbolicName: com.sap.sailing.domain +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ClassPath: . +Export-Package: com.sap.sailing.domain.base, + com.sap.sailing.domain.base.impl, + com.sap.sailing.domain.confidence, + com.sap.sailing.domain.leaderboard, + com.sap.sailing.domain.leaderboard.caching, + com.sap.sailing.domain.leaderboard.impl, + com.sap.sailing.domain.leaderboard.meta, + com.sap.sailing.domain.markpassingcalculation, + com.sap.sailing.domain.markpassingcalculation.splining, + com.sap.sailing.domain.masterdataimport, + com.sap.sailing.domain.racelog, + com.sap.sailing.domain.racelog.impl, + com.sap.sailing.domain.racelog.tracking, + com.sap.sailing.domain.regattalike, + com.sap.sailing.domain.regattalog, + com.sap.sailing.domain.regattalog.impl, + com.sap.sailing.domain.trackfiles, + com.sap.sailing.domain.trackimport, + com.sap.sailing.domain.tracking, + com.sap.sailing.domain.tracking.impl, + com.sap.sailing.util, + com.sap.sailing.util.impl;x-friends:="com.sap.sailing.server.replication,com.sap.sailing.domain.test" +Bundle-ActivationPolicy: lazy +Require-Bundle: com.googlecode.java-diff-utils;bundle-version="1.3.0", + com.sap.sailing.domain.shared.android, + com.sap.sailing.domain.common, + org.json.simple;bundle-version="1.1.0", + com.sap.sailing.geocoding, + com.sap.sse.datamining.shared, + com.sap.sse.common, + com.sap.sse, + com.sap.sse.shared.android diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/EventFetcher.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/EventFetcher.java new file mode 100755 index 00000000000..98209eaeef1 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/EventFetcher.java @@ -0,0 +1,5 @@ +package com.sap.sailing.domain.base; + +public interface EventFetcher { + Iterable getAllEvents(); +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java index 0667d9ade2a..1dfb3d18d64 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java @@ -103,7 +103,7 @@ public interface Regatta extends Named, WithID, IsRegattaLike { BoatClass getBoatClass(); - Iterable getCompetitors(); + Iterable getAllCompetitors(); /** * Will remove the series from this regatta. Will also call {@link RaceColumn#removeRaceIdentifier(Fleet)} to make @@ -168,4 +168,12 @@ public interface Regatta extends Named, WithID, IsRegattaLike { * Updates the flag deciding whether to use start time inference. See {@link #useStartTimeInference()}. */ void setUseStartTimeInference(boolean useStartTimeInference); + + /** + * {@link Event} manages an association to its {@link Event#getRegattas() regattas}. When something on the + * regatta changes (in particular, the implicit link to an event through an event's {@link CourseArea} that + * is assigned as this regatta's {@link #setDefaultCourseArea(CourseArea) default course area}), the + * opposite end of the association needs to be maintained on the event's side. + */ + void adjustEventToRegattaAssociation(EventFetcher eventFetcher); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java index aafc1d26917..3dffba3a7f5 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java @@ -10,7 +10,7 @@ public interface DynamicCompetitorStore extends CompetitorStore { DynamicCompetitor getExistingCompetitorById(Serializable competitorId); @Override - DynamicCompetitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, DynamicTeam team, DynamicBoat boat); + DynamicCompetitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email, DynamicTeam team, DynamicBoat boat); @Override Iterable getCompetitors(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java index 8dd579aaac4..5170bb3b1b5 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java @@ -12,9 +12,12 @@ import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.EventFetcher; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumnInSeries; @@ -297,13 +300,26 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene } @Override - public Iterable getCompetitors() { + public Iterable getAllCompetitors() { Set result = new HashSet(); for (RaceDefinition race : getAllRaces()) { for (Competitor c : race.getCompetitors()) { result.add(c); } } + for (Series series : getSeries()) { + for (RaceColumn rc : series.getRaceColumns()) { + for (Fleet fleet : rc.getFleets()) { + TrackedRace trackedRace = rc.getTrackedRace(fleet); + if (trackedRace != null) { + Util.addAll(trackedRace.getRace().getCompetitors(), result); + } + } + } + } + //consider {@link RegattaLog} + Set viaLog = new RegisteredCompetitorsAnalyzer<>(regattaLikeHelper.getRegattaLog()).analyze(); + result.addAll(viaLog); return result; } @@ -551,4 +567,17 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene public void removeListener(RegattaLikeListener listener) { regattaLikeHelper.removeListener(listener); } + + public void adjustEventToRegattaAssociation(EventFetcher eventFetcher) { + CourseArea defaultCourseArea = getDefaultCourseArea(); + for (Event event : eventFetcher.getAllEvents()) { + event.removeRegatta(this); + for (CourseArea courseArea : event.getVenue().getCourseAreas()) { + if (defaultCourseArea != null && courseArea.getId().equals(defaultCourseArea)) { + event.addRegatta(this); + } + } + } + + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java index d2f0bcc4713..2f7db478424 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java @@ -88,7 +88,9 @@ public interface Leaderboard extends LeaderboardBase { * in a regular view of the leaderboard. Editors for leaderboards shall, though, also display the suppressed competitors * together with a visual indication showing which competitors are currently suppressed. The "suppressed-state" of a * competitor can change over the life cycle of a leaderboard. A typical use case for suppressing a competitor is - * removing one-time entries from a series (meta-)leaderboard or suppressing a camera boat in scoring. + * removing one-time entries from a series (meta-)leaderboard or suppressing a camera boat in scoring.

    + * + * @return all competitors in this leaderboard, including the suppressed ones. */ Iterable getAllCompetitors(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java index 481d63b3cc3..6dfe6c5521a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java @@ -116,6 +116,11 @@ public class LeaderboardCacheManager { competitor.removeCompetitorChangeListener(this); } } + + @Override + public void emailChanged(String oldEmail, String newEmail) { + //ignore (email not shown in leaderboard) + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java index f68c204399f..1a447be2b5f 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java @@ -70,6 +70,10 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI return Collections.unmodifiableSet(trackedRaces); } + /** + * This default implementation collects all competitors by visiting all {@link TrackedRace}s associated with this + * leaderboard's columns (see {@link #getTrackedRaces()}). + */ @Override public Iterable getAllCompetitors() { if (allCompetitorsCache == null) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java index aee04ead6da..989e468e8b9 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java @@ -6,10 +6,14 @@ import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; @@ -275,4 +279,16 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements public void removeListener(RegattaLikeListener listener) { regattaLikeHelper.removeListener(listener); } + + @Override + public Iterable getAllCompetitors() { + Set result = new HashSet<>(); + for (Competitor c : super.getAllCompetitors()) { + result.add(c); + } + //consider {@link RegattaLog} + Set viaLog = new RegisteredCompetitorsAnalyzer<>(regattaLikeHelper.getRegattaLog()).analyze(); + result.addAll(viaLog); + return result; + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java index 0301eb7e8a9..a6df854049f 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java @@ -3,11 +3,14 @@ package com.sap.sailing.domain.leaderboard.impl; import java.util.ArrayList; import java.util.List; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumnInSeries; import com.sap.sailing.domain.base.RaceColumnListener; +import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.impl.RaceColumnInSeriesImpl; @@ -96,6 +99,17 @@ public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl implements R } } + /** + * Delegates to {@link Regatta#getAllCompetitors()} which is expected to deliver all competitors from this + * leaderboard's regatta which includes those belonging to {@link RaceDefinition races} + * {@link Regatta#getAllRaces() belonging to the regatta} as well as competitors listed on the regatta's + * {@link RegattaLog}. + */ + @Override + public Iterable getAllCompetitors() { + return regatta.getAllCompetitors(); + } + @Override public IsRegattaLike getRegattaLike() { return regatta; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java index 41bfb97db8b..a598b10a738 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java @@ -72,6 +72,16 @@ public class DummyMarkPassingWithTimePointOnly implements MarkPassing { @Override public void removeCompetitorChangeListener(CompetitorChangeListener listener) { } + + @Override + public String getEmail() { + return null; + } + + @Override + public boolean hasEmail() { + return false; + } }; } } diff --git a/java/com.sap.sailing.feature/feature.xml b/java/com.sap.sailing.feature/feature.xml index b58a6a25057..00b023d577a 100755 --- a/java/com.sap.sailing.feature/feature.xml +++ b/java/com.sap.sailing.feature/feature.xml @@ -9,392 +9,392 @@ The SAP Sailing Server. Provides connectivity to a TracTrac live GPS feed as well as a live feed from an Expedition system. -Computes leaderboard information for sailing races and offers RESTful APIs to all of this. - - - - [Enter Copyright Description here.] - - - - [Enter License Description here.] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Computes leaderboard information for sailing races and offers RESTful APIs to all of this. + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java index bf1191a0747..15bf4fec23f 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java @@ -11,6 +11,7 @@ import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.CourseBase; +import com.sap.sailing.domain.base.EventFetcher; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceColumnListener; @@ -335,7 +336,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { } @Override - public Iterable getCompetitors() { + public Iterable getAllCompetitors() { // TODO Auto-generated method stub return null; } @@ -517,6 +518,12 @@ public class MockedTrackedRace implements DynamicTrackedRace { // TODO Auto-generated method stub } + + @Override + public void adjustEventToRegattaAssociation(EventFetcher eventFetcher) { + // TODO Auto-generated method stub + + } }; } diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java index e9311746a13..f0fc52e1ea1 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java @@ -163,8 +163,8 @@ public class PolarSheetGenerationServiceTest { waypoints.add(new WaypointImpl(null)); waypoints.add(new WaypointImpl(null)); ArrayList competitors = new ArrayList(); - Competitor competitor = new CompetitorImpl(UUID.randomUUID(), "Hans Frantz", Color.RED, new TeamImpl("SAP", null, null), - new BoatImpl("Schnelle Forelle", forelle, "GER000")); + Competitor competitor = new CompetitorImpl(UUID.randomUUID(), "Hans Frantz", Color.RED, null, + new TeamImpl("SAP", null, null), new BoatImpl("Schnelle Forelle", forelle, "GER000")); competitors.add(competitor); RaceDefinition race = new RaceDefinitionImpl("Forelle1", new CourseImpl("ForelleCourse", waypoints), forelle, competitors); return race; diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SailingServiceImplMock.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SailingServiceImplMock.java index 31bba094c52..7803176ca7c 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SailingServiceImplMock.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SailingServiceImplMock.java @@ -1,8 +1,5 @@ package com.sap.sailing.gwt.ui.test; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import java.io.IOException; import java.net.UnknownHostException; import java.text.ParseException; @@ -11,9 +8,6 @@ import java.util.List; import javax.xml.bind.JAXBException; -import org.osgi.framework.BundleContext; -import org.osgi.util.tracker.ServiceTracker; - import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.common.RegattaIdentifier; @@ -27,7 +21,6 @@ import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapter; import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapterFactory; import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory; import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayService; -import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayServiceFactory; import com.sap.sailing.domain.tracking.RaceHandle; import com.sap.sailing.domain.tracking.TrackerManager; import com.sap.sailing.domain.tractracadapter.TracTracAdapterFactory; @@ -43,72 +36,37 @@ import com.sap.sse.replication.impl.ReplicationServiceImpl; public class SailingServiceImplMock extends SailingServiceImpl { private static final long serialVersionUID = 8564037671550730455L; - private RacingEventService service; - + + private final RacingEventService service; + private ReplicationService replicationService; + private final ScoreCorrectionProvider scoreCorrectionProvider = null; + private final TracTracAdapterFactory tracTracAdapterFactory = TracTracAdapterFactory.INSTANCE; + private final SwissTimingAdapterFactory swissTimingAdapterFactory; + private final SwissTimingReplayService swissTimingReplayService = null; + private final RaceLogTrackingAdapterFactory raceLogTrackingAdapterFactory = RaceLogTrackingAdapterFactory.INSTANCE; + public SailingServiceImplMock() { super(); service = new RacingEventServiceImpl(true, new MockSmartphoneImeiServiceFinderFactory()); - } - - @Override - protected ServiceTracker createAndOpenRacingEventServiceTracker( - BundleContext context) { - @SuppressWarnings("unchecked") - ServiceTracker result = mock(ServiceTracker.class); - when(result.getService()).thenReturn(new RacingEventServiceImpl()); - return result; - } - - @Override - protected ServiceTracker createAndOpenReplicationServiceTracker( - BundleContext context) { - @SuppressWarnings("unchecked") - ServiceTracker result = mock(ServiceTracker.class); try { - final RacingEventService replicable = new RacingEventServiceImpl(); - final ReplicationServiceImpl replicationService = - new ReplicationServiceImpl("test exchange", "localhost", 0, - new ReplicationInstancesManager(), new AbstractReplicablesProvider() { - @Override - public Iterable> getReplicables() { - return Collections.>singleton(replicable); - } - }); - when(result.getService()).thenReturn(replicationService); + replicationService = new ReplicationServiceImpl("test exchange", "localhost", 0, + new ReplicationInstancesManager(), new AbstractReplicablesProvider() { + @Override + public Iterable> getReplicables() { + return Collections.> singleton(service); + } + }); } catch (IOException e) { - throw new RuntimeException(); + e.printStackTrace(); } - return result; - } - - @Override - protected ServiceTracker createAndOpenScoreCorrectionProviderServiceTracker( - BundleContext bundleContext) { - return null; - } - - @Override - protected ServiceTracker createAndOpenTracTracAdapterTracker( - BundleContext context) { - @SuppressWarnings("unchecked") - ServiceTracker result = mock(ServiceTracker.class); - when(result.getService()).thenReturn(TracTracAdapterFactory.INSTANCE); - return result; - } - - @Override - protected ServiceTracker createAndOpenSwissTimingAdapterTracker( - BundleContext context) { - @SuppressWarnings("unchecked") - ServiceTracker result = mock(ServiceTracker.class); - when(result.getService()).thenReturn(new SwissTimingAdapterFactory() { + swissTimingAdapterFactory = new SwissTimingAdapterFactory() { @Override public SwissTimingAdapter getOrCreateSwissTimingAdapter(DomainFactory baseDomainFactory) { return new SwissTimingAdapter() { @Override public List getSwissTimingRaceRecords( - String hostname, int port) throws InterruptedException, - UnknownHostException, IOException, ParseException { + String hostname, int port) throws InterruptedException, UnknownHostException, IOException, + ParseException { // TODO Auto-generated method stub return null; } @@ -148,45 +106,43 @@ public class SailingServiceImplMock extends SailingServiceImpl { } }; } - }); - return result; + }; + } + + public ScoreCorrectionProvider getScoreCorrectionProvider() { + return scoreCorrectionProvider; } @Override - protected ServiceTracker createAndOpenSwissTimingReplayServiceTracker( - BundleContext context) { - @SuppressWarnings("unchecked") - ServiceTracker result = mock(ServiceTracker.class); - final SwissTimingReplayServiceFactory swissTimingReplayService = new SwissTimingReplayServiceFactory() { - @Override - public SwissTimingReplayService createSwissTimingReplayService( - com.sap.sailing.domain.swisstimingadapter.DomainFactory domainFactory) { - // TODO Auto-generated method stub - return null; - } - }; - when(result.getService()).thenReturn(swissTimingReplayService); - return result; + protected TracTracAdapterFactory getTracTracAdapterFactory() { + return tracTracAdapterFactory; + } + + @Override + protected SwissTimingAdapterFactory getSwissTimingAdapterFactory() { + return swissTimingAdapterFactory; + } + + @Override + protected SwissTimingReplayService getSwissTimingReplayService() { + return swissTimingReplayService; + } + + @Override + protected RaceLogTrackingAdapterFactory getRaceLogTrackingAdapterFactory() { + return raceLogTrackingAdapterFactory; } @Override - protected ServiceTracker createAndOpenRaceLogTrackingAdapterTracker( - BundleContext context) { - @SuppressWarnings("unchecked") - ServiceTracker result = mock(ServiceTracker.class); - RaceLogTrackingAdapterFactory factory = RaceLogTrackingAdapterFactory.INSTANCE; - when(result.getService()).thenReturn(factory); - return result; + protected ReplicationService getReplicationService() { + return replicationService; } @Override protected RacingEventService getService() { - if (service == null) { - service = new RacingEventServiceImpl(); - } return service; } - + public RacingEventService getRacingEventService() { return getService(); } diff --git a/java/com.sap.sailing.gwt.ui/.settings/com.google.gwt.eclipse.core.prefs b/java/com.sap.sailing.gwt.ui/.settings/com.google.gwt.eclipse.core.prefs index ba74941703a..a44f1dda0ca 100755 --- a/java/com.sap.sailing.gwt.ui/.settings/com.google.gwt.eclipse.core.prefs +++ b/java/com.sap.sailing.gwt.ui/.settings/com.google.gwt.eclipse.core.prefs @@ -1,4 +1,4 @@ eclipse.preferences.version=1 entryPointModules= filesCopiedToWebInfLib=gwt-servlet.jar -gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBWy13YXIgLiAtbG9jYWxXb3JrZXJzIDQgLXN0cmljdCAtbG9nTGV2ZWwgVFJBQ0VdXT48L2V4dHJhLWFyZ3M+PHZtLWFyZ3M+PCFbQ0RBVEFbLVhteDIwMjRtIC1EZ3d0LnVzZWFyY2hpdmVzPWZhbHNlXV0+PC92bS1hcmdzPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLnNhcC5zYWlsaW5nLmd3dC5Ib21lPC9lbnRyeS1wb2ludC1tb2R1bGU+PC9nd3QtY29tcGlsZS1zZXR0aW5ncz4\= +gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBWy13YXIgLiAtbG9jYWxXb3JrZXJzIDQgLXN0cmljdCAtbG9nTGV2ZWwgVFJBQ0VdXT48L2V4dHJhLWFyZ3M+PHZtLWFyZ3M+PCFbQ0RBVEFbLVhteDIwMjRtIC1EZ3d0LnVzZWFyY2hpdmVzPWZhbHNlXV0+PC92bS1hcmdzPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLnNhcC5zYWlsaW5nLmd3dC5BdXRvUGxheTwvZW50cnktcG9pbnQtbW9kdWxlPjwvZ3d0LWNvbXBpbGUtc2V0dGluZ3M+ diff --git a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index 8aee6550dd3..0f82a9aec59 --- a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF @@ -10,7 +10,7 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.server, com.sap.sailing.domain.tractracadapter, com.sap.sse.mongodb, - com.mongodb.driver;bundle-version="2.6.2", + org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sailing.domain.swisstimingadapter, com.sap.sailing.domain.persistence, com.sap.sailing.domain.swisstimingadapter.persistence, diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch index b0332ffab3a..81118d7d4af 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch @@ -69,7 +69,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java index c201c80ce34..e11db038d23 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java @@ -6,6 +6,7 @@ import com.google.gwt.i18n.client.Messages; public interface TextMessages extends Messages { public static final TextMessages INSTANCE = GWT.create(TextMessages.class); + String chartSelectionHint(); String chooseALanguage(); String home(); String events(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties index 6a50d7fa2ce..8ad020fd7fd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties @@ -1,3 +1,4 @@ +chartSelectionHint=Hint: You can also use the leaderboard (on the LEADERBOARD tab) to select the competitors displayed in the chart. chooseALanguage=Choose a language events=Events home=Home diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties index 3afbaca10ad..55b7a72c686 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties @@ -1,3 +1,4 @@ +chartSelectionHint=Hinweis: Sie können auch Ergebnisstabelle (im Menü ERGEBNISSE) nutzen, um die im Diagramm angezeigten Teilnehmer auszuwählen. chooseALanguage=Wähle eine Sprache events=Veranstaltungen home=Startseite diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml index 4a134f1f2d9..7e3fb498de0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml @@ -9,7 +9,7 @@

    -
    +
    diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.java index 0ff0c7ee412..bb66418a237 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.List; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.Style.Visibility; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; @@ -14,9 +16,11 @@ import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.gwt.home.client.place.event.regattaleaderboard.EventRegattaLeaderboardResources; +import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider; import com.sap.sailing.gwt.ui.client.DetailTypeFormatter; import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorLeaderboardChart; import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorLeaderboardChartSettings; +import com.sap.sse.common.Util; public class OldCompetitorCharts extends Composite { private static OldCompetitorChartsUiBinder uiBinder = GWT.create(OldCompetitorChartsUiBinder.class); @@ -26,6 +30,7 @@ public class OldCompetitorCharts extends Composite { @UiField HTMLPanel oldCompetitorChartsPanel; @UiField ListBox chartTypeSelectionListBox; + @UiField DivElement competitorSelectionStateUi; private final List availableDetailsTypes; private MultiCompetitorLeaderboardChart multiCompetitorChart; @@ -79,4 +84,15 @@ public class OldCompetitorCharts extends Composite { } return result; } + + public void updateSelectionState(CompetitorSelectionProvider competitorSelectionProvider) { + int selectedCompetitorsCount = Util.size(competitorSelectionProvider.getSelectedCompetitors()); + if(selectedCompetitorsCount > 0) { + int competitorsCount = Util.size(competitorSelectionProvider.getAllCompetitors()); + competitorSelectionStateUi.getStyle().setVisibility(Visibility.VISIBLE); + competitorSelectionStateUi.setInnerText(selectedCompetitorsCount + "/" + competitorsCount + " competitors selected."); + } else { + competitorSelectionStateUi.getStyle().setVisibility(Visibility.HIDDEN); + } + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.ui.xml index 997e1bc24b5..68d7122a180 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldcompetitorcharts/OldCompetitorCharts.ui.xml @@ -7,7 +7,7 @@ -
    +

    @@ -15,6 +15,11 @@
    +
    + +
    +
    +
    diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldleaderboard/OldLeaderboard.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldleaderboard/OldLeaderboard.ui.xml index 8f65326ebe2..56f6dc4dbf8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldleaderboard/OldLeaderboard.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldleaderboard/OldLeaderboard.ui.xml @@ -7,7 +7,7 @@ -
    +

    diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldmultileaderboard/OldMultiLeaderboard.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldmultileaderboard/OldMultiLeaderboard.ui.xml index 5b78dfeda4e..6bf4b5d7afd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldmultileaderboard/OldMultiLeaderboard.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/oldmultileaderboard/OldMultiLeaderboard.ui.xml @@ -7,7 +7,7 @@ -
    +

    diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalytics.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalytics.java index f80497147bf..169f4dd0a5b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalytics.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalytics.java @@ -181,6 +181,7 @@ public class RegattaAnalytics extends Composite implements LeaderboardUpdateList setActiveTabPanel(competitorChartsTabPanel, competitorChartsAnchor); DetailType selectedChartDetailType = oldCompetitorChartsComposite.getSelectedChartDetailType(); regattaAnalyticsManager.showCompetitorChart(selectedChartDetailType); + oldCompetitorChartsComposite.updateSelectionState(regattaAnalyticsManager.getCompetitorSelectionProvider()); handleClickEvent(event, competitorChartsNavigation); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalyticsDataManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalyticsDataManager.java index 5e7ec9ea299..9b0590d8434 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalyticsDataManager.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaanalytics/RegattaAnalyticsDataManager.java @@ -1,7 +1,13 @@ package com.sap.sailing.gwt.home.client.place.event.regattaanalytics; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener; import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; import com.sap.sailing.gwt.ui.client.DebugIdHelper; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; @@ -12,6 +18,7 @@ import com.sap.sailing.gwt.ui.client.shared.components.Component; import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialog; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings; +import com.sap.sse.common.Util; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.player.Timer; @@ -32,7 +39,8 @@ public class RegattaAnalyticsDataManager { private final UserAgentDetails userAgent; private final SailingServiceAsync sailingService; private final Timer timer; - + private final int MAX_COMPETITORS_IN_CHART = 30; + public RegattaAnalyticsDataManager(final SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, Timer timer, ErrorReporter errorReporter, UserAgentDetails userAgent) { this.competitorSelectionProvider = new CompetitorSelectionModel(/* hasMultiSelection */true); this.sailingService = sailingService; @@ -73,12 +81,32 @@ public class RegattaAnalyticsDataManager { return multiCompetitorChart; } + public CompetitorSelectionModel getCompetitorSelectionProvider() { + return competitorSelectionProvider; + } + public void showCompetitorChart(DetailType chartDetailType) { + // preselect the top N competitors in case there was no selection before and there too many competitors for a chart + int competitorsCount = Util.size(competitorSelectionProvider.getAllCompetitors()); + int selectedCompetitorsCount = Util.size(competitorSelectionProvider.getSelectedCompetitors()); + + if(selectedCompetitorsCount == 0 && competitorsCount > MAX_COMPETITORS_IN_CHART) { + List selectedCompetitors = new ArrayList(); + Iterator allCompetitorsIt = competitorSelectionProvider.getAllCompetitors().iterator(); + int counter = 0; + while(counter < MAX_COMPETITORS_IN_CHART) { + selectedCompetitors.add(allCompetitorsIt.next()); + counter++; + } + competitorSelectionProvider.setSelection(selectedCompetitors, (CompetitorSelectionChangeListener[]) null); + } + MultiCompetitorLeaderboardChart multiCompetitorChart = getMultiCompetitorChart(); MultiCompetitorLeaderboardChartSettings settings = new MultiCompetitorLeaderboardChartSettings(chartDetailType); multiCompetitorChart.updateSettings(settings); multiCompetitorChart.setVisible(true); timer.addTimeListener(multiCompetitorChart); + multiCompetitorChart.clearChart(); multiCompetitorChart.timeChanged(timer.getTime(), null); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css index dec9fb3e38a..427b670805c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css @@ -38,6 +38,8 @@ text-align: center; } .regattaleaderboard { + margin-left: 5rem; + margin-right: 5rem; font-size: 15px; font-size: 1rem; width: 100%; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalytics.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalytics.java index 3d48af5335a..be1c4184f59 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalytics.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalytics.java @@ -212,6 +212,7 @@ public class EventSeriesAnalytics extends Composite implements LeaderboardUpdate setActiveTabPanel(competitorChartsTabPanel, eventSeriesAnalyticsManager.getMultiCompetitorChart(), competitorChartsAnchor); DetailType selectedChartDetailType = oldCompetitorChartsComposite.getSelectedChartDetailType(); eventSeriesAnalyticsManager.showCompetitorChart(selectedChartDetailType); + oldCompetitorChartsComposite.updateSelectionState(eventSeriesAnalyticsManager.getCompetitorSelectionProvider()); handleClickEvent(event, competitorChartsNavigation); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalyticsDataManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalyticsDataManager.java index 52669221b5b..35f0d588f16 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalyticsDataManager.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/seriesanalytics/EventSeriesAnalyticsDataManager.java @@ -1,7 +1,13 @@ package com.sap.sailing.gwt.home.client.place.event.seriesanalytics; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener; import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; import com.sap.sailing.gwt.ui.client.DebugIdHelper; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; @@ -13,6 +19,7 @@ import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialog; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings; import com.sap.sailing.gwt.ui.leaderboard.MultiLeaderboardPanel; +import com.sap.sse.common.Util; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.player.Timer; @@ -36,6 +43,7 @@ public class EventSeriesAnalyticsDataManager { private final UserAgentDetails userAgent; private final SailingServiceAsync sailingService; private final Timer timer; + private final int MAX_COMPETITORS_IN_CHART = 30; public EventSeriesAnalyticsDataManager(final SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, Timer timer, ErrorReporter errorReporter, UserAgentDetails userAgent) { this.competitorSelectionProvider = new CompetitorSelectionModel(/* hasMultiSelection */true); @@ -93,14 +101,34 @@ public class EventSeriesAnalyticsDataManager { } public void showCompetitorChart(DetailType chartDetailType) { + // preselect the top N competitors in case there was no selection before and there too many competitors for a chart + int competitorsCount = Util.size(competitorSelectionProvider.getAllCompetitors()); + int selectedCompetitorsCount = Util.size(competitorSelectionProvider.getSelectedCompetitors()); + + if(selectedCompetitorsCount == 0 && competitorsCount > MAX_COMPETITORS_IN_CHART) { + List selectedCompetitors = new ArrayList(); + Iterator allCompetitorsIt = competitorSelectionProvider.getAllCompetitors().iterator(); + int counter = 0; + while(counter < MAX_COMPETITORS_IN_CHART) { + selectedCompetitors.add(allCompetitorsIt.next()); + counter++; + } + competitorSelectionProvider.setSelection(selectedCompetitors, (CompetitorSelectionChangeListener[]) null); + } + MultiCompetitorLeaderboardChart multiCompetitorChart = getMultiCompetitorChart(); MultiCompetitorLeaderboardChartSettings settings = new MultiCompetitorLeaderboardChartSettings(chartDetailType); multiCompetitorChart.updateSettings(settings); multiCompetitorChart.setVisible(true); timer.addTimeListener(multiCompetitorChart); + multiCompetitorChart.clearChart(); multiCompetitorChart.timeChanged(timer.getTime(), null); } + public CompetitorSelectionModel getCompetitorSelectionProvider() { + return competitorSelectionProvider; + } + public void hideCompetitorChart() { MultiCompetitorLeaderboardChart multiCompetitorChart = getMultiCompetitorChart(); multiCompetitorChart.setVisible(false); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AddDeviceMappingToRaceLogDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AddDeviceMappingToRaceLogDialog.java index 2d14bf984cd..74aa4170a45 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AddDeviceMappingToRaceLogDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AddDeviceMappingToRaceLogDialog.java @@ -18,11 +18,11 @@ import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.racelog.RaceLogServletConstants; import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; -import com.sap.sailing.gwt.ui.adminconsole.DeviceMappingQRCodeWidget.QRCodeURLCreationException; +import com.sap.sailing.domain.common.racelog.tracking.QRCodeURLCreationException; import com.sap.sailing.gwt.ui.adminconsole.ItemToMapToDeviceSelectionPanel.SelectionChangedHandler; +import com.sap.sailing.gwt.ui.client.GwtUrlHelper; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.BetterDateTimeBox; @@ -103,7 +103,7 @@ public class AddDeviceMappingToRaceLogDialog extends DataEntryDialog toMillis) { - throw new QRCodeURLCreationException("from cannt lie after to"); + throw new QRCodeURLCreationException("from can't lie after to"); } - return baseUrlWithoutTrailingSlash + DeviceMappingConstants.APK_PATH + "?" - + RaceLogServletConstants.PARAMS_LEADERBOARD_NAME + "=" + DeviceMappingQRCodeWidget.encode(leaderboardName) + "&" - + RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME + "=" + DeviceMappingQRCodeWidget.encode(raceColumnName) - + "&" + RaceLogServletConstants.PARAMS_RACE_FLEET_NAME + "=" + DeviceMappingQRCodeWidget.encode(fleetName) - + "&" + mappedItemQueryParam + "&" + DeviceMappingConstants.URL_FROM_MILLIS + "=" + fromMillis - + "&" + DeviceMappingConstants.URL_TO_MILLIS + "=" + toMillis; + return DeviceMappingConstants.getDeviceMappingForRaceLogUrl(baseUrlWithoutTrailingSlash, + leaderboardName, raceColumnName, fleetName, mappedItemType, mappedItemId, fromMillis, toMillis, + GwtUrlHelper.INSTANCE); } }); qrWidget.generateQRCode(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AddDeviceMappingToRegattaLogDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AddDeviceMappingToRegattaLogDialog.java index 44fcd58eaf1..27602739cd7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AddDeviceMappingToRegattaLogDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AddDeviceMappingToRegattaLogDialog.java @@ -13,15 +13,16 @@ import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; -import com.sap.sailing.gwt.ui.adminconsole.DeviceMappingQRCodeWidget.QRCodeURLCreationException; +import com.sap.sailing.domain.common.racelog.tracking.QRCodeURLCreationException; import com.sap.sailing.gwt.ui.adminconsole.ItemToMapToDeviceSelectionPanel.SelectionChangedHandler; +import com.sap.sailing.gwt.ui.client.GwtUrlHelper; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.common.client.GenericListBox; -import com.sap.sailing.gwt.ui.common.client.GenericListBox.ValueBuilder; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.MarkDTO; import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.controls.GenericListBox; +import com.sap.sse.gwt.client.controls.GenericListBox.ValueBuilder; public class AddDeviceMappingToRegattaLogDialog extends AbstractCancelableDialog { private DeviceMappingQRCodeWidget qrWidget; @@ -35,11 +36,11 @@ public class AddDeviceMappingToRegattaLogDialog extends AbstractCancelableDialog setupUi(); center(); } - + @Override protected void addMainContent(Panel mainPanel) { super.addMainContent(mainPanel); - + CaptionPanel inputPanel = new CaptionPanel(); Grid inputGrid = new Grid(1, 2); inputPanel.add(inputGrid); @@ -62,13 +63,13 @@ public class AddDeviceMappingToRegattaLogDialog extends AbstractCancelableDialog public void onSuccess(Collection result) { events.addItems(result); } - + @Override public void onFailure(Throwable caught) { errorReporter.reportError("Could not load events: " + caught.getMessage()); } }); - + itemSelectionPanel = new ItemToMapToDeviceSelectionPanel(sailingService, stringMessages, errorReporter, new SelectionChangedHandler() { @Override @@ -85,33 +86,31 @@ public class AddDeviceMappingToRegattaLogDialog extends AbstractCancelableDialog } }, null); - //load table content + // load table content sailingService.getCompetitorRegistrations(leaderboardName, itemSelectionPanel.getSetCompetitorsCallback()); - //TODO marks from RegattaLog also? + // TODO marks from RegattaLog also? qrWidget = new DeviceMappingQRCodeWidget(stringMessages, new DeviceMappingQRCodeWidget.URLFactory() { @Override - public String createURL(String baseUrlWithoutTrailingSlash, String mappedItemQueryParam) + public String createURL(String baseUrlWithoutTrailingSlash, String mappedItemType, String mappedItemId) throws QRCodeURLCreationException { if (events.getValue() == null) { throw new QRCodeURLCreationException("no event selected"); } String eventIdAsString = events.getValue().id.toString(); - return baseUrlWithoutTrailingSlash + DeviceMappingConstants.URL_BASE - + "?" + DeviceMappingConstants.URL_EVENT_ID + "=" + DeviceMappingQRCodeWidget.encode(eventIdAsString) - + "&" + DeviceMappingConstants.URL_LEADERBOARD_NAME + "=" + DeviceMappingQRCodeWidget.encode(leaderboardName) - + "&" + mappedItemQueryParam; + return DeviceMappingConstants.getDeviceMappingForRegattaLogUrl(baseUrlWithoutTrailingSlash, eventIdAsString, + leaderboardName, mappedItemType, mappedItemId, GwtUrlHelper.INSTANCE); } }); qrWidget.generateQRCode(); - + VerticalPanel leftSidePanel = new VerticalPanel(); leftSidePanel.add(inputPanel); CaptionPanel qrContentPanel = new CaptionPanel(); leftSidePanel.add(qrContentPanel); qrContentPanel.add(qrWidget); - + HorizontalPanel panel = new HorizontalPanel(); mainPanel.add(panel); panel.add(leftSidePanel); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleResources.java index 8d9424d2202..7dc5b7fbbc7 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleResources.java @@ -11,9 +11,6 @@ interface AdminConsoleResources extends ClientBundle { @Source("com/sap/sailing/gwt/ui/client/images/settingsActionIcon.png") ImageResource settingsActionIcon(); - @Source("com/sap/sse/gwt/client/images/remove.png") - ImageResource removeIcon(); - @Source("com/sap/sailing/gwt/ui/client/images/edit.png") ImageResource editIcon(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BaseQRIdentifierWidget.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BaseQRIdentifierWidget.java index 143472a1efe..8f73b604e63 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BaseQRIdentifierWidget.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BaseQRIdentifierWidget.java @@ -4,7 +4,6 @@ import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.google.gwt.http.client.URL; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HasHorizontalAlignment; @@ -13,7 +12,7 @@ import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; -import com.sap.sailing.gwt.ui.adminconsole.DeviceMappingQRCodeWidget.QRCodeURLCreationException; +import com.sap.sailing.domain.common.racelog.tracking.QRCodeURLCreationException; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.QRCodeComposite; @@ -91,9 +90,4 @@ public abstract class BaseQRIdentifierWidget implements IsWidget { protected void setError(String text) { error.setText(text); } - - public static String encode(String value) { - //pathSegment instead of queryString, so that ' ' is encoded as '%20' - return URL.encodePathSegment(value); - } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java index f6742beb834..91c37b7bb20 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java @@ -38,6 +38,7 @@ public class CompetitorEditDialog extends DataEntryDialog { private final TextBox displayColorTextBox; private final ListBox threeLetterIocCountryCode; private final TextBox sailId; + private final TextBox email; private final StringMessages stringMessages; public CompetitorEditDialog(final StringMessages stringMessages, CompetitorDTO competitorToEdit, @@ -89,6 +90,8 @@ public class CompetitorEditDialog extends DataEntryDialog { } this.name = createTextBox(competitorToEdit.getName()); + this.email = createTextBox(competitorToEdit.getEmail()); + this.email.getElement().setPropertyString("placeholder", stringMessages.pleaseEnterAnEmail()); this.displayColorTextBox = createTextBox(competitorToEdit.getColor() == null ? "" : competitorToEdit.getColor().getAsHtml()); this.threeLetterIocCountryCode = createListBox(/* isMultipleSelect */ false); CountryCodeFactory ccf = CountryCodeFactory.INSTANCE; @@ -170,7 +173,7 @@ public class CompetitorEditDialog extends DataEntryDialog { } } BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(boatClassName.getSelectedIndex()), 0); - CompetitorDTO result = new CompetitorDTOImpl(name.getText(), color, + CompetitorDTO result = new CompetitorDTOImpl(name.getText(), color, email.getText(), /* twoLetterIsoCountryCode */ null, threeLetterIocCountryCode.getValue(threeLetterIocCountryCode.getSelectedIndex()), /* countryName */ null, sailId.getText(), competitorToEdit.getIdAsString(), @@ -180,7 +183,7 @@ public class CompetitorEditDialog extends DataEntryDialog { @Override protected Widget getAdditionalWidget() { - Grid result = new Grid(5, 2); + Grid result = new Grid(6, 2); result.setWidget(0, 0, new Label(stringMessages.name())); result.setWidget(0, 1, name); result.setWidget(1, 0, new Label(stringMessages.sailNumber())); @@ -189,8 +192,10 @@ public class CompetitorEditDialog extends DataEntryDialog { result.setWidget(2, 1, threeLetterIocCountryCode); result.setWidget(3, 0, new Label(stringMessages.color())); result.setWidget(3, 1, displayColorTextBox); - result.setWidget(4, 0, new Label(stringMessages.boatClass())); - result.setWidget(4, 1, boatClassName); + result.setWidget(4, 0, new Label(stringMessages.email())); + result.setWidget(4, 1, email); + result.setWidget(5, 0, new Label(stringMessages.boatClass())); + result.setWidget(5, 1, boatClassName); return result; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java index 4b0dc656446..54f8369f8ad 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java @@ -1,18 +1,24 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Set; import com.google.gwt.cell.client.FieldUpdater; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.i18n.client.LocaleInfo; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.MultiSelectionModel; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; @@ -20,8 +26,13 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.controls.GenericListBox; +import com.sap.sse.gwt.client.controls.GenericListBox.ValueBuilder; +import com.sap.sse.gwt.client.dialog.DataEntryDialog; import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; /** @@ -43,8 +54,8 @@ public class CompetitorPanel extends SimplePanel { this(sailingService, null, stringMessages, errorReporter); } - public CompetitorPanel(final SailingServiceAsync sailingService, String leaderboardName, final StringMessages stringMessages, - final ErrorReporter errorReporter) { + public CompetitorPanel(final SailingServiceAsync sailingService, final String leaderboardName, + final StringMessages stringMessages, final ErrorReporter errorReporter) { super(); this.sailingService = sailingService; this.stringMessages = stringMessages; @@ -79,16 +90,56 @@ public class CompetitorPanel extends SimplePanel { buttonPanel.add(allowReloadButton); Button addCompetitorButton = new Button(stringMessages.add()); addCompetitorButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - openAddCompetitorDialog(); - } - }); + @Override + public void onClick(ClickEvent event) { + openAddCompetitorDialog(); + } + }); buttonPanel.add(addCompetitorButton); + + Button selectAllButton = new Button(stringMessages.selectAll()); + selectAllButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + for (CompetitorDTO c : competitorTable.getDataProvider().getList()) { + competitorSelectionModel.setSelected(c, true); + } + } + }); + buttonPanel.add(selectAllButton); + + //only if this competitor panel is connected to a leaderboard, we want to enable invitations + if (leaderboardName != null) { + final Button inviteCompetitorsButton = new Button(stringMessages.inviteCompetitors()); + inviteCompetitorsButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + Set competitors = competitorSelectionModel.getSelectedSet(); + boolean emailProvidedForAll = isEmailProvidedForAll(competitors); + + if (emailProvidedForAll) { + openChooseEventDialogAndSendMails(competitors); + } else { + Window.alert(stringMessages.notAllCompetitorsProvideEmail()); + } + } + + private boolean isEmailProvidedForAll(Iterable allCompetitors) { + for (CompetitorDTO competitor : allCompetitors) { + if (!competitor.hasEmail()) { + return false; + } + } + + return true; + } + }); + buttonPanel.add(inviteCompetitorsButton); + } + competitorsPanel.add(buttonPanel); - - //competitor table + // competitor table ImagesBarColumn competitorActionColumn = new ImagesBarColumn( new CompetitorConfigImagesBarCell(stringMessages)); competitorActionColumn.setFieldUpdater(new FieldUpdater() { @@ -112,21 +163,24 @@ public class CompetitorPanel extends SimplePanel { } }); allowReloadButton.setEnabled(!competitorSelectionModel.getSelectedSet().isEmpty()); - - if(leaderboardName != null) { + + if (leaderboardName != null) { refreshCompetitorList(); } } - + private void allowUpdate(final Iterable competitors) { List serializableSingletonList = new ArrayList(); Util.addAll(competitors, serializableSingletonList); sailingService.allowCompetitorResetToDefaults(serializableSingletonList, new AsyncCallback() { - @Override public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to allow resetting competitors "+competitors - +" to defaults: "+caught.getMessage()); + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to allow resetting competitors " + competitors + + " to defaults: " + caught.getMessage()); } - @Override public void onSuccess(Void result) { + + @Override + public void onSuccess(Void result) { Window.alert(stringMessages.successfullyAllowedCompetitorReset(competitors.toString())); } }); @@ -143,7 +197,7 @@ public class CompetitorPanel extends SimplePanel { sailingService.addOrUpdateCompetitor(competitor, new AsyncCallback() { @Override public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to update competitor: "+caught.getMessage()); + errorReporter.reportError("Error trying to update competitor: " + caught.getMessage()); } @Override @@ -159,6 +213,101 @@ public class CompetitorPanel extends SimplePanel { }).show(); } + private class SelectEventAndHostnameDialog extends DataEntryDialog> { + private GenericListBox events; + private TextBox serverUrl; + + public SelectEventAndHostnameDialog(DialogCallback> callback) { + super(stringMessages.selectEventForInvitation(), null, stringMessages.inviteCompetitors(), stringMessages.cancel(), + new Validator>() { + @Override + public String getErrorMessage(Pair valueToValidate) { + if (valueToValidate.getA() == null) { + return stringMessages.pleaseSelectAnEvent(); + } else if (valueToValidate.getB() == null || valueToValidate.getB().isEmpty()) { + return stringMessages.pleaseEnterA(stringMessages.hostname()); + } + return null; + } + }, false, callback); + } + + @Override + protected Pair getResult() { + EventDTO event = events.getValue(); + String serverUrlString = serverUrl.getValue(); + if (serverUrlString.endsWith("/")) { + serverUrlString = serverUrlString.substring(0, serverUrlString.length() - 1); + } + return new Pair<>(event, serverUrlString); + } + + @Override + protected Widget getAdditionalWidget() { + Grid grid = new Grid(2, 2); + grid.setWidget(0, 0, createLabel(stringMessages.hostname())); + serverUrl = createTextBox(Window.Location.getProtocol() + "//" + Window.Location.getHost()); + grid.setWidget(0, 1, serverUrl); + + grid.setWidget(1, 0, createLabel(stringMessages.event())); + events = createGenericListBox(new ValueBuilder() { + @Override + public String getValue(EventDTO item) { + if (item == null) { + return ""; + } + return item.getName(); + } + }, false); + grid.setWidget(1, 1, events); + + events.addItem((EventDTO) null); + sailingService.getEventsForLeaderboard(leaderboardName, new AsyncCallback>() { + @Override + public void onSuccess(Collection result) { + events.addItems(result); + } + + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Could not load events: " + caught.getMessage()); + } + }); + return grid; + } + } + + private String getLocaleInfo() { + return LocaleInfo.getCurrentLocale().getLocaleName(); + } + + private void openChooseEventDialogAndSendMails(final Set competitors) { + new SelectEventAndHostnameDialog(new DialogCallback>() { + + @Override + public void ok(Pair result) { + sailingService.inviteCompetitorsForTrackingViaEmail(result.getB(), result.getA(), leaderboardName, + competitors, getLocaleInfo(), new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + Window.alert(stringMessages.sendingMailsFailed() + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + Window.alert(stringMessages.sendingMailsSuccessfull()); + } + }); + } + + @Override + public void cancel() { + + } + }).show(); + } + public void refreshCompetitorList() { competitorTable.refreshCompetitorList(leaderboardName); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidgetWaypointsImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidgetWaypointsImagesBarCell.java index 6f7e9c87be9..97463fc4117 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidgetWaypointsImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidgetWaypointsImagesBarCell.java @@ -2,13 +2,12 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.ArrayList; -import com.google.gwt.core.client.GWT; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class CourseManagementWidgetWaypointsImagesBarCell extends ImagesBarCell { public static final String ACTION_DELETE = "ACTION_DELETE"; - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); private final StringMessages stringMessages; public CourseManagementWidgetWaypointsImagesBarCell(StringMessages stringMessages) { @@ -19,7 +18,7 @@ public class CourseManagementWidgetWaypointsImagesBarCell extends ImagesBarCell @Override protected Iterable getImageSpecs() { ArrayList result = new ArrayList(); - result.add(new ImageSpec(ACTION_DELETE, stringMessages.remove(), makeImagePrototype(resources.removeIcon()))); + result.add(new ImageSpec(ACTION_DELETE, stringMessages.remove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); return result; } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DefaultRegattaCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DefaultRegattaCreateDialog.java index 0c061b9c8eb..0b42afc7fb7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DefaultRegattaCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DefaultRegattaCreateDialog.java @@ -2,7 +2,6 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.List; -import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.ui.TabPanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; @@ -12,12 +11,11 @@ import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.SeriesDTO; import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.controls.listedit.ListEditorComposite; public class DefaultRegattaCreateDialog extends AbstractRegattaWithSeriesAndFleetsDialog { - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); - public DefaultRegattaCreateDialog(List existingEvents, RegattaDTO selectedRegatta, SailingServiceAsync sailingService, ErrorReporter errorReporter, StringMessages stringMessages, com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback callback) { @@ -34,7 +32,7 @@ public class DefaultRegattaCreateDialog extends AbstractRegattaWithSeriesAndFlee } protected ListEditorComposite createSeriesEditor(Iterable series) { - return new SeriesWithFleetsDefaultListEditor(series, stringMessages, resources.removeIcon(), /* enableFleetRemoval */ false); + return new SeriesWithFleetsDefaultListEditor(series, stringMessages, IconResources.INSTANCE.removeIcon(), /* enableFleetRemoval */ false); } protected void setupAdditionalWidgetsOnPanel(final VerticalPanel panel) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationCreateMatcherDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationCreateMatcherDialog.java index 5614548ea1c..3ba15679621 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationCreateMatcherDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationCreateMatcherDialog.java @@ -5,7 +5,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; @@ -20,6 +19,7 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceConfigurationMatcherDTO; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.dialog.DataEntryDialog; public class DeviceConfigurationCreateMatcherDialog extends DataEntryDialog { @@ -63,7 +63,6 @@ public class DeviceConfigurationCreateMatcherDialog extends DataEntryDialog devicesBoxes; @@ -164,7 +163,7 @@ public class DeviceConfigurationCreateMatcherDialog extends DataEntryDialog initialValues = originalConfiguration.allowedCourseAreaNames == null ? Collections . emptyList() : originalConfiguration.allowedCourseAreaNames; - allowedCourseAreasList = new StringListEditorComposite(initialValues, stringMessages, stringMessages.courseAreas(), resources.removeIcon(), + allowedCourseAreasList = new StringListEditorComposite(initialValues, stringMessages, stringMessages.courseAreas(), IconResources.INSTANCE.removeIcon(), SuggestedCourseAreaNames.suggestedCourseAreaNames, stringMessages.enterCourseAreaName()); allowedCourseAreasList.setWidth("80%"); allowedCourseAreasList.addValueChangeHandler(dirtyValueMarker); @@ -219,7 +220,7 @@ public class DeviceConfigurationDetailComposite extends Composite { List initialValues = originalConfiguration.byNameDesignerCourseNames == null ? Collections . emptyList() : originalConfiguration.byNameDesignerCourseNames; - courseNamesList = new StringListEditorComposite(initialValues, stringMessages, stringMessages.courseNames(), resources.removeIcon(), suggestedCourseNames, + courseNamesList = new StringListEditorComposite(initialValues, stringMessages, stringMessages.courseNames(), IconResources.INSTANCE.removeIcon(), suggestedCourseNames, stringMessages.enterCourseName()); courseNamesList.setWidth("80%"); courseNamesList.addValueChangeHandler(dirtyValueMarker); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceMappingQRCodeWidget.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceMappingQRCodeWidget.java index 4cdc985eac3..20815e78d99 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceMappingQRCodeWidget.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceMappingQRCodeWidget.java @@ -2,6 +2,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import com.google.gwt.http.client.URL; import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; +import com.sap.sailing.domain.common.racelog.tracking.QRCodeURLCreationException; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.QRCodeComposite; @@ -13,15 +14,8 @@ public class DeviceMappingQRCodeWidget extends BaseQRIdentifierWidget { private String mappedItemId; private String mappedItemType; - static class QRCodeURLCreationException extends Exception { - private static final long serialVersionUID = -8243995470804772458L; - public QRCodeURLCreationException(String message) { - super(message); - } - } - static interface URLFactory { - String createURL(String baseUrlWithoutTrailingSlash, String mappedItemQueryParam) + String createURL(String baseUrlWithoutTrailingSlash, String mappedItemType, String mappedItemId) throws QRCodeURLCreationException; } @@ -52,6 +46,6 @@ public class DeviceMappingQRCodeWidget extends BaseQRIdentifierWidget { throw new QRCodeURLCreationException("No item selected for mapping"); } - return urlFactory.createURL(serverUrl, mappedItemType + "=" + encode(mappedItemId)); + return urlFactory.createURL(serverUrl, mappedItemType, mappedItemId); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java index 3c6325ab3b8..d1dd0711f96 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.text.shared.SafeHtmlRenderer; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class EventConfigImagesBarCell extends ImagesBarCell { static final String ACTION_REMOVE = "ACTION_REMOVE"; @@ -27,7 +28,7 @@ public class EventConfigImagesBarCell extends ImagesBarCell { protected Iterable getImageSpecs() { return Arrays.asList( new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon())) + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon())) ); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java index cb573c4c8c6..74d0956b7bc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java @@ -8,7 +8,6 @@ import java.util.Date; import java.util.List; import java.util.UUID; -import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; @@ -28,11 +27,11 @@ import com.sap.sailing.gwt.ui.shared.CourseAreaDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.VenueDTO; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.controls.listedit.StringConstantsListEditorComposite; import com.sap.sse.gwt.client.controls.listedit.StringListInlineEditorComposite; public abstract class EventDialog extends DataEntryDialogWithBootstrap { - private final AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); protected StringMessages stringMessages; protected TextBox nameEntryField; protected TextArea descriptionEntryField; @@ -131,22 +130,22 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap }; courseAreaNameList = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, resources.removeIcon(), /* suggestValues */ + new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ SuggestedCourseAreaNames.suggestedCourseAreaNames, stringMessages.enterCourseAreaName(), 50)); courseAreaNameList.addValueChangeHandler(valueChangeHandler); final List imageSuggestionURLs = Arrays.asList(new String[] { "http://", "https://", "http://www.", "https://www" }); imageURLList = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, resources.removeIcon(), + new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ imageSuggestionURLs, stringMessages.enterImageURL(), 80)); imageURLList.addValueChangeHandler(valueChangeHandler); List videoURLSuggestions = new ArrayList<>(imageSuggestionURLs); videoURLSuggestions.add("http://www.youtube.com/watch?v="); videoURLList = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, resources.removeIcon(), + new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ videoURLSuggestions, stringMessages.enterVideoURL(), 80)); videoURLList.addValueChangeHandler(valueChangeHandler); sponsorImageURLList = new StringListInlineEditorComposite(Collections. emptyList(), - new StringListInlineEditorComposite.ExpandedUi(stringMessages, resources.removeIcon(), + new StringListInlineEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */ imageSuggestionURLs, stringMessages.enterSponsorImageURL(), 80)); sponsorImageURLList.addValueChangeHandler(valueChangeHandler); List leaderboardGroupNames = new ArrayList<>(); @@ -154,7 +153,7 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap leaderboardGroupNames.add(leaderboardGroupDTO.getName()); } leaderboardGroupList = new StringConstantsListEditorComposite(Collections. emptyList(), - new StringConstantsListEditorComposite.ExpandedUi(stringMessages, resources.removeIcon(), + new StringConstantsListEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), leaderboardGroupNames, "Select a leaderboard group...")); leaderboardGroupList.addValueChangeHandler(valueChangeHandler); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java index 375a7612bd4..424e67c7971 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java @@ -35,6 +35,7 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.dialog.DataEntryDialog; import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; @@ -48,7 +49,6 @@ public class IgtimiAccountsPanel extends FlowPanel { public static class AccountImagesBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); private final StringMessages stringMessages; public AccountImagesBarCell(StringMessages stringMessages) { @@ -64,7 +64,7 @@ public class IgtimiAccountsPanel extends FlowPanel { @Override protected Iterable getImageSpecs() { return Arrays.asList( - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigImagesBarCell.java index f83621faf1a..7778bfe95ff 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.text.shared.SafeHtmlRenderer; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class LeaderboardConfigImagesBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; @@ -35,7 +36,7 @@ public class LeaderboardConfigImagesBarCell extends ImagesBarCell { new ImageSpec(ACTION_EDIT_SCORES, stringMessages.actionEditScores(), makeImagePrototype(resources.scoresIcon())), new ImageSpec(ACTION_EDIT_COMPETITORS, stringMessages.actionEditCompetitors(), makeImagePrototype(resources.competitorsIcon())), new ImageSpec(ACTION_CONFIGURE_URL, stringMessages.actionConfigureUrl(), makeImagePrototype(resources.settingsActionIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon())), + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon())), new ImageSpec(ACTION_EXPORT_XML, stringMessages.actionExportXML(), makeImagePrototype(resources.exportXMLIcon())), new ImageSpec(ACTION_OPEN_COACH_DASHBOARD, stringMessages.actionOpenDashboard(), makeImagePrototype(resources.openCoachDashboard()))); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigImagesBarCell.java index 8e639715f3b..9f4528eda9a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.text.shared.SafeHtmlRenderer; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class LeaderboardGroupConfigImagesBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; @@ -26,6 +27,6 @@ public class LeaderboardGroupConfigImagesBarCell extends ImagesBarCell { @Override protected Iterable getImageSpecs() { return Arrays.asList(new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java index 3a938222b06..f37d691c789 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java @@ -8,6 +8,7 @@ import com.sap.sailing.domain.common.LeaderboardType; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; +import com.sap.sse.gwt.client.IconResources; public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { public final static String ACTION_REMOVE = "ACTION_REMOVE"; @@ -35,7 +36,7 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { StrippedLeaderboardDTO selectedLeaderboard = selectedLeaderboardProvider.getSelectedLeaderboard(); if (selectedLeaderboard != null && selectedLeaderboard.type != LeaderboardType.RegattaLeaderboard && selectedLeaderboard.type != LeaderboardType.RegattaMetaLeaderboard) { // race columns cannot be removed from a regatta leaderboard; they need to be removed from the regatta instead - result.add(new ImageSpec(ACTION_REMOVE, stringMessages.actionRaceRemove(), makeImagePrototype(resources.removeIcon()))); + result.add(new ImageSpec(ACTION_REMOVE, stringMessages.actionRaceRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } result.add(new ImageSpec(ACTION_REFRESH_RACELOG, stringMessages.refreshRaceLog(), makeImagePrototype(resources.reloadIcon()))); result.add(new ImageSpec(ACTION_SET_STARTTIME, stringMessages.setStartTime(), makeImagePrototype(resources.clockIcon()))); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaActionBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaActionBarCell.java index e5542f1aec9..cd2ef26340d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaActionBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaActionBarCell.java @@ -2,14 +2,13 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.Arrays; -import com.google.gwt.core.client.GWT; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class MediaActionBarCell extends ImagesBarCell { public static final String ACTION_REMOVE = "ACTION_REMOVE"; - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); private final StringMessages stringMessages; public MediaActionBarCell(StringMessages stringMessages) { @@ -20,6 +19,6 @@ public class MediaActionBarCell extends ImagesBarCell { @Override protected Iterable getImageSpecs() { return Arrays.asList(new ImageSpec(ACTION_REMOVE, - stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingDeviceMappingsImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingDeviceMappingsImagesBarCell.java index d31582aa965..2cc7ce92ca8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingDeviceMappingsImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingDeviceMappingsImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; +import com.sap.sse.gwt.client.IconResources; public class RaceLogTrackingDeviceMappingsImagesBarCell extends ImagesBarCell { public static final String ACTION_CLOSE = "CLOSE"; @@ -23,7 +24,7 @@ public class RaceLogTrackingDeviceMappingsImagesBarCell extends ImagesBarCell { ArrayList result = new ArrayList(); DeviceMappingDTO mapping = (DeviceMappingDTO) getContext().getKey(); - result.add(new ImageSpec(ACTION_REMOVE, stringMessages.remove(), makeImagePrototype(resources.removeIcon()))); + result.add(new ImageSpec(ACTION_REMOVE, stringMessages.remove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); if (mapping.from == null || mapping.to == null) { result.add(new ImageSpec(ACTION_CLOSE, stringMessages.closeTimeRange(), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java index 5ea041d561e..2c24f547e1a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.text.shared.SafeHtmlRenderer; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class RegattaConfigImagesBarCell extends ImagesBarCell { static final String ACTION_REMOVE = "ACTION_REMOVE"; @@ -26,6 +27,6 @@ public class RegattaConfigImagesBarCell extends ImagesBarCell { @Override protected Iterable getImageSpecs() { return Arrays.asList(new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java index 0ff24e805ba..bd855d46bea 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java @@ -2,7 +2,6 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.List; -import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; @@ -12,10 +11,10 @@ import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.SeriesDTO; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.controls.listedit.ListEditorComposite; public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWithSeriesAndFleetsDialog { - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); protected TextBox nameEntryField; protected TextBox boatClassEntryField; @@ -38,7 +37,7 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWi @Override protected ListEditorComposite createSeriesEditor(Iterable series) { - return new SeriesWithFleetsListEditor(series, stringMessages, resources.removeIcon(), isEnableFleetRemoval()); + return new SeriesWithFleetsListEditor(series, stringMessages, IconResources.INSTANCE.removeIcon(), isEnableFleetRemoval()); } protected abstract boolean isEnableFleetRemoval(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesConfigImagesBarCell.java index 839416b3260..2f1263e5921 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesConfigImagesBarCell.java @@ -6,6 +6,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.text.shared.SafeHtmlRenderer; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sse.gwt.client.IconResources; public class SeriesConfigImagesBarCell extends ImagesBarCell { static final String ACTION_REMOVE = "ACTION_REMOVE"; @@ -26,6 +27,6 @@ public class SeriesConfigImagesBarCell extends ImagesBarCell { @Override protected Iterable getImageSpecs() { return Arrays.asList(new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java index 68b306e0a3e..37c769e6c8a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java @@ -6,7 +6,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import com.google.gwt.core.shared.GWT; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; @@ -31,14 +30,12 @@ import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.SeriesDTO; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.controls.listedit.StringListEditorComposite; import com.sap.sse.gwt.client.controls.listedit.StringListInlineEditorComposite; import com.sap.sse.gwt.client.dialog.DataEntryDialog; public class SeriesEditDialog extends DataEntryDialog { - - private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); - private TextBox seriesNameTextBox; private CheckBox isMedalCheckbox; private CheckBox startWithZeroScoreCheckbox; @@ -204,7 +201,7 @@ public class SeriesEditDialog extends DataEntryDialog { discardThresholdBoxesWidget.setVisible(useSeriesResultDiscardingThresholdsCheckbox.getValue()); additionalWidgetPanel.add(discardThresholdBoxesWidget); - raceNamesEditor = new StringListInlineEditorComposite(getExistingRacesOfSeries(), new RaceNamesEditorUi(regatta, stringMessages, resources.removeIcon(), seriesName)); + raceNamesEditor = new StringListInlineEditorComposite(getExistingRacesOfSeries(), new RaceNamesEditorUi(regatta, stringMessages, IconResources.INSTANCE.removeIcon(), seriesName)); raceNamesEditor.ensureDebugId("RaceNamesStringListEditorComposite"); raceNamesEditor.addValueChangeHandler(new ValueChangeHandler>() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsCreateDialog.java index dd5031d3b76..7343855a644 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsCreateDialog.java @@ -20,6 +20,7 @@ import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.SeriesDTO; +import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.controls.listedit.ListEditorComposite; import com.sap.sse.gwt.client.dialog.DataEntryDialog; @@ -146,7 +147,7 @@ public class SeriesWithFleetsCreateDialog extends DataEntryDialog { protected void initializeFleetListComposite(StringMessages stringMessages) { fleetListComposite = new FleetListEditorComposite(Arrays.asList(new FleetDTO( - LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null)), stringMessages, resources.removeIcon()); + LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null)), stringMessages, IconResources.INSTANCE.removeIcon()); fleetListComposite.ensureDebugId("FleetListEditorComposite"); fleetListComposite.addValueChangeHandler(new ValueChangeHandler>() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsDefaultCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsDefaultCreateDialog.java index 12c7011cd36..2ba1ac26a8b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsDefaultCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesWithFleetsDefaultCreateDialog.java @@ -12,6 +12,7 @@ import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.SeriesDTO; +import com.sap.sse.gwt.client.IconResources; /** * A variant of the dialog used to create a series within a regatta that has fleets. This variant is actually more of a @@ -49,7 +50,7 @@ public class SeriesWithFleetsDefaultCreateDialog extends SeriesWithFleetsCreateD protected void initializeFleetListComposite(StringMessages stringMessages) { fleetListComposite = new FleetListEditableEditorComposite(Arrays.asList(new FleetDTO( - LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null)), stringMessages, resources.removeIcon()); + LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null)), stringMessages, IconResources.INSTANCE.removeIcon()); fleetListComposite.ensureDebugId("FleetListEditableEditorComposite"); fleetListComposite.addValueChangeHandler(new ValueChangeHandler>() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/GwtUrlHelper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/GwtUrlHelper.java new file mode 100644 index 00000000000..58c0c4ce99d --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/GwtUrlHelper.java @@ -0,0 +1,22 @@ +package com.sap.sailing.gwt.ui.client; + +import com.google.gwt.core.shared.GWT; +import com.google.gwt.http.client.URL; +import com.sap.sse.common.util.UrlHelper; + +/** + * Tycho complains that {@link com.google.gwt} cannot be resolved when placing this in *common projects, where it would ideally + * go (then we could also auto-determine if GWT context is present, e.g. through {@link GWT#isClient}). + * + * @author Fredrik Teschke + * + */ +public enum GwtUrlHelper implements UrlHelper { + INSTANCE; + + @Override + public String encodeUrl(String decodedUrlString) { + return URL.encode(decodedUrlString); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index 938a6aa1123..a66c90200b5 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -87,6 +87,7 @@ import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO; import com.sap.sse.common.NoCorrespondingServiceRegisteredException; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.mail.MailException; import com.sap.sse.common.search.KeywordQuery; import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtService; @@ -573,4 +574,7 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List getDeviceMappingsFromLogHierarchy(String leaderboardName, String raceColumnName, String fleetName) throws TransformationException; + + void inviteCompetitorsForTrackingViaEmail(String serverUrlWithoutTrailingSlash, EventDTO event, + String leaderboardName, Set competitors, String localeInfo) throws MailException; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index 196080e488d..90c914384a3 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -684,4 +684,8 @@ public interface SailingServiceAsync extends BuildVersionRetriever, FileStorageM void createRegattaStructure(Iterable regattaNames, EventDTO newEvent, AsyncCallback asyncCallback); + void getActiveFileStorageServiceName(AsyncCallback callback); + + void inviteCompetitorsForTrackingViaEmail(String serverUrlWithoutTrailingSlash, EventDTO event, + String leaderboardName, Set competitors, String localeInfo, AsyncCallback callback); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index cbef88b3ee3..7c30ad62231 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -34,6 +34,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages { String carry(); String competitor(); String competitors(); + String competitorsSelected(int selectedCompetitorsCount, int competitorsCount); String defaultLeaderboard(); String noSuchLeaderboard(); String leaderboardConfiguration(); @@ -1141,4 +1142,11 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages { String scoringSchemeHighPointEssOverallDescription(); String timeBetweenRaceStartAndCompetitorStartInSeconds(); String timeBetweenRaceStartAndCompetitorStartInSecondsTooltip(); + String email(); + String pleaseEnterAnEmail(); + String inviteCompetitors(); + String notAllCompetitorsProvideEmail(); + String sendingMailsFailed(); + String sendingMailsSuccessfull(); + String selectEventForInvitation(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 6a71c26d303..2f7373b6bab 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -29,6 +29,7 @@ total=\u03A3 carry=Accumulated competitor=Competitor competitors=Competitors +competitorsSelected={0}/{1} competitors selected. defaultLeaderboard=Default Leaderboard noSuchLeaderboard=No such leaderboard leaderboardConfiguration=Leaderboard Configuration @@ -1121,4 +1122,11 @@ fileStorage=File Storage active=Active scoringSchemeHighPointEssOverallDescription=Score in points. Winner of an act scores 10 points, 2nd - 9 points, .... Any tie in the overall Extreme Sailing Series is broken in favour of the competitor with the most Act wins. If that does not break the tie, the result in the last Act will be used. timeBetweenRaceStartAndCompetitorStartInSeconds=Start delay -timeBetweenRaceStartAndCompetitorStartInSecondsTooltip=Time between the start of the race and the time the competitor passed the start waypoint. Negative time suggests OCS. \ No newline at end of file +timeBetweenRaceStartAndCompetitorStartInSecondsTooltip=Time between the start of the race and the time the competitor passed the start waypoint. Negative time suggests OCS. +email=E-Mail +pleaseEnterAnEmail=Please enter an E-Mail. +inviteCompetitors=Invite competitors +notAllCompetitorsProvideEmail=Not all competitors provide an E-Mail +sendingMailsFailed=Sending Mails failed +sendingMailsSuccessfull=Successfully sent E-Mails +selectEventForInvitation=Select Event for Invitation \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 5fc7d30cba1..ad69cfd2349 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -29,6 +29,7 @@ total=Gesamt carry=übertr. competitor=Team competitors=Teams +competitorsSelected={0}/{1} Teams ausgewählt. defaultLeaderboard=Alle Ergebnisse noSuchLeaderboard=Rangliste nicht gefunden leaderboardConfiguration=Ranglisten-Konfiguration @@ -1111,4 +1112,11 @@ fileStorage=Datei Speicherung active=Aktiv scoringSchemeHighPointEssOverallDescription=High Point System, der Gewinner eines Acts erhält 10 Punkte, der Zweite 9 und so weiter. timeBetweenRaceStartAndCompetitorStartInSeconds=Startverzug -timeBetweenRaceStartAndCompetitorStartInSecondsTooltip=Zeit seit dem Start der Wettfahrt, nach der der Teilnehmer die Startmarke passiert hat. Negative Werte suggerieren einen Frühstart. \ No newline at end of file +timeBetweenRaceStartAndCompetitorStartInSecondsTooltip=Zeit seit dem Start der Wettfahrt, nach der der Teilnehmer die Startmarke passiert hat. Negative Werte suggerieren einen Frühstart. +email=E-Mail +pleaseEnterAnEmail=Bitte geben Sie eine E-Mail ein. +inviteCompetitors=Teilnehmer einladen +notAllCompetitorsProvideEmail=Nicht alle Teilnehmer haben eine E-Mail angegeben +sendingMailsFailed=Versenden der E-Mails fehlgeschlagen +sendingMailsSuccessfull=Versenden der E-Mails war erfolgreich! +selectEventForInvitation=Event für Einladung auswählen \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties index 67d2e6e8c6d..2b46014b206 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties @@ -29,6 +29,7 @@ total=\u03A3 carry=Суммарная competitor=Участник competitors=Участники +competitorsSelected={0}/{1} Участники. defaultLeaderboard=Таблица лидеров по умолчанию noSuchLeaderboard=Такая таблица лидеров отсутствует leaderboardConfiguration=Форма таблицы лидеров @@ -1060,4 +1061,11 @@ fileStorage=File Storage active=Active scoringSchemeHighPointEssOverallDescription=Score in points. Winner of an act scores 10 points, 2nd - 9 points, .... Any tie in the overall Extreme Sailing Series is broken in favour of the competitor with the most Act wins. If that does not break the tie, the result in the last Act will be used. timeBetweenRaceStartAndCompetitorStartInSeconds=Start delay -timeBetweenRaceStartAndCompetitorStartInSecondsTooltip=Time between the start of the race and the time the competitor passed the start waypoint. Negative time suggests OCS. \ No newline at end of file +timeBetweenRaceStartAndCompetitorStartInSecondsTooltip=Time between the start of the race and the time the competitor passed the start waypoint. Negative time suggests OCS. +email=эмаль +pleaseEnterAnEmail=Пожалуйста, введите эмаль +inviteCompetitors=приглашать Участники +notAllCompetitorsProvideEmail=Not all competitors provide an E-Mail +sendingMailsFailed=Sending Mails failed +sendingMailsSuccessfull=Successfully sent E-Mails +selectEventForInvitation=Select Event for Invitation \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java index feb71eaee46..c6899dd8751 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java @@ -27,6 +27,7 @@ import org.moxieapps.gwt.highcharts.client.plotOptions.Marker; import org.moxieapps.gwt.highcharts.client.plotOptions.Marker.Symbol; import com.google.gwt.i18n.client.NumberFormat; +import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.RequiresResize; import com.google.gwt.user.client.ui.Widget; @@ -180,7 +181,7 @@ public abstract class AbstractCompetitorLeaderboardChart extends A })); } - protected void clearChart() { + public void clearChart() { competitorSeries.clear(); chart.removeAllSeries(); } @@ -245,7 +246,9 @@ public abstract class AbstractCompetitorLeaderboardChart extends A break; } - chart.setSizeToMatchContainer(); + // TODO will removing the following line do harm on any usage of this abstract base class? + // chart.setSizeToMatchContainer(); + // it's important here to recall the redraw method, otherwise the bug fix for wrong checkbox // positions (nativeAdjustCheckboxPosition) // in the BaseChart class would not be called @@ -296,8 +299,11 @@ public abstract class AbstractCompetitorLeaderboardChart extends A raceColumnNumber++; } } - chart.getYAxis().setMaxPadding(0.5 / maxCompetitorCount).setMinPadding(0.5 / maxCompetitorCount); - chart.setHeight(maxCompetitorCount * 30 + 100 + "px"); + setHeight(); + } + + private void setHeight() { + chart.setSize(chart.getOffsetWidth(), Window.getClientHeight()); } private void fillTotalPointsSeries( @@ -341,8 +347,7 @@ public abstract class AbstractCompetitorLeaderboardChart extends A raceColumnNumber++; } } - chart.getYAxis().setMaxPadding(0.5/maxCompetitorCount).setMinPadding(0.5/maxCompetitorCount); - chart.setHeight(maxCompetitorCount * 30 + 100 + "px"); + setHeight(); } private boolean hasValidValues(List values) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 3fc62904e07..efe9616b827 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -418,6 +418,7 @@ import com.sap.sse.common.Util.Triple; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.impl.TimeRangeImpl; +import com.sap.sse.common.mail.MailException; import com.sap.sse.common.search.KeywordQuery; import com.sap.sse.common.search.Result; import com.sap.sse.filestorage.FileStorageService; @@ -431,8 +432,10 @@ import com.sap.sse.replication.ReplicationFactory; import com.sap.sse.replication.ReplicationMasterDescriptor; import com.sap.sse.replication.ReplicationService; import com.sap.sse.replication.impl.ReplicaDescriptor; +import com.sap.sse.util.ServiceTrackerFactory; import com.sapsailing.xrr.structureimport.eventimport.RegattaJSON; + /** * The server side implementation of the RPC service. */ @@ -496,6 +499,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private final SwissTimingReplayService swissTimingReplayService; private final QuickRanksLiveCache quickRanksLiveCache; + public SailingServiceImpl() { BundleContext context = Activator.getDefault(); Activator activator = Activator.getInstance(); @@ -503,21 +507,25 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S activator.setSailingService(this); // register so this service is informed when the bundle shuts down } quickRanksLiveCache = new QuickRanksLiveCache(this); - racingEventServiceTracker = createAndOpenRacingEventServiceTracker(context); - replicationServiceTracker = createAndOpenReplicationServiceTracker(context); - resultUrlRegistryServiceTracker = createAndOpenResultUrlRegistryServiceTracker(context); - swissTimingAdapterTracker = createAndOpenSwissTimingAdapterTracker(context); - tractracAdapterTracker = createAndOpenTracTracAdapterTracker(context); - raceLogTrackingAdapterTracker = createAndOpenRaceLogTrackingAdapterTracker(context); - deviceIdentifierStringSerializationHandlerTracker = createAndOpenDeviceIdentifierStringSerializationHandlerTracker(context); - igtimiAdapterTracker = createAndOpenIgtimiTracker(context); + racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class); + replicationServiceTracker = ServiceTrackerFactory.createAndOpen(context, ReplicationService.class); + resultUrlRegistryServiceTracker = ServiceTrackerFactory.createAndOpen(context, ResultUrlRegistry.class); + swissTimingAdapterTracker = ServiceTrackerFactory.createAndOpen(context, SwissTimingAdapterFactory.class); + tractracAdapterTracker = ServiceTrackerFactory.createAndOpen(context, TracTracAdapterFactory.class); + raceLogTrackingAdapterTracker = ServiceTrackerFactory.createAndOpen(context, + RaceLogTrackingAdapterFactory.class); + deviceIdentifierStringSerializationHandlerTracker = ServiceTrackerFactory.createAndOpen(context, + DeviceIdentifierStringSerializationHandler.class); + igtimiAdapterTracker = ServiceTrackerFactory.createAndOpen(context, IgtimiConnectionFactory.class); baseDomainFactory = getService().getBaseDomainFactory(); mongoObjectFactory = getService().getMongoObjectFactory(); domainObjectFactory = getService().getDomainObjectFactory(); // TODO what about passing on the mongo/domain object factory to obtain an according SwissTimingAdapterPersistence instance similar to how the tractracDomainObjectFactory etc. are created below? swissTimingAdapterPersistence = SwissTimingAdapterPersistence.INSTANCE; - swissTimingReplayService = getSwissTimingReplayService(context); - scoreCorrectionProviderServiceTracker = createAndOpenScoreCorrectionProviderServiceTracker(context); + swissTimingReplayService = ServiceTrackerFactory.createAndOpen(context, SwissTimingReplayServiceFactory.class) + .getService().createSwissTimingReplayService(getSwissTimingAdapter().getSwissTimingDomainFactory()); + scoreCorrectionProviderServiceTracker = ServiceTrackerFactory.createAndOpen(context, + ScoreCorrectionProvider.class); tractracDomainObjectFactory = com.sap.sailing.domain.tractracadapter.persistence.PersistenceFactory.INSTANCE .createDomainObjectFactory(mongoObjectFactory.getDatabase(), getTracTracAdapter() .getTracTracDomainFactory()); @@ -556,89 +564,26 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S quickRanksLiveCache.stop(); } - protected SwissTimingReplayService getSwissTimingReplayService(BundleContext context) { - return createAndOpenSwissTimingReplayServiceTracker(context).getService().createSwissTimingReplayService(getSwissTimingAdapter().getSwissTimingDomainFactory()); + protected SwissTimingAdapterFactory getSwissTimingAdapterFactory() { + return swissTimingAdapterTracker.getService(); } protected SwissTimingAdapter getSwissTimingAdapter() { - return swissTimingAdapterTracker.getService().getOrCreateSwissTimingAdapter(baseDomainFactory); + return getSwissTimingAdapterFactory().getOrCreateSwissTimingAdapter(baseDomainFactory); + } + + protected TracTracAdapterFactory getTracTracAdapterFactory() { + return tractracAdapterTracker.getService(); } protected TracTracAdapter getTracTracAdapter() { - return tractracAdapterTracker.getService().getOrCreateTracTracAdapter(baseDomainFactory); - } - - protected ServiceTracker createAndOpenTracTracAdapterTracker(BundleContext context) { - ServiceTracker result = new ServiceTracker( - context, TracTracAdapterFactory.class.getName(), null); - result.open(); - return result; - } - - protected ServiceTracker createAndOpenIgtimiTracker(BundleContext context) { - ServiceTracker result = new ServiceTracker( - context, IgtimiConnectionFactory.class.getName(), null); - result.open(); - return result; - } - - protected ServiceTracker createAndOpenSwissTimingAdapterTracker( - BundleContext context) { - ServiceTracker result = new ServiceTracker( - context, SwissTimingAdapterFactory.class.getName(), null); - result.open(); - return result; - } - - protected ServiceTracker createAndOpenSwissTimingReplayServiceTracker( - BundleContext context) { - ServiceTracker result = new ServiceTracker( - context, SwissTimingReplayServiceFactory.class.getName(), null); - result.open(); - return result; - } - - protected ServiceTracker createAndOpenRaceLogTrackingAdapterTracker( - BundleContext context) { - ServiceTracker result = - new ServiceTracker( - context, RaceLogTrackingAdapterFactory.class.getName(), null); - result.open(); - return result; + return getTracTracAdapterFactory().getOrCreateTracTracAdapter(baseDomainFactory); } private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); } - protected ServiceTracker createAndOpenRacingEventServiceTracker( - BundleContext context) { - ServiceTracker result = new ServiceTracker( - context, RacingEventService.class.getName(), null); - result.open(); - return result; - } - - protected ServiceTracker createAndOpenResultUrlRegistryServiceTracker( - BundleContext context) { - ServiceTracker result = new ServiceTracker( - context, ResultUrlRegistry.class.getName(), null); - result.open(); - return result; - } - - /** - * Asks the OSGi system for registered score correction provider services - */ - protected ServiceTracker createAndOpenScoreCorrectionProviderServiceTracker( - BundleContext bundleContext) { - ServiceTracker tracker = new ServiceTracker(bundleContext, - ScoreCorrectionProvider.class.getName(), - /* customizer */null); - tracker.open(); - return tracker; - } - @Override public Iterable getScoreCorrectionProviderNames() { List result = new ArrayList(); @@ -685,15 +630,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return new ScoreCorrectionProviderDTO(scoreCorrectionProvider.getName(), hasResultsForBoatClassFromDateByEventName); } - protected ServiceTracker createAndOpenReplicationServiceTracker( - BundleContext context) { - ServiceTracker result = - new ServiceTracker( - context, ReplicationService.class.getName(), null); - result.open(); - return result; - } - /** * If date is null, the {@link LiveLeaderboardUpdater} for the * leaderboardName requested is obtained or created if it doesn't exist yet. The request is then passed @@ -1116,10 +1052,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } - private SwissTimingReplayService getSwissTimingReplayService() { - return swissTimingReplayService; - } - @Override public List getPreviousTracTracConfigurations() throws Exception { Iterable configs = tractracDomainObjectFactory.getTracTracConfigurations(); @@ -2239,7 +2171,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return racingEventServiceTracker.getService(); // grab the service } - private ReplicationService getReplicationService() { + protected ReplicationService getReplicationService() { return replicationServiceTracker.getService(); } @@ -2699,6 +2631,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } } + + protected SwissTimingReplayService getSwissTimingReplayService() { + return swissTimingReplayService; + } @Override public List listSwissTiminigReplayRaces(String swissTimingUrl) { @@ -4538,12 +4474,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S DynamicBoat boat = new BoatImpl(competitor.getName() + " boat", boatClass, competitor.getSailID()); result = getBaseDomainFactory().convertToCompetitorDTO( getBaseDomainFactory().getOrCreateCompetitor(UUID.randomUUID(), competitor.getName(), - competitor.getColor(), team, boat)); + competitor.getColor(), competitor.getEmail(), team, boat)); } else { result = getBaseDomainFactory().convertToCompetitorDTO( getService().apply( new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), competitor - .getColor(), competitor.getSailID(), nationality, existingCompetitor.getTeam().getImage()))); + .getColor(), competitor.getEmail(), competitor.getSailID(), nationality, existingCompetitor.getTeam().getImage()))); } return result; } @@ -4736,9 +4672,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private IgtimiConnectionFactory getIgtimiConnectionFactory() { return igtimiAdapterTracker.getService(); } + + protected RaceLogTrackingAdapterFactory getRaceLogTrackingAdapterFactory() { + return raceLogTrackingAdapterTracker.getService(); + } protected RaceLogTrackingAdapter getRaceLogTrackingAdapter() { - return raceLogTrackingAdapterTracker.getService().getAdapter(getBaseDomainFactory()); + return getRaceLogTrackingAdapterFactory().getAdapter(getBaseDomainFactory()); } @Override @@ -5180,16 +5120,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S raceLog.add(event); } - private ServiceTracker - createAndOpenDeviceIdentifierStringSerializationHandlerTracker(BundleContext context) { - ServiceTracker tracker = - new ServiceTracker( - context, DeviceIdentifierStringSerializationHandler.class, null); - - tracker.open(); - return tracker; - } - @Override public List getDeserializableDeviceIdentifierTypes() { List result = new ArrayList(); @@ -5436,13 +5366,16 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } return getService().getFileStorageManagementService().getFileStorageService(name); } + + private Locale getLocale(String localeInfoName) { + return ResourceBundleStringMessages.Util.getLocaleFor(localeInfoName); + } @Override public FileStorageServiceDTO[] getAvailableFileStorageServices(String localeInfoName) { - Locale locale = ResourceBundleStringMessages.Util.getLocaleFor(localeInfoName); List serviceDtos = new ArrayList<>(); for (FileStorageService s : getService().getFileStorageManagementService().getAvailableFileStorageServices()) { - serviceDtos.add(FileStorageServiceDTOUtils.convert(s, locale)); + serviceDtos.add(FileStorageServiceDTOUtils.convert(s, getLocale(localeInfoName))); } return serviceDtos.toArray(new FileStorageServiceDTO[0]); } @@ -5461,14 +5394,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public FileStorageServicePropertyErrorsDTO testFileStorageServiceProperties(String serviceName, String localeInfoName) { - Locale locale = ResourceBundleStringMessages.Util.getLocaleFor(localeInfoName); try { FileStorageService service = getFileStorageService(serviceName); if (service != null) { service.testProperties(); } } catch (InvalidPropertiesException e) { - return FileStorageServiceDTOUtils.convert(e, locale); + return FileStorageServiceDTOUtils.convert(e, getLocale(localeInfoName)); } return null; } @@ -5486,4 +5418,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return null; } } + + @Override + public void inviteCompetitorsForTrackingViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, + String leaderboardName, Set competitorDtos, String localeInfoName) throws MailException { + Event event = getService().getEvent(eventDto.id); + Set competitors = new HashSet<>(); + for (CompetitorDTO c : competitorDtos) { + competitors.add(getCompetitor(c)); + } + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + getRaceLogTrackingAdapter().inviteCompetitorsForTrackingViaEmail(event, leaderboard, serverUrlWithoutTrailingSlash, + competitors, getLocale(localeInfoName)); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html index b8fe7d2e47c..fba94343b2e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html @@ -180,7 +180,7 @@
  • China races, such as in Qingdao, may have the map background displayed at slightly wrong locations. This is due to an intentional random transformation that Google applies to GPS locations for China. You can circumvent this issue by switching to satellite view where the map background is displayed - correctly. + correctly.
  • Fixed a bug that in some cases has caused the wind chart, the advantage line, the wind indicator on the map and the leaderboard to use slightly different wind values. The problem was related to different averaging and diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/shiro.ini b/java/com.sap.sailing.gwt.ui/src/main/resources/shiro.ini index 2958f1e5360..d9123231d8e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/shiro.ini +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/shiro.ini @@ -14,10 +14,10 @@ credentialsMatcher.hashIterations = 1024 upRealm = com.sap.sse.security.UsernamePasswordRealm upRealm.credentialsMatcher = $credentialsMatcher - oauthRealm = com.sap.sse.security.OAuthRealm +accessTokenRealm = com.sap.sse.security.AccessTokenRealm -securityManager.realms = $upRealm, $oauthRealm +securityManager.realms = $upRealm, $oauthRealm, $accessTokenRealm sessionManager = com.sap.sse.security.SecurityWebSessionManager securityManager.sessionManager = $sessionManager diff --git a/java/com.sap.sailing.media.persistence.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.media.persistence.test/META-INF/MANIFEST.MF index 4a9952f771c..86266b2b867 100644 --- a/java/com.sap.sailing.media.persistence.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.media.persistence.test/META-INF/MANIFEST.MF @@ -5,7 +5,7 @@ Bundle-SymbolicName: com.sap.sailing.media.persistence.test Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: com.mongodb.driver;bundle-version="2.6.2", +Require-Bundle: org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sse.mongodb, org.json.simple;bundle-version="1.1.0", org.hamcrest.core;bundle-version="1.1.0", diff --git a/java/com.sap.sailing.media.persistence.test/src/com/sap/sailing/media/persistence/test/AbstractMongoDBTest.java b/java/com.sap.sailing.media.persistence.test/src/com/sap/sailing/media/persistence/test/AbstractMongoDBTest.java index 2b575666043..1e0e90d58ad 100644 --- a/java/com.sap.sailing.media.persistence.test/src/com/sap/sailing/media/persistence/test/AbstractMongoDBTest.java +++ b/java/com.sap.sailing.media.persistence.test/src/com/sap/sailing/media/persistence/test/AbstractMongoDBTest.java @@ -8,6 +8,7 @@ import org.junit.Before; import com.mongodb.DB; import com.mongodb.Mongo; +import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.sap.sse.mongodb.MongoDBConfiguration; import com.sap.sse.mongodb.MongoDBService; @@ -30,7 +31,7 @@ public abstract class AbstractMongoDBTest { } protected Mongo newMongo() throws UnknownHostException, MongoException { - return new Mongo(System.getProperty("mongo.host", "127.0.0.1"), dbConfiguration.getPort()); + return new MongoClient(System.getProperty("mongo.host", "127.0.0.1"), dbConfiguration.getPort()); } @Before diff --git a/java/com.sap.sailing.media.persistence.test/src/com/sap/sailing/media/persistence/test/MediaDBTest.java b/java/com.sap.sailing.media.persistence.test/src/com/sap/sailing/media/persistence/test/MediaDBTest.java index 425bf369413..4c70ea73458 100644 --- a/java/com.sap.sailing.media.persistence.test/src/com/sap/sailing/media/persistence/test/MediaDBTest.java +++ b/java/com.sap.sailing.media.persistence.test/src/com/sap/sailing/media/persistence/test/MediaDBTest.java @@ -51,7 +51,7 @@ public class MediaDBTest extends AbstractMongoDBTest { @Test public void testCreateVideoTrackWithId() { - final String dbId = new ObjectId().toStringMongod(); + final String dbId = new ObjectId().toHexString(); final String videoTitle = "Test Video"; final String url = "http://localhost:8888/media/HTML5/1809147112001_1842870496001_SAP-Regatta-Day02-Final_libtheora.ogv"; MediaDB mongoDB = MediaDBFactory.INSTANCE.getMediaDB(getMongoService()); @@ -101,7 +101,7 @@ public class MediaDBTest extends AbstractMongoDBTest { // @Test // public void testImportVideoTrackToEmptyDb() throws Exception { // //insert test object -// final String dbId = new ObjectId().toStringMongod(); +// final String dbId = new ObjectId().toHexString(); // final String title = "Test Video"; // final String url = "test"; // Date date = new Date(); diff --git a/java/com.sap.sailing.mongodb.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.mongodb.test/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index 9f5043908a8..5fd34711b67 --- a/java/com.sap.sailing.mongodb.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.mongodb.test/META-INF/MANIFEST.MF @@ -1,35 +1,35 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Test -Bundle-SymbolicName: com.sap.sailing.mongodb.test -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Fragment-Host: com.sap.sse.mongodb -Require-Bundle: com.sap.sailing.domain, - com.sap.sailing.domain.shared.android, - com.sap.sailing.domain.test, - com.tractrac.clientmodule;bundle-version="2.0.0", - com.sap.sailing.domain.tractracadapter, - com.sap.sailing.domain.persistence, - com.sap.sailing.server, - com.sap.sailing.expeditionconnector, - org.json.simple;bundle-version="1.1.0", - com.sap.sailing.domain.swisstimingadapter, - org.objenesis;bundle-version="1.3.0", - org.junit4;bundle-version="4.8.2", - org.hamcrest;bundle-version="1.1.0", - org.mockito.mockito-core;bundle-version="1.9.5", - com.sap.sailing.polars, - com.sap.sailing.domain.racelogtrackingadapter.testsupport, - com.sap.sailing.server.gateway, - com.sap.sse.common, - com.sap.sse.operationaltransformation, - com.sap.sse.replication, - com.sap.sse, - com.sap.sse.filestorage -Import-Package: com.sap.sailing.domain.common, - com.sap.sailing.domain.common.impl, - com.sap.sailing.domain.common.racelog, - com.sap.sailing.domain.common.racelog.tracking - +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Test +Bundle-SymbolicName: com.sap.sailing.mongodb.test +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Fragment-Host: com.sap.sse.mongodb +Require-Bundle: com.sap.sailing.domain, + com.sap.sailing.domain.shared.android, + com.sap.sailing.domain.test, + com.tractrac.clientmodule;bundle-version="2.0.0", + com.sap.sailing.domain.tractracadapter, + com.sap.sailing.domain.persistence, + com.sap.sailing.server, + com.sap.sailing.expeditionconnector, + org.json.simple;bundle-version="1.1.0", + com.sap.sailing.domain.swisstimingadapter, + org.objenesis;bundle-version="1.3.0", + org.junit4;bundle-version="4.8.2", + org.hamcrest;bundle-version="1.1.0", + org.mockito.mockito-core;bundle-version="1.9.5", + com.sap.sailing.polars, + com.sap.sailing.domain.racelogtrackingadapter.testsupport, + com.sap.sailing.server.gateway, + com.sap.sse.common, + com.sap.sse.operationaltransformation, + com.sap.sse.replication, + com.sap.sse, + com.sap.sse.filestorage +Import-Package: com.sap.sailing.domain.common, + com.sap.sailing.domain.common.impl, + com.sap.sailing.domain.common.racelog, + com.sap.sailing.domain.common.racelog.tracking + diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/AbstractMongoDBTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/AbstractMongoDBTest.java index 1093cdb29ed..75f10fdbd1a 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/AbstractMongoDBTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/AbstractMongoDBTest.java @@ -9,6 +9,7 @@ import org.junit.Before; import com.mongodb.DB; import com.mongodb.Mongo; +import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.sap.sse.mongodb.MongoDBConfiguration; import com.sap.sse.mongodb.MongoDBService; @@ -31,20 +32,18 @@ public abstract class AbstractMongoDBTest { } protected Mongo newMongo() throws UnknownHostException, MongoException { - return new Mongo(dbConfiguration.getHostName(), dbConfiguration.getPort()); + return new MongoClient(dbConfiguration.getHostName(), dbConfiguration.getPort()); } @Before public void dropTestDB() throws UnknownHostException, MongoException, InterruptedException { assertNotNull(mongo); - db.requestStart(); dropAllCollections(db); assertNotNull(db); } @After public void tearDown() { - db.requestDone(); } private void dropAllCollections(DB theDB) throws InterruptedException { diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java index 08ece8cbcc0..dad04664a00 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java @@ -82,7 +82,7 @@ public class StoreAndLoadDeviceIdentifierTest extends AbstractMongoDBTest { private DeviceIdentifier storeAndLoad(DeviceIdentifier device, TypeBasedServiceFinderFactory forStoring, TypeBasedServiceFinderFactory forLoading) { createFactories(forStoring); - Competitor c = new CompetitorImpl("a", "a", null, null, null); + Competitor c = new CompetitorImpl("a", "a", null, null, null, null); raceLog.add(RaceLogEventFactory.INSTANCE.createDeviceCompetitorMappingEvent(now(), author, device, c, 0, now(), now())); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java index 84b39d90664..d40fac7e98b 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java @@ -174,7 +174,7 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { @Test public void testStoreAndLoadDeviceCompetitorMappingEvent() { DeviceIdentifier device = new SmartphoneImeiIdentifier("a"); - Competitor mappedTo = DomainFactory.INSTANCE.getOrCreateCompetitor("abc", "abc", null, null, null); + Competitor mappedTo = DomainFactory.INSTANCE.getOrCreateCompetitor("abc", "abc", null, null, null, null); TimePoint from = new MillisecondsTimePoint(20); TimePoint to = new MillisecondsTimePoint(30); RaceLogDeviceCompetitorMappingEvent expectedEvent = eventFactory.createDeviceCompetitorMappingEvent( @@ -251,7 +251,7 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { public void testStoreAndLoadRegisterCompetitorEvent() { RaceLogRegisterCompetitorEvent expectedEvent = eventFactory.createRegisterCompetitorEvent( expectedEventTime, author, expectedEventTime, expectedId, expectedPassId, - DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null)); + DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null)); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogRegisterCompetitorEvent actualEvent = loadEvent(dbObject); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogsTest.java index 41da56eb7bb..a1b3e64e31b 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogsTest.java @@ -178,7 +178,7 @@ public class StoreAndLoadRaceLogsTest extends AbstractMongoDBTest { private static final String OldFormatRaceLogIdentifier = "A%2EA%2EB%2EB%2EC%2EC"; private String createOldFormatRaceLogEventJson(Serializable id) { - return "{ \"_id\" : { \"$oid\" : \""+ new ObjectId().toStringMongod() + "\"} , \"RACE_LOG_IDENTIFIER\" : \"" + OldFormatRaceLogIdentifier + "\" , \"RACE_LOG_EVENT\" : " + return "{ \"_id\" : { \"$oid\" : \""+ new ObjectId().toHexString() + "\"} , \"RACE_LOG_IDENTIFIER\" : \"" + OldFormatRaceLogIdentifier + "\" , \"RACE_LOG_EVENT\" : " + "{ \"TIME_AS_MILLIS\" : 42 , \"RACE_LOG_EVENT_CREATED_AT\" : 1376058090051 , \"RACE_LOG_EVENT_ID\" : { \"$uuid\" : \"" + id.toString() + "\"} , " + "\"RACE_LOG_EVENT_PASS_ID\" : 42 , \"RACE_LOG_EVENT_INVOLVED_BOATS\" : [ ] , \"RACE_LOG_EVENT_CLASS\" : \"RaceLogFlagEvent\" , \"RACE_LOG_EVENT_FLAG_UPPER\" : \"ALPHA\" , " + "\"RACE_LOG_EVENT_FLAG_LOWER\" : \"BRAVO\" , \"RACE_LOG_EVENT_FLAG_DISPLAYED\" : \"true\"}}"; diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java index f1adb9b63e6..078dcfd56fd 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java @@ -58,7 +58,7 @@ public class StoreGPSFixTrackTest extends AbstractMongoDBTest { public void testStoreAndLoadFixes() throws TransformationException, NoCorrespondingServiceRegisteredException { TypeBasedServiceFinderFactory factory = new MockSmartphoneImeiServiceFinderFactory(); AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0); - Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null); + Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null); Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService(), factory); DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE, factory); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestRaceLogRemovalInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestRaceLogRemovalInRegatta.java index 85dd0f2cc3a..1359256c846 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestRaceLogRemovalInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestRaceLogRemovalInRegatta.java @@ -55,7 +55,8 @@ public class TestRaceLogRemovalInRegatta extends AbstractTestStoringAndRetrievin RaceLogStartTimeEvent expectedEventBlue = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now, author, 0, MillisecondsTimePoint.now()); blueLog.add(expectedEventBlue); // these events are now expected to be stored persistently in the race log store - db.getLastError(); // synchronize on DB + //getLastError() is now deprecated - seems to run fine without (at least locally) + //db.getLastError(); // synchronize on DB qualification.removeRaceColumn(raceColumnName); qualification.addRaceColumn(raceColumnName, /* trackedRegattaRegistry */ null /* no re-association with tracked regatta required */); RaceLog yellowLogAfterRecreation = qualification.getRaceColumnByName(raceColumnName).getRaceLog(yellowFleet); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index 720b868c6db..ff13f587b82 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -627,7 +627,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null); List competitors = new ArrayList(); - competitors.add(new CompetitorImpl("Axel", "Axel Uhl", Color.RED, null, null)); + competitors.add(new CompetitorImpl("Axel", "Axel Uhl", Color.RED, null, null, null)); Iterable waypoints = Collections.emptyList(); Course course = new CourseImpl("Course", waypoints); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index 63f90f5e010..538815fa923 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -113,15 +113,15 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe @Test public void testStoringAndRetrievingLeaderboardGroupWithOverallLeaderboardWithScoreCorrection() throws NoWindException { RacingEventService racingEventService = new RacingEventServiceImpl(); - Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), - new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); + Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null, + new TeamImpl("STG", Collections.singleton( + new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); raceWithTwoCompetitors.addCompetitor(hasso); @@ -169,15 +169,15 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe @Test public void testStoringAndRetrievingLeaderboardGroupWithSuppressedCompetitorsInOverallLeaderboard() { - Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), - new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); + Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null, + new TeamImpl("STG", Collections.singleton( + new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); raceWithTwoCompetitors.addCompetitor(hasso); @@ -225,15 +225,15 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe @Test public void testStoringAndRetrievingLeaderboardGroupWithTwoSuppressedCompetitorsInOverallLeaderboard() { - Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), - new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); + Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null, + new TeamImpl("STG", Collections.singleton( + new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); raceWithTwoCompetitors.addCompetitor(hasso); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java index d9fa5489325..0eae97a4c52 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java @@ -76,11 +76,11 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); Competitor wolfgang = createCompetitor(); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), - new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null, + new TeamImpl("STG", Collections.singleton( + new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); raceWithTwoCompetitors.addCompetitor(hasso); @@ -350,7 +350,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final DomainFactory domainFactory = new DomainFactoryImpl(); // create the competitor through the competitor store/factory here so that the DomainObjectFactory finds it and // resolves the score corrections appropriate - Competitor competitor = domainFactory.getOrCreateCompetitor(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, new TeamImpl("STG", Collections.singleton( + Competitor competitor = domainFactory.getOrCreateCompetitor(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, "someone@nowhere.de", new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); @@ -377,10 +377,10 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { } private Competitor createCompetitor() { - Competitor competitor = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); + Competitor competitor = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null)); return competitor; } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java index ba6a79af120..befdd06a53e 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java @@ -125,9 +125,11 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD Fleet defaultFleet = leaderboard.getFleet(null); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); raceColumn.getRaceLog(defaultFleet).add(expectedEvent); - db.getLastError(); // sync DB + //getLastError() is now deprecated - seems to run fine without (at least locally) + //db.getLastError(); // sync DB leaderboard.removeRaceColumn(raceColumnName); - db.getLastError(); // sync DB + //getLastError() is now deprecated - seems to run fine without (at least locally) + //db.getLastError(); // sync DB leaderboard.addRaceColumn(raceColumnName, /* medalRace */false); // now assert that the race log is empty because the column was removed and so should have been the race log RaceLog loadedRaceLog = leaderboard.getRaceColumnByName(raceColumnName).getRaceLog(leaderboard.getRaceColumnByName(raceColumnName).getFleets().iterator().next()); @@ -149,10 +151,12 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD Fleet defaultFleet = leaderboard.getFleet(null); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); raceColumn.getRaceLog(defaultFleet).add(expectedEvent); - db.getLastError(); // sync DB to ensure event is stored + //getLastError() is now deprecated - seems to run fine without (at least locally) + //db.getLastError(); // sync DB to ensure event is stored final String newColumnName = "New "+raceColumnName; service.renameLeaderboardColumn(leaderboardName, raceColumnName, newColumnName); - db.getLastError(); // sync DB + //getLastError() is now deprecated - seems to run fine without (at least locally) + //db.getLastError(); // sync DB // now assert that the race log still holds the original race log event because the column was only renamed RaceLog renamedRaceLog = leaderboard.getRaceColumnByName(newColumnName).getRaceLog(leaderboard.getRaceColumnByName(newColumnName).getFleets().iterator().next()); renamedRaceLog.lockForRead(); @@ -273,7 +277,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningConfirmedEvent() { - Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, null, null); + Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, "someone@nowhere.de", null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new com.sap.sse.common.Util.Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); @@ -342,7 +346,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningListChangeEvent() { - Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, null, null); + Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, "someone@nowhere.de", null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new com.sap.sse.common.Util.Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java index ede401bb4a2..31bc1d59e72 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java @@ -187,7 +187,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningListChangeEvent() { - Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, null, null); + Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, "someone@nowhere.de", null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new com.sap.sse.common.Util.Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); @@ -217,7 +217,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningConfirmedEvent() { - Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, null, null); + Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, "someone@nowhere.de", null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new com.sap.sse.common.Util.Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java index 5b60e2bf20d..bf8931f5d89 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java @@ -14,6 +14,7 @@ import org.junit.Test; import com.mongodb.DB; import com.mongodb.Mongo; +import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; @@ -60,7 +61,7 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive } private Mongo newMongo() throws UnknownHostException, MongoException { - return new Mongo(dbConfiguration.getHostName(), + return new MongoClient(dbConfiguration.getHostName(), dbConfiguration.getPort()); } diff --git a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetGenerationTest.java b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetGenerationTest.java index 31622df7ab3..42b953c8aa9 100644 --- a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetGenerationTest.java +++ b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetGenerationTest.java @@ -91,8 +91,8 @@ public class PolarSheetGenerationTest { settings, executor); BoatClass forelle = new BoatClassImpl("Forelle", true); - Competitor competitor = new CompetitorImpl(UUID.randomUUID(), "Hans Frantz", Color.RED, new TeamImpl("SAP", null, null), - new BoatImpl("Schnelle Forelle", forelle, "GER000")); + Competitor competitor = new CompetitorImpl(UUID.randomUUID(), "Hans Frantz", Color.RED, null, + new TeamImpl("SAP", null, null), new BoatImpl("Schnelle Forelle", forelle, "GER000")); PolarFixAggregationWorker task = new PolarFixAggregationWorker(race, resultContainer, startTime, endTime, diff --git a/java/com.sap.sailing.selenium.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.selenium.test/META-INF/MANIFEST.MF index 30df672565c..5d967ca8b4f 100644 --- a/java/com.sap.sailing.selenium.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.selenium.test/META-INF/MANIFEST.MF @@ -9,7 +9,7 @@ Require-Bundle: org.hamcrest;bundle-version="1.1.0", org.junit4;bundle-version="4.8.2", org.openqa.selenium.osgi;bundle-version="2.40.0", com.sap.sse.mongodb;bundle-version="1.0.0", - com.mongodb.driver;bundle-version="2.6.2", + org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sailing.domain.common, com.sap.sse.common Bundle-ClassPath: lib/cglib-nodep-2.2.3.jar, diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java index d337eba26b9..e138920caad 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java @@ -84,15 +84,14 @@ public class TestLeaderboardConfiguration extends AbstractSeleniumTest { List races = table.getRaceNames(); assertThat(races.size(), equalTo(5)); - assertThat(table.getEntries().size(), equalTo(0)); - + assertThat(table.getEntries().size(), equalTo(28)); // the regatta already has the races linked; regatta leaderboard obtains competitors from regatta adminConsoleWindow.switchToWindow(); AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration(); LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString()); Integer[] expectedPointsForFindelJens = new Integer[] {2, 18, 12, 4, 7}; - Integer[] expectedRankForFindelJens = new Integer[] {3, 9, 11, 7, 6}; + Integer[] expectedRankForFindelJens = new Integer[] {2, 9, 11, 7, 6}; // Bogacki with no score in R1 expected to end up at end of leaderboard // Link the races and check the leaderboard again for (int i = 0; i < 5; i++) { diff --git a/java/com.sap.sailing.server.gateway.ess40/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.gateway.ess40/META-INF/MANIFEST.MF index b94ba1f61af..f91c2c01d96 100644 --- a/java/com.sap.sailing.server.gateway.ess40/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.gateway.ess40/META-INF/MANIFEST.MF @@ -13,7 +13,7 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.domain.tractracadapter, com.sap.sailing.domain.persistence, com.sap.sse.mongodb, - com.mongodb.driver;bundle-version="2.6.2", + org.mongodb.mongo-java-driver;bundle-version="2.13.0", javax.servlet;bundle-version="2.6.0", com.sap.sailing.domain.common, com.sap.sailing.server.gateway, diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.gateway.serialization.shared.android/META-INF/MANIFEST.MF old mode 100755 new mode 100644 diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java index dcd7490de68..84c7591ac7e 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java @@ -51,6 +51,8 @@ public class CompetitorJsonDeserializer implements JsonDeserializer } String name = (String) object.get(CompetitorJsonSerializer.FIELD_NAME); String displayColorAsString = (String) object.get(CompetitorJsonSerializer.FIELD_DISPLAY_COLOR); + String email = (String) object.get(CompetitorJsonSerializer.FIELD_EMAIL); + final Color displayColor; if (displayColorAsString == null || displayColorAsString.isEmpty()) { displayColor = null; @@ -67,7 +69,8 @@ public class CompetitorJsonDeserializer implements JsonDeserializer boat = boatJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, CompetitorJsonSerializer.FIELD_BOAT)); } - Competitor competitor = competitorStore.getOrCreateCompetitor(competitorId, name, displayColor, team, boat); + + Competitor competitor = competitorStore.getOrCreateCompetitor(competitorId, name, displayColor, email, team, boat); return competitor; } catch (Exception e) { throw new JsonDeserializationException(e); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java index 8a42dcb3b06..8f255cdddaa 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java @@ -30,6 +30,7 @@ public class CompetitorJsonSerializer implements JsonSerializer { public static final String FIELD_TEAM = "team"; public static final String FIELD_BOAT = "boat"; public static final String FIELD_DISPLAY_COLOR = "displayColor"; + public static final String FIELD_EMAIL = "email"; private final JsonSerializer teamJsonSerializer; private final JsonSerializer boatJsonSerializer; @@ -66,6 +67,7 @@ public class CompetitorJsonSerializer implements JsonSerializer { } result.put(FIELD_NAME, competitor.getName()); result.put(FIELD_DISPLAY_COLOR, competitor.getColor() == null ? null : competitor.getColor().getAsHtml()); + result.put(FIELD_EMAIL, competitor.getEmail()); result.put(FIELD_SAILID, competitor.getBoat() == null ? "" : competitor.getBoat().getSailID()); final Nationality nationality = competitor.getTeam() == null ? null : competitor.getTeam().getNationality(); result.put(FIELD_NATIONALITY, nationality == null ? "" : nationality.getThreeLetterIOCAcronym()); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index 0e35f55d5bc..1d3f145cbdf 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -237,7 +237,7 @@ public class RaceLogEventSerializerTest { public void testRegisterCompetitorEventSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. RaceLogEvent event = factory.createRegisterCompetitorEvent(null, author, 0, - DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null)); + DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null)); serializer.serialize(event); verify(registerCompetitorEventSerializer).serialize(event); } diff --git a/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF index 32c34e17f71..5a14c4424a4 100644 --- a/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF @@ -1,20 +1,20 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Gateway Serialization -Bundle-SymbolicName: com.sap.sailing.server.gateway.serialization -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.json.simple -Require-Bundle: com.sap.sailing.domain.common, - com.sap.sailing.domain.shared.android, - com.sap.sailing.domain, - net.sf.marineapi;bundle-version="0.5.0", - com.sap.sse, - com.sap.sse.common, - com.sap.sailing.server.gateway.serialization.shared.android -Export-Package: com.sap.sailing.server.gateway.deserialization.impl, - com.sap.sailing.server.gateway.serialization.impl, - com.sap.sailing.server.gateway.serialization.racelog.tracking, - com.sap.sailing.server.gateway.serialization.racelog.tracking.impl -Bundle-ActivationPolicy: lazy +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Gateway Serialization +Bundle-SymbolicName: com.sap.sailing.server.gateway.serialization +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Import-Package: org.json.simple +Require-Bundle: com.sap.sailing.domain.common, + com.sap.sailing.domain.shared.android, + com.sap.sailing.domain, + net.sf.marineapi;bundle-version="0.5.0", + com.sap.sse, + com.sap.sse.common, + com.sap.sailing.server.gateway.serialization.shared.android +Export-Package: com.sap.sailing.server.gateway.deserialization.impl, + com.sap.sailing.server.gateway.serialization.impl, + com.sap.sailing.server.gateway.serialization.racelog.tracking, + com.sap.sailing.server.gateway.serialization.racelog.tracking.impl +Bundle-ActivationPolicy: lazy diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java index 9cb04846da0..b74ad82272b 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java @@ -49,7 +49,7 @@ public class RegattaJsonSerializer implements JsonSerializer { if(competitorSerializer != null) { JSONArray competitorsJson = new JSONArray(); - for (Competitor competitor: regatta.getCompetitors()) { + for (Competitor competitor: regatta.getAllCompetitors()) { competitorsJson.add(competitorSerializer.serialize(competitor)); } result.put(FIELD_COMPETITORS, competitorsJson); diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java index 9cbc93bc25a..bc6cf71f321 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java @@ -89,11 +89,11 @@ public abstract class AbstractJsonExportTest { BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); for (int i = 1; i <= numberOfCompetitorsToCreate; i++) { String competitorName = "C" + i; - Competitor competitor = new CompetitorImpl(UUID.randomUUID(), competitorName, Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl(competitorName, new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous "+competitorName)), - new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", + Competitor competitor = new CompetitorImpl(UUID.randomUUID(), competitorName, Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl(competitorName, new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous "+competitorName)), + new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", boatClass, null)); result.add(competitor); } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/RaceLogSerializationTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/RaceLogSerializationTest.java index 27bf9672fff..9df60e2713f 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/RaceLogSerializationTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/RaceLogSerializationTest.java @@ -49,8 +49,8 @@ public class RaceLogSerializationTest { private JsonDeserializer deserializer; private final AbstractLogEventAuthor author = new LogEventAuthorImpl("test", 0); private static final Competitor competitor = new CompetitorImpl("a", "b", null, - new TeamImpl("a", Collections.singletonList(new PersonImpl("a", new NationalityImpl("GER"), new Date(), "abc")), null), - new BoatImpl("a", new BoatClassImpl("a", true), "abc")); + null, + new TeamImpl("a", Collections.singletonList(new PersonImpl("a", new NationalityImpl("GER"), new Date(), "abc")), null), new BoatImpl("a", new BoatClassImpl("a", true), "abc")); @Before public void setup() { diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java index 308954f2376..6ec2d9293be 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java @@ -70,11 +70,11 @@ public abstract class AbstractJaxRsApiTest { BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); for (int i = 1; i <= numberOfCompetitorsToCreate; i++) { String competitorName = "C" + i; - Competitor competitor = new CompetitorImpl(123, competitorName, Color.RED, new TeamImpl("STG", Collections.singleton( - new PersonImpl(competitorName, new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous "+competitorName)), - new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", + Competitor competitor = new CompetitorImpl(123, competitorName, Color.RED, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl(competitorName, new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous "+competitorName)), + new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", boatClass, null)); result.add(competitor); } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java index 43855aa01f0..4c04bd95597 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java @@ -34,7 +34,7 @@ public class CompetitorsResourceTest extends AbstractJaxRsApiTest { super.setUp(); DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl(nationality), null, null)), null); DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID); - racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, team, boat); + racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, team, boat); } @Test diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java index e5302d47c0a..29a39aed17c 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java @@ -44,8 +44,8 @@ public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest public void setUp() { super.setUp(); Competitor c = createCompetitors(1).get(0); - competitor = racingEventService.getBaseDomainFactory().getOrCreateCompetitor(c.getId(), c.getName(), c.getColor(), - (DynamicTeam) c.getTeam(), (DynamicBoat) c.getBoat()); + competitor = racingEventService.getBaseDomainFactory().getOrCreateCompetitor(c.getId(), c.getName(), + c.getColor(), c.getEmail(), (DynamicTeam) c.getTeam(), (DynamicBoat) c.getBoat()); Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), Collections.singleton(new SeriesImpl("series", false, Collections @@ -62,7 +62,7 @@ public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest LeaderboardsResource resource = spyResource(new LeaderboardsResource()); UUID deviceUuid = UUID.randomUUID(); - //checkin + // checkin long fromMillis = 500; JSONObject json = new JSONObject(); json.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitor.getId().toString()); @@ -82,22 +82,24 @@ public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest DeviceMapping mappingForC = mappingsForC.get(0); assertThat("that mapping is for the correct device", ((SmartphoneUUIDIdentifier) mappingForC.getDevice()).getUUID(), equalTo(deviceUuid)); - assertThat("that mapping starts at the correct timepoint", mappingForC.getTimeRange().from().asMillis(), equalTo(fromMillis)); + assertThat("that mapping starts at the correct timepoint", mappingForC.getTimeRange().from().asMillis(), + equalTo(fromMillis)); assertThat("that mapping is open-ended", mappingForC.getTimeRange().hasOpenEnd(), equalTo(true)); - - //checkout + + // checkout long toMillis = 1000; json = new JSONObject(); json.put(DeviceMappingConstants.JSON_TO_MILLIS, toMillis); json.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitor.getId().toString()); json.put(DeviceMappingConstants.JSON_DEVICE_UUID, deviceUuid.toString()); - + response = resource.postCheckout(json.toString(), leaderboard.getName()); assertThat("checkout returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode())); - + mappings = new DeviceCompetitorMappingFinder<>(log).analyze(); mappingForC = mappings.get(competitor).get(0); - assertThat("mapping now ends at checkout timepoint", mappingForC.getTimeRange().to().asMillis(), equalTo(toMillis)); + assertThat("mapping now ends at checkout timepoint", mappingForC.getTimeRange().to().asMillis(), + equalTo(toMillis)); } } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/TeamImageTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/TeamImageTest.java index 61576a65b08..0c6b0ccb51f 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/TeamImageTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/TeamImageTest.java @@ -54,7 +54,7 @@ public class TeamImageTest extends AbstractJaxRsApiTest { DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl( nationality), null, null)), null); DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID); - racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, team, boat); + racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, team, boat); } @Test diff --git a/java/com.sap.sailing.server.gateway/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.gateway/META-INF/MANIFEST.MF index 91c6d959b86..41fcf805f1d 100644 --- a/java/com.sap.sailing.server.gateway/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.gateway/META-INF/MANIFEST.MF @@ -1,56 +1,56 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Sailing Server Gateway -Bundle-SymbolicName: com.sap.sailing.server.gateway -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: com.sap.sailing.polars, - com.sap.sailing.polars.regression, - com.sap.sailing.polars.windestimation, - com.sap.sailing.server, - com.sap.sailing.server.operationaltransformation, - javax.ws.rs;version="1.1.1", - javax.ws.rs.core;version="1.1.1", - javax.ws.rs.ext;version="1.1.1", - org.apache.commons.lang, - org.json.simple, - org.json.simple.parser, - org.osgi.framework;version="1.3.0", - org.osgi.util.tracker;version="1.3.1" -Require-Bundle: com.sap.sailing.domain, - com.sap.sailing.expeditionconnector, - com.sap.sailing.declination, - com.sap.sailing.domain.tractracadapter, - com.sap.sailing.domain.persistence, - com.sap.sse.mongodb, - com.mongodb.driver;bundle-version="2.6.2", - javax.servlet;bundle-version="2.6.0", - com.sap.sailing.domain.common, - com.sap.sailing.udpconnector, - org.jdom;bundle-version="1.0.0", - com.sap.sailing.server.gateway.serialization, - com.sap.sailing.domain.shared.android, - com.sap.sailing.server.trackfiles, - org.eclipse.jetty.websocket.api;bundle-version="9.0.4", - org.eclipse.jetty.websocket.server;bundle-version="9.0.4", - org.eclipse.jetty.websocket.servlet;bundle-version="9.0.4", - org.eclipse.jetty.websocket.client;bundle-version="9.0.4", - org.eclipse.jetty.websocket.common;bundle-version="9.0.4", - javax.validation;bundle-version="1.0.0", - com.sun.jersey;bundle-version="1.17.0", - org.objectweb.asm;bundle-version="3.3.1", - org.apache.commons.fileupload;bundle-version="1.2.2", - com.sap.sailing.domain.igtimiadapter, - com.sap.sse.common, - com.sap.sse.replication, - com.sap.sse, - com.sap.sailing.server.gateway.serialization.shared.android, - com.sap.sse.shared.android, - com.sap.sse.filestorage, - com.sun.jersey.contribs.jersey-multipart;bundle-version="1.17.1" -Bundle-ClassPath: . -Web-ContextPath: /sailingserver -Export-Package: com.sap.sailing.server.gateway, - com.sap.sailing.server.gateway.jaxrs, - com.sap.sailing.server.gateway.jaxrs.spi +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Sailing Server Gateway +Bundle-SymbolicName: com.sap.sailing.server.gateway +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Import-Package: com.sap.sailing.polars, + com.sap.sailing.polars.regression, + com.sap.sailing.polars.windestimation, + com.sap.sailing.server, + com.sap.sailing.server.operationaltransformation, + javax.ws.rs;version="1.1.1", + javax.ws.rs.core;version="1.1.1", + javax.ws.rs.ext;version="1.1.1", + org.apache.commons.lang, + org.json.simple, + org.json.simple.parser, + org.osgi.framework;version="1.3.0", + org.osgi.util.tracker;version="1.3.1" +Require-Bundle: com.sap.sailing.domain, + com.sap.sailing.expeditionconnector, + com.sap.sailing.declination, + com.sap.sailing.domain.tractracadapter, + com.sap.sailing.domain.persistence, + com.sap.sse.mongodb, + org.mongodb.mongo-java-driver;bundle-version="2.13.0", + javax.servlet;bundle-version="2.6.0", + com.sap.sailing.domain.common, + com.sap.sailing.udpconnector, + org.jdom;bundle-version="1.0.0", + com.sap.sailing.server.gateway.serialization, + com.sap.sailing.domain.shared.android, + com.sap.sailing.server.trackfiles, + org.eclipse.jetty.websocket.api;bundle-version="9.0.4", + org.eclipse.jetty.websocket.server;bundle-version="9.0.4", + org.eclipse.jetty.websocket.servlet;bundle-version="9.0.4", + org.eclipse.jetty.websocket.client;bundle-version="9.0.4", + org.eclipse.jetty.websocket.common;bundle-version="9.0.4", + javax.validation;bundle-version="1.0.0", + com.sun.jersey;bundle-version="1.17.0", + org.objectweb.asm;bundle-version="3.3.1", + org.apache.commons.fileupload;bundle-version="1.2.2", + com.sap.sailing.domain.igtimiadapter, + com.sap.sse.common, + com.sap.sse.replication, + com.sap.sse, + com.sap.sailing.server.gateway.serialization.shared.android, + com.sap.sse.shared.android, + com.sap.sse.filestorage, + com.sun.jersey.contribs.jersey-multipart;bundle-version="1.17.1" +Bundle-ClassPath: . +Web-ContextPath: /sailingserver +Export-Package: com.sap.sailing.server.gateway, + com.sap.sailing.server.gateway.jaxrs, + com.sap.sailing.server.gateway.jaxrs.spi diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/RegattaAndRaceDataJsonGetServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/RegattaAndRaceDataJsonGetServlet.java index 6b9ff74828d..cb774ad9a47 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/RegattaAndRaceDataJsonGetServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/RegattaAndRaceDataJsonGetServlet.java @@ -372,7 +372,7 @@ public class RegattaAndRaceDataJsonGetServlet extends AbstractJsonHttpServlet { jsonEvent.put("boatclass", regatta.getBoatClass().getName()); } JSONArray jsonCompetitors = new JSONArray(); - for (Competitor competitor : regatta.getCompetitors()) { + for (Competitor competitor : regatta.getAllCompetitors()) { JSONObject jsonCompetitor = new JSONObject(); jsonCompetitor.put("name", competitor.getName()); jsonCompetitor.put("sailID", competitor.getBoat()==null?"":competitor.getBoat().getSailID()); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java index 7b864d75085..e6af41be4fc 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java @@ -144,7 +144,7 @@ public class CompetitorsResource extends AbstractSailingServerResource { .entity("Could not store competitor image").type(MediaType.TEXT_PLAIN).build()); } - getService().getCompetitorStore().updateCompetitor(competitorId, competitor.getName(), competitor.getColor(), + getService().getCompetitorStore().updateCompetitor(competitorId, competitor.getName(), competitor.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), imageUri); logger.log(Level.INFO, "Set team image for competitor " + competitor.getName()); diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamGetDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamGetDoc.html new file mode 100644 index 00000000000..8cb27f6a6b8 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamGetDoc.html @@ -0,0 +1,46 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 Beta + + +

    SAP Sailing Analytics Webservices API Version 1.0 Beta

    +

    URL: /api/v1/competitors/{id}/team

    + +Description: +

    Gets the details of a competitor's team

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:Json
    Mandatory parameters:None
    Optional parameters:None
    Request method:GET
    Example:http://www.sapsailing.com/sailingserver/api/v1/competitors/bba11294-9930-11e0-85be-406186cbf87c/team
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamImagePostDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamImagePostDoc.html new file mode 100644 index 00000000000..b94a26965db --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorTeamImagePostDoc.html @@ -0,0 +1,61 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 Beta + + +

    SAP Sailing Analytics Webservices API Version 1.0 Beta

    +

    URL: /api/v1/competitors/{id}/team/image

    + +Description: +

    Sets the team image

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:JSON
    Mandatory headers:Content-Type: (image-png|image-jpg)
     Content-Length
    Mandatory parameters:None
    Optional parameters:None
    Request method:POST (Binary data, not multipart)
    Request example:
    curl -H "Content-Type:image/jpeg" --data-binary @{image-path} \
    +   http://sapsailing.com/sailingserver/api/v1/competitors/{competitor-id}/team/image
    Response example:
    {
    +  "teamImageUri" : "http://training.sapsailing.com/team_images/9871d3a2c554b27151cacf1422eec048.jpeg"
    +}
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html index 766f399ca1a..ec818730916 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html @@ -96,6 +96,18 @@ name to make sure you get to the event you're interested in. /api/v1/leaderboards/{name} Gets the details of a leaderboard + + /api/v1/leaderboards/{name}/device_mappings/start + Tracking App Device Checkin on leaderboard + + + /api/v1/leaderboards/{name}/device_mappings/end + Tracking App Device Checkout on leaderboard + + + /api/v1/leaderboards/{name}/competitors/{id} + Gets the details of a competitor in the context of a leaderboard + /api/v1/gps_fixes Adds GPS-fixes that originated from a device with a unique identifier @@ -105,8 +117,12 @@ name to make sure you get to the event you're interested in. Gets the details of a competitor - /api/v1/leaderboards/{name}/competitors/{id} - Gets the details of a competitor in the context of a leaderboard + /api/v1/competitors/{id}/team + Gets the details of a competitor's team + + + /api/v1/competitors/{id}/team/image + Sets the team image diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckinPostDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckinPostDoc.html new file mode 100644 index 00000000000..f56526a95b3 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckinPostDoc.html @@ -0,0 +1,56 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 Beta + + +

    SAP Sailing Analytics Webservices API Version 1.0 Beta

    +

    URL: /api/v1/leaderboards/{name}/device_mappings/start

    + +Description: +

    Tracking App Device Checkin on leaderboard

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:HTTP 200 (no body)
    Mandatory parameters:None
    Optional parameters:None
    Request method:POST
    Mandatory input:JSON
     
    {
    +    "competitorId" : "af855a56-9726-4a9c-a77e-da955bd289bg",
    +    "deviceType" : "ios",
    +    "deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf",
    +    "pushDeviceId" : "0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78",
    +    "fromMillis" : 1415624564718
    +}
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckoutPostDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckoutPostDoc.html new file mode 100644 index 00000000000..8be664a81e1 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCheckoutPostDoc.html @@ -0,0 +1,54 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 Beta + + +

    SAP Sailing Analytics Webservices API Version 1.0 Beta

    +

    URL: /api/v1/leaderboards/{name}/device_mappings/end

    + +Description: +

    Tracking App Device Checkout on leaderboard

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:HTTP 200 (no body)
    Mandatory parameters:None
    Optional parameters:None
    Request method:POST
    Mandatory input:JSON
     
    {
    +    "competitorId" : "af855a56-9726-4a9c-a77e-da955bd289bg",
    +    "deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf",
    +    "toMillis" : 1415624564719
    +}
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCompetitorGetDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCompetitorGetDoc.html new file mode 100644 index 00000000000..3dbd8660aa3 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCompetitorGetDoc.html @@ -0,0 +1,46 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 Beta + + +

    SAP Sailing Analytics Webservices API Version 1.0 Beta

    +

    URL: /api/v1/leaderboards/{name}/competitors/{competitorId}

    + +Description: +

    Gets the leaderboard-specific version of a competitor

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:Json
    Mandatory parameters:None
    Optional parameters:None
    Request method:GET
    Example:http://www.sapsailing.com/sailingserver/api/v1/leaderboards/{name}/competitors/{id}
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.replication.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.replication.test/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index 87dbe7fb84c..29dcfc7528e --- a/java/com.sap.sailing.server.replication.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.replication.test/META-INF/MANIFEST.MF @@ -1,30 +1,30 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Server Replication Test -Bundle-SymbolicName: com.sap.sailing.server.replication.test -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Fragment-Host: com.sap.sse.replication -Import-Package: com.rabbitmq.client;version="2.8.4" -Require-Bundle: com.sap.sailing.server, - com.sap.sailing.domain.common, - com.sap.sailing.domain, - com.sap.sailing.domain.test, - com.sap.sse.mongodb, - com.mongodb.driver;bundle-version="2.6.2", - com.sap.sailing.domain.persistence, - com.sap.sailing.domain.tractracadapter, - com.tractrac.clientmodule;bundle-version="2.0.0", - com.sap.sailing.expeditionconnector, - com.sap.sailing.domain.swisstimingadapter, - org.json.simple;bundle-version="1.1.0", - org.junit4;bundle-version="4.8.2", - org.hamcrest;bundle-version="1.1.0", - com.sap.sailing.polars, - com.sap.sse.common, - org.mockito.mockito-core;bundle-version="1.9.5", - com.sap.sailing.domain.shared.android, - com.sap.sse.replication.testsupport, - com.sap.sse.filestorage, - com.sap.sse.shared.android +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Server Replication Test +Bundle-SymbolicName: com.sap.sailing.server.replication.test +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Fragment-Host: com.sap.sse.replication +Import-Package: com.rabbitmq.client;version="2.8.4" +Require-Bundle: com.sap.sailing.server, + com.sap.sailing.domain.common, + com.sap.sailing.domain, + com.sap.sailing.domain.test, + com.sap.sse.mongodb, + org.mongodb.mongo-java-driver;bundle-version="2.13.0", + com.sap.sailing.domain.persistence, + com.sap.sailing.domain.tractracadapter, + com.tractrac.clientmodule;bundle-version="2.0.0", + com.sap.sailing.expeditionconnector, + com.sap.sailing.domain.swisstimingadapter, + org.json.simple;bundle-version="1.1.0", + org.junit4;bundle-version="4.8.2", + org.hamcrest;bundle-version="1.1.0", + com.sap.sailing.polars, + com.sap.sse.common, + org.mockito.mockito-core;bundle-version="1.9.5", + com.sap.sailing.domain.shared.android, + com.sap.sse.replication.testsupport, + com.sap.sse.filestorage, + com.sap.sse.shared.android diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/AbstractLogReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/AbstractLogReplicationTest.java index 522b32f12a4..5d9524cd142 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/AbstractLogReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/AbstractLogReplicationTest.java @@ -21,8 +21,6 @@ import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; import com.sap.sailing.domain.common.dto.SeriesCreationParametersDTO; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.persistence.MongoObjectFactory; -import com.sap.sailing.domain.persistence.PersistenceFactory; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.server.impl.RacingEventServiceImpl; import com.sap.sailing.server.operationaltransformation.AddSpecificRegatta; @@ -37,16 +35,14 @@ public abstract class AbstractLogReplicationTest { - protected MongoDBService mongoDBService; - protected MongoObjectFactory mongoObjectFactory; +public abstract class AbstractServerReplicationTest extends com.sap.sse.replication.testsupport.AbstractServerWithSingleServiceReplicationTest { + protected ServerReplicationTestSetUp testSetUp; - /** - * Drops the test DB, if dropDB is true and requests the DB to start. - */ - @Override - protected void persistenceSetUp(boolean dropDB) { - mongoDBService = MongoDBService.INSTANCE; - if (dropDB) { - mongoDBService.getDB().dropDatabase(); + protected AbstractServerReplicationTest(ServerReplicationTestSetUp testSetUp) { + super(testSetUp); + this.testSetUp = testSetUp; + } + + public AbstractServerReplicationTest() { + super(new ServerReplicationTestSetUp()); + testSetUp = (ServerReplicationTestSetUp) super.testSetUp; + } + + protected static class ServerReplicationTestSetUp extends com.sap.sse.replication.testsupport.AbstractServerReplicationTestSetUp { + protected MongoDBService mongoDBService; + protected MongoObjectFactory mongoObjectFactory; + + /** + * Drops the test DB, if dropDB is true and requests the DB to start. + */ + @Override + protected void persistenceSetUp(boolean dropDB) { + mongoDBService = MongoDBService.INSTANCE; + if (dropDB) { + mongoDBService.getDB().dropDatabase(); + } + mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(mongoDBService); } - mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(mongoDBService); - mongoObjectFactory.getDatabase().requestStart(); - } - protected RacingEventServiceImpl createNewMaster() { - return new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(mongoDBService, - DomainFactory.INSTANCE), mongoObjectFactory, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), - EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); - } - - protected RacingEventServiceImpl createNewReplica() { - return new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(mongoDBService, - // replica gets its own base DomainFactory: - new DomainFactoryImpl()), mongoObjectFactory, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), - EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); - } + @Override + public RacingEventServiceImpl createNewMaster() { + return new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(mongoDBService, + DomainFactory.INSTANCE), mongoObjectFactory, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), + EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); + } - protected void persistenceTearDown() { - mongoObjectFactory.getDatabase().requestDone(); + @Override + public RacingEventServiceImpl createNewReplica() { + return new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(mongoDBService, + // replica gets its own base DomainFactory: + new DomainFactoryImpl()), mongoObjectFactory, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), + EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); + } } } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java index a26e7f3dbf1..0756050f030 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java @@ -76,7 +76,7 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { Iterable emptyWaypointList = Collections.emptyList(); final String competitorName = "Der mit dem Kiel zieht"; Competitor competitor = master.getBaseDomainFactory().getOrCreateCompetitor( - 123, competitorName, Color.RED, + 123, competitorName, Color.RED, "someone@nowhere.de", new TeamImpl("STG", Collections.singleton(new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), @@ -106,7 +106,7 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { // now update competitor on master using replicating operation final String newCompetitorName = "Der Vogel, der mit dem Kiel zieht"; - master.apply(new UpdateCompetitor(competitor.getId().toString(), newCompetitorName, competitor.getColor(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), + master.apply(new UpdateCompetitor(competitor.getId().toString(), newCompetitorName, competitor.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage())); Thread.sleep(1000); assertEquals(newCompetitorName, replicatedCompetitor.getName()); // expect in-place update of existing competitor in replica @@ -114,7 +114,7 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { // now allow for resetting to default through some event, such as receiving a GPS position master.apply(new AllowCompetitorResetToDefaults(Collections.singleton(competitor.getId().toString()))); // modify the competitor on the master "from below" without an UpdateCompetitor operation, only locally: - master.getBaseDomainFactory().getCompetitorStore().updateCompetitor(competitor.getId().toString(), competitorName, Color.RED, + master.getBaseDomainFactory().getCompetitorStore().updateCompetitor(competitor.getId().toString(), competitorName, Color.RED, competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage()); final RegattaAndRaceIdentifier raceIdentifier = masterRegatta.getRaceIdentifier(raceDefinition); DynamicTrackedRace trackedRace = (DynamicTrackedRace) master.apply(new CreateTrackedRace(raceIdentifier, diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/ConnectionResetAndReconnectTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/ConnectionResetAndReconnectTest.java index 30ce408fa99..170313fa30c 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/ConnectionResetAndReconnectTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/ConnectionResetAndReconnectTest.java @@ -12,7 +12,6 @@ import java.util.List; import java.util.UUID; import java.util.logging.Logger; -import org.junit.Before; import org.junit.Test; import com.rabbitmq.client.Channel; @@ -33,6 +32,10 @@ import com.sap.sse.replication.impl.ReplicationMasterDescriptorImpl; public class ConnectionResetAndReconnectTest extends AbstractServerReplicationTest { static final Logger logger = Logger.getLogger(ConnectionResetAndReconnectTest.class.getName()); + public ConnectionResetAndReconnectTest() { + super(new ServerReplicationTestSetUp()); + } + public static boolean forceStopDelivery = false; static class QueuingConsumerTest extends QueueingConsumer { @@ -81,16 +84,19 @@ public class ConnectionResetAndReconnectTest extends AbstractServerReplicationTe } - @Before - @Override - public void setUp() throws Exception { - try { - Pair, ReplicationMasterDescriptor> result = basicSetUp(/* dropDB */ true, - /* master=null means create a new one */ null, /* replica=null means create a new one */null); - masterDescriptor = MasterReplicationDescriptorMock.from(result.getB()); - } catch (Exception e) { - e.printStackTrace(); - tearDown(); + private static class ServerReplicationTestSetUp extends + com.sap.sailing.server.replication.test.AbstractServerReplicationTest.ServerReplicationTestSetUp { + @Override + public void setUp() throws Exception { + try { + Pair, ReplicationMasterDescriptor> result = basicSetUp( + /* dropDB */true, + /* master=null means create a new one */null, /* replica=null means create a new one */null); + masterDescriptor = MasterReplicationDescriptorMock.from(result.getB()); + } catch (Exception e) { + e.printStackTrace(); + tearDown(); + } } } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java index c28f2ea50e6..9bb2e1db068 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java @@ -46,6 +46,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.mongodb.MongoDBService; import com.sap.sse.replication.ReplicationMasterDescriptor; import com.sap.sse.replication.ReplicationService; +import com.sap.sse.replication.testsupport.AbstractServerReplicationTestSetUp.ReplicationServiceTestImpl; public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServerReplicationTest { private static final Logger logger = Logger.getLogger(DelayedLeaderboardCorrectionsReplicationTest.class.getName()); @@ -115,7 +116,7 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer masterLeaderboardReloaded.getRaceColumnByName(Q2), MillisecondsTimePoint.now())); // replicate the re-loaded environment - Pair, ReplicationMasterDescriptor> descriptors = basicSetUp( + Pair, ReplicationMasterDescriptor> descriptors = basicSetUp( /* dropDB */false, master, replica); replicaReplicator = descriptors.getA(); masterDescriptor = descriptors.getB(); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java index 862220bc514..a2b082373bd 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java @@ -73,9 +73,10 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.replication.ReplicationMasterDescriptor; import com.sap.sse.replication.impl.ReplicationReceiver; +import com.sap.sse.replication.testsupport.AbstractServerReplicationTestSetUp.ReplicationServiceTestImpl; public class InitialLoadReplicationObjectIdentityTest extends AbstractServerReplicationTest { - private Pair, ReplicationMasterDescriptor> replicationDescriptorPair; + private Pair, ReplicationMasterDescriptor> replicationDescriptorPair; /** * Drops the test DB. Sets up master and replica, starts the JMS message broker and registers the replica with the master. @@ -84,10 +85,10 @@ public class InitialLoadReplicationObjectIdentityTest extends AbstractServerRepl @Override public void setUp() throws Exception { persistenceSetUp(/* dropDB */ true); - this.master = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(mongoDBService, DomainFactory.INSTANCE), PersistenceFactory.INSTANCE - .getMongoObjectFactory(mongoDBService), MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); - this.replica = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(mongoDBService, DomainFactory.INSTANCE), PersistenceFactory.INSTANCE - .getMongoObjectFactory(mongoDBService), MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); + this.master = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(testSetUp.mongoDBService, DomainFactory.INSTANCE), PersistenceFactory.INSTANCE + .getMongoObjectFactory(testSetUp.mongoDBService), MediaDBFactory.INSTANCE.getMediaDB(testSetUp.mongoDBService), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); + this.replica = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(testSetUp.mongoDBService, DomainFactory.INSTANCE), PersistenceFactory.INSTANCE + .getMongoObjectFactory(testSetUp.mongoDBService), MediaDBFactory.INSTANCE.getMediaDB(testSetUp.mongoDBService), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); } private void performReplicationSetup() throws Exception { diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/PrematureOperationReceiptTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/PrematureOperationReceiptTest.java index 6e640221b30..18d90dc0e82 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/PrematureOperationReceiptTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/PrematureOperationReceiptTest.java @@ -5,7 +5,6 @@ import static org.junit.Assert.assertNull; import java.io.IOException; -import org.junit.Before; import org.junit.Test; import com.sap.sailing.domain.leaderboard.Leaderboard; @@ -17,17 +16,19 @@ import com.sap.sse.replication.ReplicationMasterDescriptor; import com.sap.sse.replication.impl.ReplicationReceiver; public class PrematureOperationReceiptTest extends AbstractServerReplicationTest { - private ReplicationReceiver replicator; + private static ReplicationReceiver replicator; + + public PrematureOperationReceiptTest() { + super(new ServerReplicationTestSetUp()); + } - /** - * Drops the test DB. Sets up master and replica, starts the JMS message broker and registers the replica with the master. - */ - @Before - @Override - public void setUp() throws Exception { - Pair, ReplicationMasterDescriptor> result = - basicSetUp(/* dropDB */ true, /* master=null means create a new one */ null, /* replica=null means create a new one */ null); - replicator = replicaReplicator.startToReplicateFromButDontYetFetchInitialLoad(result.getB(), /* startReplicatorSuspended */ true); + private static class ServerReplicationTestSetUp extends AbstractServerReplicationTest.ServerReplicationTestSetUp { + @Override + public void setUp() throws Exception { + Pair, ReplicationMasterDescriptor> result = + basicSetUp(/* dropDB */ true, /* master=null means create a new one */ null, /* replica=null means create a new one */ null); + replicator = replicaReplicator.startToReplicateFromButDontYetFetchInitialLoad(result.getB(), /* startReplicatorSuspended */ true); + } } /** diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java index 9660d8b92f3..44fb244da54 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java @@ -38,35 +38,23 @@ import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.server.RacingEventService; import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard; import com.sap.sailing.server.operationaltransformation.AddColumnToSeries; import com.sap.sailing.server.operationaltransformation.CreateRegattaLeaderboard; import com.sap.sailing.server.operationaltransformation.RenameLeaderboard; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.replication.ReplicationMasterDescriptor; public class RaceLogReplicationTest extends AbstractLogReplicationTest { - - private Pair, ReplicationMasterDescriptor> replicationDescriptorPair; private RaceLogEvent raceLogEvent; private RaceLogEvent anotherRaceLogEvent; private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1); @Before - @Override - public void setUp() throws Exception { + public void createEvents() throws Exception { raceLogEvent = RaceLogEventFactory.INSTANCE.createRaceStatusEvent(new MillisecondsTimePoint(1), author, 42, RaceLogRaceStatus.UNKNOWN); anotherRaceLogEvent = RaceLogEventFactory.INSTANCE.createRaceStatusEvent(new MillisecondsTimePoint(2), author, 42, RaceLogRaceStatus.UNKNOWN); - try { - replicationDescriptorPair = basicSetUp(/* dropDB */ true, null, null); - } catch (Exception e) { - e.printStackTrace(); - tearDown(); - } } @Test @@ -77,7 +65,7 @@ public class RaceLogReplicationTest extends AbstractLogReplicationTest { - - private Pair, ReplicationMasterDescriptor> replicationDescriptorPair; private RegattaLogEvent regattaLogEvent; // private RegattaLogEvent anotherRegattaLogEvent; @@ -37,17 +32,10 @@ public class RegattaLogReplicationTest extends } @Before - @Override - public void setUp() throws Exception { + public void createEvent() throws Exception { final Competitor competitor = TrackBasedTest.createCompetitor("Test Competitor"); regattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(0), author, t(0), 0, competitor); // anotherRegattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(1), author, t(1), 1, null); - try { - replicationDescriptorPair = basicSetUp(/* dropDB */ true, null, null); - } catch (Exception e) { - e.printStackTrace(); - tearDown(); - } } @Test @@ -57,7 +45,7 @@ public class RegattaLogReplicationTest extends final String fleetName = "Default"; Regatta regatta = setupRegatta(RegattaImpl.getDefaultName(regattaName, BOAT_CLASS_NAME_49er), seriesName, fleetName, BOAT_CLASS_NAME_49er); RegattaLog masterLog = regatta.getRegattaLog(); - replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB()); + replicaReplicator.startToReplicateFrom(masterDescriptor); RegattaLog replicaLog = getReplicaLog(regatta); addAndValidateEventIds(masterLog, replicaLog); } @@ -70,7 +58,7 @@ public class RegattaLogReplicationTest extends Regatta regatta = setupRegatta(RegattaImpl.getDefaultName(regattaName, BOAT_CLASS_NAME_49er), seriesName, fleetName, BOAT_CLASS_NAME_49er); RegattaLog masterLog = regatta.getRegattaLog(); masterLog.add(regattaLogEvent); - replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB()); + replicaReplicator.startToReplicateFrom(masterDescriptor); RegattaLog replicaLog = getReplicaLog(regatta); addAndValidateEventIds(masterLog, replicaLog); } @@ -83,7 +71,7 @@ public class RegattaLogReplicationTest extends Regatta masterRegatta = setupRegatta(RegattaImpl.getDefaultName(regattaName, BOAT_CLASS_NAME_49er), seriesName, fleetName, BOAT_CLASS_NAME_49er); RegattaLog masterLog = masterRegatta.getRegattaLog(); masterLog.add(regattaLogEvent); - replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB()); + replicaReplicator.startToReplicateFrom(masterDescriptor); RegattaLog replicaLog = getReplicaLog(masterRegatta); addAndValidateEventIds(masterLog, replicaLog, regattaLogEvent); } @@ -94,7 +82,7 @@ public class RegattaLogReplicationTest extends FlexibleLeaderboard masterLeaderboard = setupFlexibleLeaderboard(leaderboardName); RegattaLog masterLog = masterLeaderboard.getRegattaLog(); masterLog.add(regattaLogEvent); - replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB()); + replicaReplicator.startToReplicateFrom(masterDescriptor); RegattaLog replicaLog = getReplicaLog(masterLeaderboard); addAndValidateEventIds(masterLog, replicaLog, regattaLogEvent); } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java index 047ecd2589c..d045f487598 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java @@ -71,7 +71,7 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio // FIXME use master DomainFactory; see bug 592 final DomainFactory masterDomainFactory = DomainFactory.INSTANCE; BoatClass boatClass = masterDomainFactory.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */true); - competitor = masterDomainFactory.getCompetitorStore().getOrCreateCompetitor("GER 61", "Tina Lutz", Color.RED, new TeamImpl("Tina Lutz + Susann Beucke", + competitor = masterDomainFactory.getCompetitorStore().getOrCreateCompetitor("GER 61", "Tina Lutz", Color.RED, "someone@nowhere.de", new TeamImpl("Tina Lutz + Susann Beucke", (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Tina Lutz", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null), new PersonImpl("Tina Lutz", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null) }), new PersonImpl("Rigo de Mas", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), diff --git a/java/com.sap.sailing.server.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.test/META-INF/MANIFEST.MF index ae3c881fe94..108bae95913 100644 --- a/java/com.sap.sailing.server.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.test/META-INF/MANIFEST.MF @@ -14,7 +14,6 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sse.operationaltransformation, com.sap.sse.mongodb, com.tractrac.clientmodule;bundle-version="2.0.0", - com.mongodb.driver;bundle-version="2.6.2", org.hamcrest;bundle-version="1.1.0", org.junit4;bundle-version="4.8.2", com.sap.sailing.domain.test, diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/impl/MasterDataImporterMediaTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/impl/MasterDataImporterMediaTest.java index efba508d901..8e3d83e1295 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/impl/MasterDataImporterMediaTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/impl/MasterDataImporterMediaTest.java @@ -94,7 +94,7 @@ public class MasterDataImporterMediaTest { public void testImportOneTrackToEmptyTarget_WithOverride() throws Exception { createRacingEventService(); - String dbId = new ObjectId().toStringMongod(); + String dbId = new ObjectId().toHexString(); Set assignedRaces = new HashSet(); assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); MediaTrack mediaTrackToImport = new MediaTrack(dbId, "title", "url", MillisecondsTimePoint.now(), @@ -118,7 +118,7 @@ public class MasterDataImporterMediaTest { @Test public void testImportOneTrackToSameTarget_WithOverride() throws Exception { - String dbId = new ObjectId().toStringMongod(); + String dbId = new ObjectId().toHexString(); MimeType mimeType = MimeType.mp3; Set assignedRaces = new HashSet(); assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); @@ -146,7 +146,7 @@ public class MasterDataImporterMediaTest { @Test public void testImportOneTrackToExistingOtherTrack_WithOverride() throws Exception { - String dbId = new ObjectId().toStringMongod(); + String dbId = new ObjectId().toHexString(); MimeType mimeType = MimeType.mp3; Set assignedRaces = new HashSet(); assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); @@ -155,7 +155,7 @@ public class MasterDataImporterMediaTest { createRacingEventService(existingMediaTrack); - String dbId2 = new ObjectId().toStringMongod(); + String dbId2 = new ObjectId().toHexString(); MediaTrack mediaTrackToImport = new MediaTrack(dbId2, existingMediaTrack.title, existingMediaTrack.url, existingMediaTrack.startTime, existingMediaTrack.duration, mimeType, existingMediaTrack.assignedRaces); mediaTracksToImport.add(mediaTrackToImport); @@ -174,7 +174,7 @@ public class MasterDataImporterMediaTest { @Test public void testImportOneTrackToSameTargetWithChangedTitle_WithOverride() throws Exception { - String dbId = new ObjectId().toStringMongod(); + String dbId = new ObjectId().toHexString(); MimeType mimeType = MimeType.mp3; Set assignedRaces = new HashSet(); assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); @@ -205,7 +205,7 @@ public class MasterDataImporterMediaTest { @Test public void testImportOneTrackWithNullTitleToSameTargetWithTitle_WithOverride() throws Exception { - String dbId = new ObjectId().toStringMongod(); + String dbId = new ObjectId().toHexString(); MimeType mimeType = MimeType.mp3; Set assignedRaces = new HashSet(); assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); @@ -236,7 +236,7 @@ public class MasterDataImporterMediaTest { @Test public void testImportOneTrackToSameTargetWithChangedTitle_NoOverride() throws Exception { - String dbId = new ObjectId().toStringMongod(); + String dbId = new ObjectId().toHexString(); MimeType mimeType = MimeType.mp3; Set assignedRaces = new HashSet(); assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); @@ -267,7 +267,7 @@ public class MasterDataImporterMediaTest { @Test public void testImportOneTrackToSameTargetWithChangedUrl_WithOverride() throws Exception { - String dbId = new ObjectId().toStringMongod(); + String dbId = new ObjectId().toHexString(); MimeType mimeType = MimeType.mp3; Set assignedRaces = new HashSet(); assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); @@ -298,7 +298,7 @@ public class MasterDataImporterMediaTest { @Test public void testImportOneTrackToSameTargetWithChangedStarttime_WithOverride() throws Exception { - String dbId = new ObjectId().toStringMongod(); + String dbId = new ObjectId().toHexString(); MimeType mimeType = MimeType.mp3; Set assignedRaces = new HashSet(); assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); @@ -329,7 +329,7 @@ public class MasterDataImporterMediaTest { @Test public void testImportOneTrackToSameTargetWithChangedDuration_WithOverride() throws Exception { - String dbId = new ObjectId().toStringMongod(); + String dbId = new ObjectId().toHexString(); MimeType mimeType = MimeType.mp3; Set assignedRaces = new HashSet(); assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); @@ -359,7 +359,7 @@ public class MasterDataImporterMediaTest { @Test public void testImportOneTrackToSameTargetWithChangedAssignedRaces_WithOverride() throws Exception { - String dbId = new ObjectId().toStringMongod(); + String dbId = new ObjectId().toHexString(); MimeType mimeType = MimeType.mp3; Set assignedRaces = new HashSet(); assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java index e26d57c9e15..5b4a1c95bf1 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java @@ -22,20 +22,20 @@ public class CompetitorStoreTest { public void testAddingToTransientStore() { CompetitorStore transientStore = new TransientCompetitorStoreImpl(); DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); - Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getTeam(), template.getBoat()); + Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), template.getTeam(), template.getBoat()); assertTrue(competitor != template); - Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getTeam(), template.getBoat()); + Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), template.getTeam(), template.getBoat()); assertSame(competitor, competitor2); assertEquals(DomainFactory.INSTANCE.getOrCreateNationality("GER"), competitor.getTeam().getNationality()); DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana - Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), differentTeam, template.getBoat()); + Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), differentTeam, template.getBoat()); assertSame(competitor, competitor3); // use existing competitor despite the different team assertSame(competitor.getTeam(), competitor3.getTeam()); // now mark the competitor as to update from defaults transientStore.allowCompetitorResetToDefaults(competitor); - Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), differentTeam, template.getBoat()); + Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), differentTeam, template.getBoat()); assertSame(competitor, competitor4); // expecting an in-place update assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); } @@ -44,7 +44,7 @@ public class CompetitorStoreTest { public void testPersistentCompetitorStore() { CompetitorStore persistentStore1 = new PersistentCompetitorStore(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */ true, null); DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); - Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getTeam(), template.getBoat()); + Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), template.getTeam(), template.getBoat()); CompetitorStore persistentStore2 = new PersistentCompetitorStore(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */ false, null); Competitor competitor2 = persistentStore2.getExistingCompetitorById(template.getId()); @@ -53,14 +53,14 @@ public class CompetitorStoreTest { assertEquals(template.getTeam().getNationality(), competitor2.getTeam().getNationality()); DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana - Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), differentTeam, template.getBoat()); + Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), differentTeam, template.getBoat()); assertSame(competitor2, competitor3); // use existing competitor despite the different team assertNotSame(differentTeam, competitor2.getTeam()); // team expected to remain unchanged assertEquals(competitor.getTeam().getNationality(), competitor3.getTeam().getNationality()); // no updatability requested; nationality expected to remain unchanged // now mark the competitor as to update from defaults persistentStore2.allowCompetitorResetToDefaults(competitor2); - Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), differentTeam, template.getBoat()); + Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), differentTeam, template.getBoat()); assertSame(competitor2, competitor4); // expecting an in-place update assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); } diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java index df63bd3332f..fa34ead7e9e 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java @@ -61,7 +61,7 @@ public class LeaderboardStorageTest extends TestCase { DynamicBoat boat = new BoatImpl("woot", service.getBaseDomainFactory().getOrCreateBoatClass("H16"), "70155"); String competitorId = "testC"; Competitor competitor = service.getBaseDomainFactory().getOrCreateCompetitor(competitorId, "Test C", null, - team, boat); + null, team, boat); double carriedPoints = 2.0; leaderboard.setCarriedPoints(competitor, carriedPoints); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 24bdb4998e0..bbccc27371c 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -217,7 +217,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, team, boat); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, team, boat); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -227,8 +227,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, team2, - boat2); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + team2, boat2); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -298,7 +298,6 @@ public class MasterDataImportTest { inputStream = new ByteArrayInputStream(os.toByteArray()); MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); importer.importFromStream(inputStream, randomUUID, false); - db.getLastError(); // make sure the write has finished before reads are used } finally { os.close(); inputStream.close(); @@ -449,7 +448,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, team, boat); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, team, boat); competitors.add(competitor); UUID competitor2UUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -457,7 +456,7 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); - CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", Color.RED, team2, boat2); + CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", Color.RED, null, team2, boat2); competitors.add(competitor2); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -604,7 +603,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, team, boat); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, team, boat); competitors.add(competitor); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -749,7 +748,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", Color.RED, team, + Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", Color.RED, "noone@nowhere.de", team, boat); competitors.add(competitor); UUID competitor2UUID = UUID.randomUUID(); @@ -759,7 +758,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); Competitor competitor2 = sourceDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitor2UUID, - "Froderik", Color.RED, team2, boat2); + "Froderik", Color.RED, "noone@nowhere.de", team2, boat2); competitors.add(competitor2); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -905,7 +904,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, team, boat); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, team, boat); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -915,8 +914,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, team2, - boat2); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + team2, boat2); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -1104,7 +1103,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, team, boat); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, team, boat); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1114,8 +1113,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, team2, - boat2); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + team2, boat2); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -1206,7 +1205,7 @@ public class MasterDataImportTest { DynamicBoat boatToOverride = new BoatImpl("Wingy", boatClassToOverride, "GER70133"); String competitorOldName = "oldName"; Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, - Color.BLUE, teamToOverride, boatToOverride); + Color.BLUE, "noone@nowhere.de", teamToOverride, boatToOverride); competitorsToOverride.add(competitorToOverride); Leaderboard leaderboardToOverride = destService.addRegattaLeaderboard( @@ -1399,7 +1398,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, team, boat); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, team, boat); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1409,8 +1408,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, team2, - boat2); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + team2, boat2); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -1533,7 +1532,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, team, boat); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, team, boat); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1543,8 +1542,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, team2, - boat2); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + team2, boat2); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -1749,7 +1748,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, team, boat); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, team, boat); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1759,8 +1758,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, team2, - boat2); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + team2, boat2); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -1978,7 +1977,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, team, boat); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, team, boat); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1988,8 +1987,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, team2, - boat2); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + team2, boat2); competitors.add(competitorToSuppress); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java index c400a3a1df3..d9b183abd42 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java @@ -105,7 +105,7 @@ public class WindByRaceLogTest { } private Competitor createCompetitor(final DomainFactory masterDomainFactory) { - return masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", Color.RED, new TeamImpl("Sailor", + return masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", Color.RED, "noone@nowhere.de", new TeamImpl("Sailor", (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Sailor 1", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null)}), new PersonImpl("Sailor 2", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), new BoatImpl("GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61")); diff --git a/java/com.sap.sailing.server/META-INF/MANIFEST.MF b/java/com.sap.sailing.server/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index 77586cd9435..592e424d212 --- a/java/com.sap.sailing.server/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server/META-INF/MANIFEST.MF @@ -1,47 +1,47 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Sailing Server -Bundle-SymbolicName: com.sap.sailing.server -Bundle-Version: 1.0.0.qualifier -Bundle-Activator: com.sap.sailing.server.impl.Activator -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: com.sap.sailing.polars, - com.sap.sailing.polars.factory, - com.sap.sailing.server.gateway.deserialization, - org.json.simple, - org.json.simple.parser, - org.osgi.framework;version="1.3.0", - org.osgi.util.tracker;version="1.3.1" -Bundle-ActivationPolicy: lazy -Require-Bundle: com.sap.sailing.domain, - com.sap.sailing.expeditionconnector, - com.sap.sailing.declination, - com.sap.sse.mongodb, - com.mongodb.driver;bundle-version="2.6.2", - com.sap.sailing.domain.persistence, - com.sap.sailing.domain.common, - com.sap.sailing.udpconnector, - com.sap.sailing.domain.shared.android, - com.sap.sailing.server.gateway.serialization, - com.sap.sailing.polars, - com.sap.sse.common, - com.sap.sse.operationaltransformation, - com.sap.sse.replication, - com.sap.sse, - com.sap.sailing.server.gateway.serialization.shared.android, - com.sap.sse.shared.android, - com.sap.sse.filestorage -Bundle-ClassPath: . -Export-Package: com.sap.sailing.server, - com.sap.sailing.server.impl; - x-friends:="com.sap.sailing.mongodb.test, - com.sap.sailing.server.test, - com.sap.sailing.server.gateway.test, - com.sap.sailing.domain.swisstimingadapter.test, - com.sap.sailing.gwt.ui.test, - com.sap.sailing.server.replication.test, - com.sap.sailing.domain.racelogtrackingadapter.test", - com.sap.sailing.server.masterdata, - com.sap.sailing.server.operationaltransformation - +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Sailing Server +Bundle-SymbolicName: com.sap.sailing.server +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: com.sap.sailing.server.impl.Activator +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Import-Package: com.sap.sailing.polars, + com.sap.sailing.polars.factory, + com.sap.sailing.server.gateway.deserialization, + org.json.simple, + org.json.simple.parser, + org.osgi.framework;version="1.3.0", + org.osgi.util.tracker;version="1.3.1" +Bundle-ActivationPolicy: lazy +Require-Bundle: com.sap.sailing.domain, + com.sap.sailing.expeditionconnector, + com.sap.sailing.declination, + com.sap.sse.mongodb, + org.mongodb.mongo-java-driver;bundle-version="2.13.0", + com.sap.sailing.domain.persistence, + com.sap.sailing.domain.common, + com.sap.sailing.udpconnector, + com.sap.sailing.domain.shared.android, + com.sap.sailing.server.gateway.serialization, + com.sap.sailing.polars, + com.sap.sse.common, + com.sap.sse.operationaltransformation, + com.sap.sse.replication, + com.sap.sse, + com.sap.sailing.server.gateway.serialization.shared.android, + com.sap.sse.shared.android, + com.sap.sse.filestorage +Bundle-ClassPath: . +Export-Package: com.sap.sailing.server, + com.sap.sailing.server.impl; + x-friends:="com.sap.sailing.mongodb.test, + com.sap.sailing.server.test, + com.sap.sailing.server.gateway.test, + com.sap.sailing.domain.swisstimingadapter.test, + com.sap.sailing.gwt.ui.test, + com.sap.sailing.server.replication.test, + com.sap.sailing.domain.racelogtrackingadapter.test", + com.sap.sailing.server.masterdata, + com.sap.sailing.server.operationaltransformation + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy).launch b/java/com.sap.sailing.server/SailingServer (No Proxy).launch index dafc3f5acbc..8a9f6b5f5a2 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy).launch @@ -1,38 +1,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch index 77e494a85c3..ded8c572ff2 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch @@ -1,37 +1,37 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch index d930d8863f2..4a87c5dcac8 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch index b1bf39016a2..3a7fa0de9c5 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch index dffcfa6a813..254ba26fee7 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch @@ -22,10 +22,10 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch index 138ec9b55d8..723697b6c4f 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch @@ -1,30 +1,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch index 3840425304c..f14b6637666 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch @@ -29,9 +29,9 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy).launch b/java/com.sap.sailing.server/SailingServer (Proxy).launch index d11abd89b94..73c1d33df86 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy).launch @@ -30,10 +30,10 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch index 7a6ef7430b1..49611a87c36 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch b/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch index cb2904874cb..9e99a5d1946 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch @@ -1,30 +1,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch b/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch index 24ba2ffa54e..59df666c599 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch @@ -1,30 +1,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch b/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch index 2f1261d6a1c..1851792927f 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch @@ -24,10 +24,10 @@ - + - + diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java index 18fb666575d..fb46cb94e1d 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java @@ -73,7 +73,6 @@ public class Activator implements BundleActivator { context.registerService(Replicable.class.getName(), racingEventService, replicableServiceProperties); context.registerService(RacingEventService.class.getName(), racingEventService, null); context.registerService(ClearStateTestSupport.class.getName(), racingEventService, null); - Dictionary properties = new Hashtable(); properties.put(TypeBasedServiceFinder.TYPE, GPSFixImpl.class.getName()); registrations.add(context.registerService(GPSFixMongoHandler.class, diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java index 380907e07af..496bddb79ba 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java @@ -96,9 +96,9 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl } @Override - public Competitor updateCompetitor(String idAsString, String newName, Color newRgbDisplayColor, String newSailId, + public Competitor updateCompetitor(String idAsString, String newName, Color newRgbDisplayColor, String newEmail, String newSailId, Nationality newNationality, URI newTeamImageUri) { - Competitor result = super.updateCompetitor(idAsString, newName, newRgbDisplayColor, newSailId, newNationality, + Competitor result = super.updateCompetitor(idAsString, newName, newRgbDisplayColor, newEmail, newSailId, newNationality, newTeamImageUri); storeTo.storeCompetitor(result); return result; diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index 20d934eeeea..5a9c2791332 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -60,6 +60,7 @@ import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.domain.base.EventFetcher; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.LeaderboardSearchResult; import com.sap.sailing.domain.base.LeaderboardSearchResultBase; @@ -209,7 +210,7 @@ import com.sap.sse.replication.impl.OperationWithResultWithIdWrapper; import com.sap.sse.util.ClearStateTestSupport; public class RacingEventServiceImpl implements RacingEventService, ClearStateTestSupport, RegattaListener, - LeaderboardRegistry, Replicator { + LeaderboardRegistry, Replicator, EventFetcher { private static final Logger logger = Logger.getLogger(RacingEventServiceImpl.class.getName()); /** @@ -462,7 +463,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes @Override public void competitorUpdated(Competitor competitor) { replicate(new UpdateCompetitor(competitor.getId().toString(), competitor.getName(), competitor - .getColor(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), + .getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage())); } }); @@ -1789,14 +1790,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes regatta.addSeries(seriesObj); } } - for (Event event : getAllEvents()) { - event.removeRegatta(regatta); - for (CourseArea courseArea : event.getVenue().getCourseAreas()) { - if (newDefaultCourseAreaId != null && courseArea.getId().equals(newDefaultCourseAreaId)) { - event.addRegatta(regatta); - } - } - } + regatta.adjustEventToRegattaAssociation(this); if (regatta.isPersistent()) { mongoObjectFactory.storeRegatta(regatta); } @@ -2354,7 +2348,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes for (Competitor competitor : ((CompetitorStore) ois.readObject()).getCompetitors()) { DynamicCompetitor dynamicCompetitor = (DynamicCompetitor) competitor; competitorStore.getOrCreateCompetitor(dynamicCompetitor.getId(), dynamicCompetitor.getName(), - dynamicCompetitor.getColor(), dynamicCompetitor.getTeam(), dynamicCompetitor.getBoat()); + dynamicCompetitor.getColor(), dynamicCompetitor.getEmail(), dynamicCompetitor.getTeam(), dynamicCompetitor.getBoat()); } logoutput.append("Received " + competitorStore.size() + " NEW competitors\n"); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java index 3daf9b6f90a..c2e0d7d60ca 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java @@ -14,6 +14,7 @@ public class UpdateCompetitor extends AbstractRacingEventServiceOperationnull, the competitor obtains the "NONE" nationality, usually represented by a white * flag */ - public UpdateCompetitor(String idAsString, String newName, Color newDisplayColor, String newSailId, + public UpdateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail, String newSailId, Nationality newNationality, URI newTeamImageUri) { super(); this.idAsString = idAsString; @@ -33,6 +34,7 @@ public class UpdateCompetitor extends AbstractRacingEventServiceOperation + + + + + diff --git a/java/com.sap.sailing.targetplatform.base/features/target-jackson/feature.xml b/java/com.sap.sailing.targetplatform.base/features/target-jackson/feature.xml index 796b9a450bf..16263fd6bd7 100644 --- a/java/com.sap.sailing.targetplatform.base/features/target-jackson/feature.xml +++ b/java/com.sap.sailing.targetplatform.base/features/target-jackson/feature.xml @@ -47,4 +47,32 @@ version="2.5.0" unpack="false"/> + + + + + + + + diff --git a/java/com.sap.sailing.targetplatform.base/plugins/target-base/mongo-java-driver-2.13.0.jar b/java/com.sap.sailing.targetplatform.base/plugins/target-base/mongo-java-driver-2.13.0.jar new file mode 100644 index 00000000000..6555bbd36f0 Binary files /dev/null and b/java/com.sap.sailing.targetplatform.base/plugins/target-base/mongo-java-driver-2.13.0.jar differ diff --git a/java/com.sap.sailing.targetplatform.base/plugins/target-base/org.apache.servicemix.bundles.zxing-3.1.0_1.jar b/java/com.sap.sailing.targetplatform.base/plugins/target-base/org.apache.servicemix.bundles.zxing-3.1.0_1.jar new file mode 100644 index 00000000000..81fd8253c69 Binary files /dev/null and b/java/com.sap.sailing.targetplatform.base/plugins/target-base/org.apache.servicemix.bundles.zxing-3.1.0_1.jar differ diff --git a/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/README b/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/README index 8cb44f1d018..3ec8626ccc3 100644 --- a/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/README +++ b/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/README @@ -1 +1,3 @@ -bundles (already OSGi-ified) copied from http://repo1.maven.org/maven2/com/fasterxml/jackson/ +2.5.0 bundles (already OSGi-ified) copied from http://repo1.maven.org/maven2/com/fasterxml/jackson/ + +jackon 1.9.13 bundles and jettison-1.3.7 are optional [transitive] depedencies of the newer jackson bundles and com.sun.jersey \ No newline at end of file diff --git a/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jackson-core-lgpl-1.9.13.jar b/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jackson-core-lgpl-1.9.13.jar new file mode 100644 index 00000000000..df84945d9a4 Binary files /dev/null and b/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jackson-core-lgpl-1.9.13.jar differ diff --git a/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jackson-jaxrs-1.9.13.jar b/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jackson-jaxrs-1.9.13.jar new file mode 100644 index 00000000000..b85f45cf407 Binary files /dev/null and b/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jackson-jaxrs-1.9.13.jar differ diff --git a/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jackson-mapper-lgpl-1.9.13.jar b/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jackson-mapper-lgpl-1.9.13.jar new file mode 100644 index 00000000000..208e92d7d7b Binary files /dev/null and b/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jackson-mapper-lgpl-1.9.13.jar differ diff --git a/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jettison-1.3.7.jar b/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jettison-1.3.7.jar new file mode 100644 index 00000000000..56e2b019a73 Binary files /dev/null and b/java/com.sap.sailing.targetplatform.base/plugins/target-jackson/jettison-1.3.7.jar differ diff --git a/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-remote.target b/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-remote.target index 95ec6374d34..fc3bc7a06be 100755 --- a/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-remote.target +++ b/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-remote.target @@ -1,5 +1,5 @@ - + @@ -71,6 +71,10 @@ + + + + @@ -118,6 +122,7 @@ + @@ -219,6 +224,7 @@ + diff --git a/java/com.sap.sailing.targetplatform/scripts/uploadRepositoryToServer.sh b/java/com.sap.sailing.targetplatform/scripts/uploadRepositoryToServer.sh index ea28968942c..dc961e780ec 100755 --- a/java/com.sap.sailing.targetplatform/scripts/uploadRepositoryToServer.sh +++ b/java/com.sap.sailing.targetplatform/scripts/uploadRepositoryToServer.sh @@ -22,7 +22,7 @@ echo "Uploading local repository to $REPO_HOME/sailing" scp -r ../../com.sap.sailing.targetplatform.base/target/repository $USER@$SERVER:$REPO_HOME/sailing echo "Making readable for everyone..." -ssh $USER@$SERVER "chmod -R a+r $REPO_HOME/sailing/*" +ssh $USER@$SERVER "chmod -R a+r $REPO_HOME/sailing" echo "Remote files now available:" ssh $USER@$SERVER "ls -lah $REPO_HOME/sailing" diff --git a/java/com.sap.sailing.xrr.resultimport.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.xrr.resultimport.test/META-INF/MANIFEST.MF index 98d70b203e1..1d11bdf45a4 100644 --- a/java/com.sap.sailing.xrr.resultimport.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.xrr.resultimport.test/META-INF/MANIFEST.MF @@ -1,12 +1,12 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Test -Bundle-SymbolicName: com.sap.sailing.xrr.resultimport.test -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Fragment-Host: com.sap.sailing.xrr.resultimport -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: org.junit4;bundle-version="4.8.2", - com.sap.sse.common -Export-Package: com.sap.sailing.xrr.resultimport.test +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Test +Bundle-SymbolicName: com.sap.sailing.xrr.resultimport.test +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Fragment-Host: com.sap.sailing.xrr.resultimport +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.junit4;bundle-version="4.8.2", + com.sap.sse.common +Export-Package: com.sap.sailing.xrr.resultimport.test Import-Package: com.sap.sailing.xrr.schema diff --git a/java/com.sap.sailing.xrr.resultimport/META-INF/MANIFEST.MF b/java/com.sap.sailing.xrr.resultimport/META-INF/MANIFEST.MF index 490f8570201..58883e77295 100644 --- a/java/com.sap.sailing.xrr.resultimport/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.xrr.resultimport/META-INF/MANIFEST.MF @@ -1,22 +1,22 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Resultimport -Bundle-SymbolicName: com.sap.sailing.xrr.resultimport -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Export-Package: com.sap.sailing.xrr.resultimport, - com.sap.sailing.xrr.resultimport.impl -Import-Package: com.google.gwt.json.client, - com.sap.sailing.server, - com.sap.sailing.server.impl, - com.sap.sailing.server.operationaltransformation, - com.sap.sailing.xrr.schema, - org.json.simple, - org.json.simple.parser, - org.osgi.framework;version="1.6.0" -Require-Bundle: com.sap.sailing.domain, - com.sap.sailing.domain.common, - com.sap.sailing.resultimport, - com.sap.sse.common +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Resultimport +Bundle-SymbolicName: com.sap.sailing.xrr.resultimport +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Export-Package: com.sap.sailing.xrr.resultimport, + com.sap.sailing.xrr.resultimport.impl +Import-Package: com.google.gwt.json.client, + com.sap.sailing.server, + com.sap.sailing.server.impl, + com.sap.sailing.server.operationaltransformation, + com.sap.sailing.xrr.schema, + org.json.simple, + org.json.simple.parser, + org.osgi.framework;version="1.6.0" +Require-Bundle: com.sap.sailing.domain, + com.sap.sailing.domain.common, + com.sap.sailing.resultimport, + com.sap.sse.common Bundle-Activator: com.sap.sailing.xrr.resultimport.impl.Activator diff --git a/java/com.sap.sailing.xrr.schema/META-INF/MANIFEST.MF b/java/com.sap.sailing.xrr.schema/META-INF/MANIFEST.MF old mode 100755 new mode 100644 diff --git a/java/com.sap.sailing.xrr.structureimport/META-INF/MANIFEST.MF b/java/com.sap.sailing.xrr.structureimport/META-INF/MANIFEST.MF old mode 100755 new mode 100644 diff --git a/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java b/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java index c27ee51992d..e183abd1036 100755 --- a/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java +++ b/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java @@ -201,11 +201,12 @@ public class StructureImporter { String idAsString = person.getPersonID(); String name = person.getGivenName() + " " + person.getFamilyName(); Color color = null; + String email = null; Nationality nationality = (person.getNOC() == null) ? null : getNationality(person.getNOC() .toString()); BoatAndTeam boatAndTeam = getBoatAndTeam(idAsString, name, nationality, boatClass); this.baseDomainFactory.convertToCompetitorDTO(this.baseDomainFactory.getOrCreateCompetitor( - UUID.fromString(idAsString), name, color, boatAndTeam.getTeam(), boatAndTeam.getBoat())); + UUID.fromString(idAsString), name, color, email, boatAndTeam.getTeam(), boatAndTeam.getBoat())); } else { break; } diff --git a/java/com.sap.sse.common/META-INF/MANIFEST.MF b/java/com.sap.sse.common/META-INF/MANIFEST.MF index 56290d7ee65..22a6396d68e 100644 --- a/java/com.sap.sse.common/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.common/META-INF/MANIFEST.MF @@ -8,7 +8,9 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Export-Package: com.sap.sse.common, com.sap.sse.common.filter, com.sap.sse.common.impl, + com.sap.sse.common.mail, com.sap.sse.common.scalablevalue, - com.sap.sse.common.search + com.sap.sse.common.search, + com.sap.sse.common.util Require-Bundle: com.sap.sse.datamining.shared;bundle-version="1.0.0" Bundle-ActivationPolicy: lazy diff --git a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/MailException.java b/java/com.sap.sse.common/src/com/sap/sse/common/mail/MailException.java similarity index 66% rename from java/com.sap.sse.security.common/src/com/sap/sse/security/shared/MailException.java rename to java/com.sap.sse.common/src/com/sap/sse/common/mail/MailException.java index 9d3491ee00b..a52525a7784 100755 --- a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/MailException.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/mail/MailException.java @@ -1,4 +1,4 @@ -package com.sap.sse.security.shared; +package com.sap.sse.common.mail; import java.io.Serializable; @@ -10,4 +10,8 @@ public class MailException extends Exception implements Serializable { public MailException(String message) { super(message); } + + public MailException(String message, Throwable caught) { + super(message, caught); + } } diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/util/UrlHelper.java b/java/com.sap.sse.common/src/com/sap/sse/common/util/UrlHelper.java new file mode 100644 index 00000000000..0b55cf0da1c --- /dev/null +++ b/java/com.sap.sse.common/src/com/sap/sse/common/util/UrlHelper.java @@ -0,0 +1,9 @@ +package com.sap.sse.common.util; + +/** + * Context-independent interface for dealing with URLs. + * GWT context does not offer full implementations of URL/URI. * + */ +public interface UrlHelper { + String encodeUrl(String decodedUrlString); +} diff --git a/java/com.sap.sse.filestorage.test/src/com/sap/sse/filestorage/replication/test/AbstractFileStorageManagementServiceReplicationTest.java b/java/com.sap.sse.filestorage.test/src/com/sap/sse/filestorage/replication/test/AbstractFileStorageManagementServiceReplicationTest.java index be1aba6fc9a..b8e02563ed2 100755 --- a/java/com.sap.sse.filestorage.test/src/com/sap/sse/filestorage/replication/test/AbstractFileStorageManagementServiceReplicationTest.java +++ b/java/com.sap.sse.filestorage.test/src/com/sap/sse/filestorage/replication/test/AbstractFileStorageManagementServiceReplicationTest.java @@ -10,43 +10,49 @@ import com.sap.sse.filestorage.impl.EmptyFileStorageServicePropertyStoreImpl; import com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl; import com.sap.sse.filestorage.testsupport.DummyFileStorageService; import com.sap.sse.mongodb.MongoDBService; -import com.sap.sse.replication.testsupport.AbstractServerReplicationTest; +import com.sap.sse.replication.testsupport.AbstractServerWithSingleServiceReplicationTest; public abstract class AbstractFileStorageManagementServiceReplicationTest extends - AbstractServerReplicationTest { - private MongoDBService mongoDBService; + AbstractServerWithSingleServiceReplicationTest { + public AbstractFileStorageManagementServiceReplicationTest() { + super(new ServerReplicationTestSetUp()); + } - @Override - protected void persistenceSetUp(boolean dropDB) { - mongoDBService = MongoDBService.INSTANCE; - if (dropDB) { + private static class ServerReplicationTestSetUp extends com.sap.sse.replication.testsupport.AbstractServerReplicationTestSetUp { + private MongoDBService mongoDBService; + + @Override + protected void persistenceSetUp(boolean dropDB) { + mongoDBService = MongoDBService.INSTANCE; + if (dropDB) { + mongoDBService.getDB().dropDatabase(); + } + } + + protected FileStorageManagementServiceImpl createNewService() { + return new FileStorageManagementServiceImpl( + new SingleTypeBasedServiceFinderImpl<>(new DummyFileStorageService(), + DummyFileStorageService.NAME), EmptyFileStorageServicePropertyStoreImpl.INSTANCE); + } + + @Override + public FileStorageManagementServiceImpl createNewMaster() throws MalformedURLException, IOException, + InterruptedException { + FileStorageManagementServiceImpl result = createNewService(); + FileStorageService serviceOnMaster = result.getAvailableFileStorageServices()[0]; + result.setActiveFileStorageService(serviceOnMaster); + result.setFileStorageServiceProperty(serviceOnMaster, DummyFileStorageService.PROPERTY_NAME, "123"); + return result; + } + + @Override + public FileStorageManagementServiceImpl createNewReplica() { + return createNewService(); + } + + @Override + protected void persistenceTearDown() { mongoDBService.getDB().dropDatabase(); } } - - protected FileStorageManagementServiceImpl createNewService() { - return new FileStorageManagementServiceImpl( - new SingleTypeBasedServiceFinderImpl<>(new DummyFileStorageService(), - DummyFileStorageService.NAME), EmptyFileStorageServicePropertyStoreImpl.INSTANCE); - } - - @Override - protected FileStorageManagementServiceImpl createNewMaster() throws MalformedURLException, IOException, - InterruptedException { - FileStorageManagementServiceImpl result = createNewService(); - FileStorageService serviceOnMaster = result.getAvailableFileStorageServices()[0]; - result.setActiveFileStorageService(serviceOnMaster); - result.setFileStorageServiceProperty(serviceOnMaster, DummyFileStorageService.PROPERTY_NAME, "123"); - return result; - } - - @Override - protected FileStorageManagementServiceImpl createNewReplica() { - return createNewService(); - } - - @Override - protected void persistenceTearDown() { - mongoDBService.getDB().dropDatabase(); - } } diff --git a/java/com.sap.sse.filestorage/META-INF/MANIFEST.MF b/java/com.sap.sse.filestorage/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index f2d8afce059..4df238efad2 --- a/java/com.sap.sse.filestorage/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.filestorage/META-INF/MANIFEST.MF @@ -18,8 +18,8 @@ Require-Bundle: org.apache.servicemix.bundles.aws-java-sdk;bundle-version="1.9.8 org.apache.commons.logging;bundle-version="1.1.3", com.sap.sse.common, com.sap.sse.mongodb, - com.mongodb.driver;bundle-version="2.6.2", com.sap.sse.replication, com.sap.sse.operationaltransformation, com.sap.sse, - org.apache.commons.io + org.apache.commons.io, + org.mongodb.mongo-java-driver;bundle-version="2.13.0" diff --git a/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/MongoFileStorageServicePropertyStoreImpl.java b/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/MongoFileStorageServicePropertyStoreImpl.java index c38bc6a19e6..9e0988cb7d9 100644 --- a/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/MongoFileStorageServicePropertyStoreImpl.java +++ b/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/MongoFileStorageServicePropertyStoreImpl.java @@ -25,7 +25,7 @@ public class MongoFileStorageServicePropertyStoreImpl implements FileStorageServ propertiesCollection = dbService.getDB().getCollection(PROPERTIES_COLLECTION_NAME); DBObject index = new BasicDBObjectBuilder().add(FieldNames.SERVICE_NAME.name(), true) .add(FieldNames.PROPERTY_NAME.name(), true).get(); - propertiesCollection.ensureIndex(index, "unique service name/property name combination", true); + propertiesCollection.createIndex(index, "unique service name/property name combination", true); activeServiceCollection = dbService.getDB().getCollection(ACTIVE_SERVICE_COLLECTION_NAME); } diff --git a/java/com.sap.sse.gwt.adminconsole/META-INF/MANIFEST.MF b/java/com.sap.sse.gwt.adminconsole/META-INF/MANIFEST.MF old mode 100755 new mode 100644 diff --git a/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF b/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF index d62d8cf0d7b..7fbd22023b4 100644 --- a/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF @@ -5,5 +5,6 @@ Bundle-SymbolicName: com.sap.sse.gwt.test Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Require-Bundle: org.junit4;bundle-version="4.8.2" -Fragment-Host: com.sap.sse.gwt;bundle-version="1.0.0.qualifier" +Require-Bundle: com.sap.sse.gwt;bundle-version="1.0.0", + com.sap.sse.common;bundle-version="1.0.0", + org.junit4;bundle-version="4.8.2" diff --git a/java/com.sap.sse.gwt.test/build.properties b/java/com.sap.sse.gwt.test/build.properties index f11210d3f2c..0a97af7a804 100644 --- a/java/com.sap.sse.gwt.test/build.properties +++ b/java/com.sap.sse.gwt.test/build.properties @@ -2,4 +2,5 @@ source.. = src/,\ resources/ output.. = bin/ bin.includes = META-INF/,\ - . + .,\ + resources/ diff --git a/java/com.sap.sse.gwt.test/pom.xml b/java/com.sap.sse.gwt.test/pom.xml index 2d43815d42e..b22d0bb4c1c 100644 --- a/java/com.sap.sse.gwt.test/pom.xml +++ b/java/com.sap.sse.gwt.test/pom.xml @@ -9,18 +9,26 @@ com.sap.sse.gwt.test eclipse-test-plugin - + + org.apache.maven.plugins + maven-surefire-plugin + + + **/AsyncActionsExecutorTest.java + + + org.codehaus.mojo gwt-maven-plugin - 2.4.0 - - **/AsyncActionsExecutorTest.java - + ${gwt.version} + + **/AsyncActionsExecutorTest.java + test diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/IconResources.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/IconResources.java new file mode 100755 index 00000000000..dd1a3dcf9ec --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/IconResources.java @@ -0,0 +1,13 @@ +package com.sap.sse.gwt.client; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.ImageResource; + +public interface IconResources extends ClientBundle { + + public static final IconResources INSTANCE = GWT.create(IconResources.class); + + @Source("images/remove.png") + ImageResource removeIcon(); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/common/client/GenericListBox.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/GenericListBox.java similarity index 96% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/common/client/GenericListBox.java rename to java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/GenericListBox.java index 86925fdce37..621b5d494a3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/common/client/GenericListBox.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/GenericListBox.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.common.client; +package com.sap.sse.gwt.client.controls; import java.util.ArrayList; import java.util.Collection; diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/dialog/DataEntryDialog.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/dialog/DataEntryDialog.java index fdc9f4bb7fe..33d5e0caa06 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/dialog/DataEntryDialog.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/dialog/DataEntryDialog.java @@ -30,6 +30,8 @@ import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.datepicker.client.DateBox; +import com.sap.sse.gwt.client.controls.GenericListBox; +import com.sap.sse.gwt.client.controls.GenericListBox.ValueBuilder; import com.sap.sse.gwt.client.controls.IntegerBox; /** @@ -417,6 +419,21 @@ public abstract class DataEntryDialog { result.setWordWrap(false); return result; } + + public GenericListBox createGenericListBox(ValueBuilder valueBuilder, + boolean isMultipleSelect) { + GenericListBox result = new GenericListBox<>(valueBuilder); + result.setMultipleSelect(isMultipleSelect); + result.addChangeHandler(new ChangeHandler() { + @Override + public void onChange(ChangeEvent event) { + validate(); + } + }); + DialogUtils.linkEnterToButton(getOkButton(), result); + DialogUtils.linkEscapeToButton(getCancelButton(), result); + return result; + } public ListBox createListBox(boolean isMultipleSelect) { ListBox result = new ListBox(); diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/VerticalTabLayoutPanel.css b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.css similarity index 100% rename from java/com.sap.sse.gwt/src/com/sap/sse/gwt/resources/VerticalTabLayoutPanel.css rename to java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.css diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.java index c30cf12450e..c9c9a767128 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/panels/VerticalTabLayoutPanel.java @@ -175,7 +175,7 @@ public class VerticalTabLayoutPanel extends ResizeComposite implements HasWidget } interface VerticalTabLayoutPanelResources extends ClientBundle { - @Source("com/sap/sse/gwt/resources/VerticalTabLayoutPanel.css") + @Source("VerticalTabLayoutPanel.css") CssResource verticalTabPanelStyles(); } diff --git a/java/com.mongodb.driver/.classpath b/java/com.sap.sse.mail.replication.test/.classpath old mode 100644 new mode 100755 similarity index 61% rename from java/com.mongodb.driver/.classpath rename to java/com.sap.sse.mail.replication.test/.classpath index 2813f7273c1..eca7bdba8f0 --- a/java/com.mongodb.driver/.classpath +++ b/java/com.sap.sse.mail.replication.test/.classpath @@ -1,11 +1,7 @@ - - - - - - + + diff --git a/java/com.mongodb.driver/.project b/java/com.sap.sse.mail.replication.test/.project similarity index 91% rename from java/com.mongodb.driver/.project rename to java/com.sap.sse.mail.replication.test/.project index 61eea193841..51fa2fe50fb 100755 --- a/java/com.mongodb.driver/.project +++ b/java/com.sap.sse.mail.replication.test/.project @@ -1,28 +1,28 @@ - - - com.mongodb.driver - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - + + + com.sap.sse.mail.replication.test + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/java/com.mongodb.driver/.settings/org.eclipse.jdt.core.prefs b/java/com.sap.sse.mail.replication.test/.settings/org.eclipse.jdt.core.prefs old mode 100644 new mode 100755 similarity index 54% rename from java/com.mongodb.driver/.settings/org.eclipse.jdt.core.prefs rename to java/com.sap.sse.mail.replication.test/.settings/org.eclipse.jdt.core.prefs index a698e59674f..0c68a61dca8 --- a/java/com.mongodb.driver/.settings/org.eclipse.jdt.core.prefs +++ b/java/com.sap.sse.mail.replication.test/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,7 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.source=1.8 diff --git a/java/com.mongodb.driver/.settings/org.eclipse.pde.core.prefs b/java/com.sap.sse.mail.replication.test/.settings/org.eclipse.pde.core.prefs similarity index 71% rename from java/com.mongodb.driver/.settings/org.eclipse.pde.core.prefs rename to java/com.sap.sse.mail.replication.test/.settings/org.eclipse.pde.core.prefs index c1a415bd7d5..f29e940a005 100755 --- a/java/com.mongodb.driver/.settings/org.eclipse.pde.core.prefs +++ b/java/com.sap.sse.mail.replication.test/.settings/org.eclipse.pde.core.prefs @@ -1,4 +1,3 @@ -#Wed Jun 08 13:41:06 CEST 2011 -eclipse.preferences.version=1 -pluginProject.extensions=false -resolve.requirebundle=false +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/java/com.sap.sse.mail.replication.test/META-INF/MANIFEST.MF b/java/com.sap.sse.mail.replication.test/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..2757ce82521 --- /dev/null +++ b/java/com.sap.sse.mail.replication.test/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Test +Bundle-SymbolicName: com.sap.sse.mail.replication.test +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Fragment-Host: com.sap.sse.mail +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.hamcrest;bundle-version="1.1.0", + org.junit4;bundle-version="4.8.2", + com.rabbitmq.client, + com.sap.sse.replication.testsupport, + com.sap.sse.mail.replication.testsupport diff --git a/java/com.sap.sse.mail.replication.test/build.properties b/java/com.sap.sse.mail.replication.test/build.properties new file mode 100755 index 00000000000..34d2e4d2dad --- /dev/null +++ b/java/com.sap.sse.mail.replication.test/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/java/com.sap.sse.mail.replication.test/pom.xml b/java/com.sap.sse.mail.replication.test/pom.xml new file mode 100755 index 00000000000..eb287b53335 --- /dev/null +++ b/java/com.sap.sse.mail.replication.test/pom.xml @@ -0,0 +1,13 @@ + + + 4.0.0 + + root + com.sap.sailing + 1.0.0-SNAPSHOT + + com.sap.sse.mail.replication.test + eclipse-plugin + diff --git a/java/com.sap.sse.mail.replication.test/src/com/sap/sse/mail/replication/test/SimpleMailServiceReplicationTest.java b/java/com.sap.sse.mail.replication.test/src/com/sap/sse/mail/replication/test/SimpleMailServiceReplicationTest.java new file mode 100755 index 00000000000..7692ee59b1e --- /dev/null +++ b/java/com.sap.sse.mail.replication.test/src/com/sap/sse/mail/replication/test/SimpleMailServiceReplicationTest.java @@ -0,0 +1,25 @@ +package com.sap.sse.mail.replication.test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +import org.junit.Test; + +import com.sap.sse.common.mail.MailException; +import com.sap.sse.mail.replication.testsupport.AbstractMailServiceReplicationTest; + +public class SimpleMailServiceReplicationTest extends AbstractMailServiceReplicationTest { + @Test + public void testReplicationOfSendMail() throws InterruptedException, + IllegalAccessException, MailException { + master.sendMail("test@ing.me", "oh what a beatiful mail", "to be sent on this day"); + + replicaReplicator.waitUntilQueueIsEmpty(); + Thread.sleep(3000); + + assertThat("mail was not sent on replica", + AbstractMailServiceReplicationTest.numberOfMailsSent.get(replica), equalTo(null)); + assertThat("mail was sent on master", + AbstractMailServiceReplicationTest.numberOfMailsSent.get(master), equalTo(1)); + } +} diff --git a/java/com.sap.sse.mail.replication.testsupport/.classpath b/java/com.sap.sse.mail.replication.testsupport/.classpath new file mode 100755 index 00000000000..eca7bdba8f0 --- /dev/null +++ b/java/com.sap.sse.mail.replication.testsupport/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/java/com.sap.sse.mail.replication.testsupport/.project b/java/com.sap.sse.mail.replication.testsupport/.project new file mode 100755 index 00000000000..1d1e9965612 --- /dev/null +++ b/java/com.sap.sse.mail.replication.testsupport/.project @@ -0,0 +1,28 @@ + + + com.sap.sse.mail.replication.testsupport + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/java/com.sap.sse.mail.replication.testsupport/.settings/org.eclipse.jdt.core.prefs b/java/com.sap.sse.mail.replication.testsupport/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..0c68a61dca8 --- /dev/null +++ b/java/com.sap.sse.mail.replication.testsupport/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/java/com.sap.sse.mail.replication.testsupport/.settings/org.eclipse.pde.core.prefs b/java/com.sap.sse.mail.replication.testsupport/.settings/org.eclipse.pde.core.prefs new file mode 100755 index 00000000000..f29e940a005 --- /dev/null +++ b/java/com.sap.sse.mail.replication.testsupport/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/java/com.sap.sse.mail.replication.testsupport/META-INF/MANIFEST.MF b/java/com.sap.sse.mail.replication.testsupport/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..84cf686c18a --- /dev/null +++ b/java/com.sap.sse.mail.replication.testsupport/META-INF/MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Test +Bundle-SymbolicName: com.sap.sse.mail.replication.testsupport +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: com.sap.sse.replication, + com.sap.sse.replication.testsupport, + com.sap.sse.mail, + com.sap.sse, + com.sap.sse.common, + org.hamcrest;bundle-version="1.1.0", + org.junit4;bundle-version="4.8.2", + org.mockito.mockito-core;bundle-version="1.10.14", + com.sun.mail.javax.mail;bundle-version="1.4.5" +Export-Package: com.sap.sse.mail.replication.testsupport diff --git a/java/com.sap.sse.mail.replication.testsupport/build.properties b/java/com.sap.sse.mail.replication.testsupport/build.properties new file mode 100755 index 00000000000..34d2e4d2dad --- /dev/null +++ b/java/com.sap.sse.mail.replication.testsupport/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/java/com.sap.sse.mail.replication.testsupport/pom.xml b/java/com.sap.sse.mail.replication.testsupport/pom.xml new file mode 100755 index 00000000000..2ed85a10b24 --- /dev/null +++ b/java/com.sap.sse.mail.replication.testsupport/pom.xml @@ -0,0 +1,13 @@ + + + 4.0.0 + + root + com.sap.sailing + 1.0.0-SNAPSHOT + + com.sap.sse.mail.replication.testsupport + eclipse-plugin + diff --git a/java/com.sap.sse.mail.replication.testsupport/src/com/sap/sse/mail/replication/testsupport/AbstractMailServiceReplicationTest.java b/java/com.sap.sse.mail.replication.testsupport/src/com/sap/sse/mail/replication/testsupport/AbstractMailServiceReplicationTest.java new file mode 100644 index 00000000000..835afedebab --- /dev/null +++ b/java/com.sap.sse.mail.replication.testsupport/src/com/sap/sse/mail/replication/testsupport/AbstractMailServiceReplicationTest.java @@ -0,0 +1,59 @@ +package com.sap.sse.mail.replication.testsupport; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; + +import com.sap.sse.common.mail.MailException; +import com.sap.sse.mail.MailService; +import com.sap.sse.mail.impl.MailServiceImpl; +import com.sap.sse.replication.testsupport.AbstractServerReplicationTestSetUp; +import com.sap.sse.replication.testsupport.AbstractServerWithSingleServiceReplicationTest; + +public class AbstractMailServiceReplicationTest extends AbstractServerWithSingleServiceReplicationTest { + public AbstractMailServiceReplicationTest() { + super(new MailServerReplicationTestSetUp()); + } + + public static final Map numberOfMailsSent = new HashMap<>(); + + @Before + public void clearNumberOfMailsSent() { + numberOfMailsSent.clear(); + } + + public static MailServiceImpl createMailCountingService(final boolean canSendMail) { + return new MailServiceImpl(null) { + @Override + protected void internalSendMail(String toAddress, String subject, ContentSetter contentSetter) + throws MailException { + if (canSendMail) { + Integer old = numberOfMailsSent.get(this); + numberOfMailsSent.put(this, old == null ? 1 : old + 1); + } + } + }; + } + + public static class MailServerReplicationTestSetUp extends AbstractServerReplicationTestSetUp { + public MailServerReplicationTestSetUp() { + super(); + } + + public MailServerReplicationTestSetUp(int servletPort) { + super(servletPort); + } + + @Override + protected MailServiceImpl createNewMaster() throws MailException { + return createMailCountingService(true); + } + + @Override + protected MailServiceImpl createNewReplica() throws MailException { + return createMailCountingService(false); + } + } + +} diff --git a/java/com.sap.sse.mail/.classpath b/java/com.sap.sse.mail/.classpath new file mode 100755 index 00000000000..b862a296d38 --- /dev/null +++ b/java/com.sap.sse.mail/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/java/com.sap.sse.mail/.project b/java/com.sap.sse.mail/.project new file mode 100755 index 00000000000..05362453cda --- /dev/null +++ b/java/com.sap.sse.mail/.project @@ -0,0 +1,28 @@ + + + com.sap.sse.mail + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/java/com.sap.sse.mail/.settings/org.eclipse.jdt.core.prefs b/java/com.sap.sse.mail/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..295926d9641 --- /dev/null +++ b/java/com.sap.sse.mail/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/java/com.sap.sse.mail/.settings/org.eclipse.pde.core.prefs b/java/com.sap.sse.mail/.settings/org.eclipse.pde.core.prefs new file mode 100755 index 00000000000..b7e72d019c2 --- /dev/null +++ b/java/com.sap.sse.mail/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/java/com.sap.sse.mail/META-INF/MANIFEST.MF b/java/com.sap.sse.mail/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..d5aff706f24 --- /dev/null +++ b/java/com.sap.sse.mail/META-INF/MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Sse Email +Bundle-SymbolicName: com.sap.sse.mail +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-Activator: com.sap.sse.mail.impl.Activator +Export-Package: com.sap.sse.mail, + com.sap.sse.mail.impl +Import-Package: javax.mail, + javax.mail.internet, + org.osgi.framework +Require-Bundle: com.sap.sse.replication, + com.sap.sse.operationaltransformation, + com.sap.sse.common, + com.sap.sse diff --git a/java/com.sap.sse.mail/build.properties b/java/com.sap.sse.mail/build.properties new file mode 100755 index 00000000000..41eb6ade2b4 --- /dev/null +++ b/java/com.sap.sse.mail/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/java/com.mongodb.driver/pom.xml b/java/com.sap.sse.mail/pom.xml similarity index 84% rename from java/com.mongodb.driver/pom.xml rename to java/com.sap.sse.mail/pom.xml index 1d905b3f915..5d7f50f4093 100644 --- a/java/com.mongodb.driver/pom.xml +++ b/java/com.sap.sse.mail/pom.xml @@ -1,13 +1,12 @@ - - - 4.0.0 - - root - com.sap.sailing - 1.0.0-SNAPSHOT - - com.mongodb.driver - 2.6.2 - eclipse-plugin - + + + 4.0.0 + + root + com.sap.sailing + 1.0.0-SNAPSHOT + + com.sap.sse.mail + eclipse-plugin + diff --git a/java/com.sap.sse.mail/src/com/sap/sse/mail/MailOperation.java b/java/com.sap.sse.mail/src/com/sap/sse/mail/MailOperation.java new file mode 100644 index 00000000000..908e751563a --- /dev/null +++ b/java/com.sap.sse.mail/src/com/sap/sse/mail/MailOperation.java @@ -0,0 +1,15 @@ +package com.sap.sse.mail; + +import com.sap.sse.mail.impl.ReplicableMailService; +import com.sap.sse.replication.OperationWithResult; + +public interface MailOperation extends OperationWithResult { + /** + * By default, the mail-related operations will perform an update on the receiving replica that in turn + * will trigger replication of this change transitively. + */ + default boolean isRequiresExplicitTransitiveReplication() { + return false; + } + +} diff --git a/java/com.sap.sse.mail/src/com/sap/sse/mail/MailService.java b/java/com.sap.sse.mail/src/com/sap/sse/mail/MailService.java new file mode 100644 index 00000000000..06017a4c737 --- /dev/null +++ b/java/com.sap.sse.mail/src/com/sap/sse/mail/MailService.java @@ -0,0 +1,32 @@ +package com.sap.sse.mail; + +import javax.mail.Multipart; + +import com.sap.sse.common.mail.MailException; +import com.sap.sse.mail.impl.ReplicableMailService; +import com.sap.sse.replication.Replicable; +import com.sap.sse.replication.impl.ReplicableWithObjectInputStream; +import com.sap.sse.util.ClearStateTestSupport; + + +/** + * Announced via OSGi service registry. Requires {@code mail.properties} file in {@code configuration} directory + * to be correctly configured. + * + * A mail should only be sent out once by one instance. This is similar to only adding an item once to a store + * (database). Therefore - while a sendMail() operation is replicated - it is only executed by one instance, + * for now the master instance. All replicas receive an empty ({@code null}) mail configuration during + * {@link Replicable#initiallyFillFrom initial replication}, and therefore do not try to send mails themselves. + * + * @author Axel Uhl + * @author Fredrik Teschke + * + */ +public interface MailService extends ReplicableWithObjectInputStream>, ClearStateTestSupport { + void sendMail(String toAddress, String subject, String body) throws MailException; + + /** + * Send mail with multipart content (e.g. inline image). + */ + void sendMail(String toAddress, String subject, Multipart multipartContent) throws MailException; +} diff --git a/java/com.sap.sse.mail/src/com/sap/sse/mail/impl/Activator.java b/java/com.sap.sse.mail/src/com/sap/sse/mail/impl/Activator.java new file mode 100644 index 00000000000..45b6b3e46ec --- /dev/null +++ b/java/com.sap.sse.mail/src/com/sap/sse/mail/impl/Activator.java @@ -0,0 +1,56 @@ +package com.sap.sse.mail.impl; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +import com.sap.sse.mail.MailService; +import com.sap.sse.replication.Replicable; +import com.sap.sse.util.ClearStateTestSupport; + +public class Activator implements BundleActivator { + private static final Logger logger = Logger.getLogger(Activator.class.getName()); + + private ServiceRegistration registration; + + public void start(BundleContext context) throws Exception { + // Load mail properties + final String jettyHome = System.getProperty("jetty.home", "configuration"); + final File propertiesDir = new File(jettyHome).getParentFile(); + File propertiesfile = new File(propertiesDir, "mail.properties"); + Properties mailProperties = new Properties(); + try { + mailProperties.load(new FileReader(propertiesfile)); + } catch (IOException ioe) { + logger.log(Level.SEVERE, "Couldn't read mail properties from " + propertiesfile.getCanonicalPath(), ioe); + } + + MailService mailService = new MailServiceImpl(mailProperties); + registration = context.registerService(MailService.class, mailService, null); + final Dictionary replicableServiceProperties = new Hashtable<>(); + replicableServiceProperties.put(Replicable.OSGi_Service_Registry_ID_Property_Name, mailService.getId() + .toString()); + context.registerService(Replicable.class.getName(), mailService, replicableServiceProperties); + context.registerService(ClearStateTestSupport.class.getName(), mailService, null); + Logger.getLogger(Activator.class.getName()).info("Mail Service registered."); + } + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception { + registration.unregister(); + } + +} diff --git a/java/com.sap.sse.mail/src/com/sap/sse/mail/impl/MailServiceImpl.java b/java/com.sap.sse.mail/src/com/sap/sse/mail/impl/MailServiceImpl.java new file mode 100644 index 00000000000..e46bab2d984 --- /dev/null +++ b/java/com.sap.sse.mail/src/com/sap/sse/mail/impl/MailServiceImpl.java @@ -0,0 +1,226 @@ +package com.sap.sse.mail.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.mail.Message.RecipientType; +import javax.mail.MessagingException; +import javax.mail.Multipart; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; + +import com.sap.sse.common.mail.MailException; +import com.sap.sse.replication.OperationExecutionListener; +import com.sap.sse.replication.OperationWithResult; +import com.sap.sse.replication.ReplicationMasterDescriptor; +import com.sap.sse.replication.impl.OperationWithResultWithIdWrapper; + +public class MailServiceImpl implements ReplicableMailService { + private static final Logger logger = Logger.getLogger(MailServiceImpl.class.getName()); + + private Properties mailProperties; + + /** + * The master from which this replicable is currently replicating, or null if this replicable is not + * currently replicated from any master. + */ + private ReplicationMasterDescriptor replicatingFromMaster; + private final ConcurrentHashMap, OperationExecutionListener> operationExecutionListeners; + private final Set> operationsSentToMasterForReplication = new HashSet<>(); + private ThreadLocal currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster = ThreadLocal + .withInitial(() -> false); + + public MailServiceImpl(Properties mailProperties) { + this.mailProperties = mailProperties; + this.operationExecutionListeners = new ConcurrentHashMap<>(); + } + + private class SMTPAuthenticator extends javax.mail.Authenticator { + public PasswordAuthentication getPasswordAuthentication() { + String username = mailProperties.getProperty("mail.smtp.user"); + String password = mailProperties.getProperty("mail.smtp.password"); + return new PasswordAuthentication(username, password); + } + } + + protected static interface ContentSetter { + void setContent(MimeMessage msg) throws MessagingException; + } + + private boolean canSendMail() { + return mailProperties != null && mailProperties.containsKey("mail.transport.protocol"); + } + + //protected for testing purposes + protected void internalSendMail(String toAddress, String subject, ContentSetter contentSetter) throws MailException { + if (canSendMail()) { + if (toAddress != null) { + Session session = Session.getInstance(mailProperties, new SMTPAuthenticator()); + MimeMessage msg = new MimeMessage(session); + ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + try { + msg.setFrom(new InternetAddress(mailProperties.getProperty("mail.from", "root@sapsailing.com"))); + msg.setSubject(subject); + msg.addRecipient(RecipientType.TO, new InternetAddress(toAddress.trim())); + + // this fixes the DCH MIME type error + // see http://tanyamadurapperuma.blogspot.de/2014/01/struggling-with-nosuchproviderexception.html + Thread.currentThread().setContextClassLoader(javax.mail.Session.class.getClassLoader()); + + contentSetter.setContent(msg); + + // for testing with gmail + //Transport ts = session.getTransport("smtps"); + + Transport ts = session.getTransport(); + ts.connect(); + ts.sendMessage(msg, msg.getRecipients(RecipientType.TO)); + ts.close(); + logger.info("mail sent to " + toAddress + " with subject " + subject); + } catch (MessagingException e) { + logger.log(Level.SEVERE, "Error trying to send mail to " + toAddress, e); + throw new MailException(e.getMessage(), e); + } finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); + } + } + } else { + logger.warning("No mail properties provided. Cannot send e-mail about " + + subject + + " to " + + toAddress + + ". This could also mean that this is running on a replica server in which case this is perfectly fine."); + } + } + + @Override + public Void internalSendMail(String toAddress, String subject, String body) throws MailException { + internalSendMail(toAddress, subject, new ContentSetter() { + @Override + public void setContent(MimeMessage msg) throws MessagingException { + msg.setContent(body, "text/plain"); + } + }); + return null; + } + + @Override + public void sendMail(String toAddress, String subject, String body) throws MailException { + apply(s -> s.internalSendMail(toAddress, subject, body)); + } + + @Override + public Void internalSendMail(String toAddress, String subject, Multipart multipartContent) throws MailException { + internalSendMail(toAddress, subject, new ContentSetter() { + @Override + public void setContent(MimeMessage msg) throws MessagingException { + msg.setContent(multipartContent); + } + }); + return null; + } + + @Override + public void sendMail(String toAddress, String subject, Multipart multipartContent) throws MailException { + apply(s -> s.internalSendMail(toAddress, subject, multipartContent)); + } + + @Override + public void clearState() throws Exception { + // nothing to clear for test support + } + + // ----------------- Replication ------------- + @Override + public void clearReplicaState() throws MalformedURLException, IOException, InterruptedException { + // do nothing + } + + @Override + public Serializable getId() { + return getClass().getName(); + } + + @Override + public ObjectInputStream createObjectInputStreamResolvingAgainstCache(InputStream is) throws IOException { + return new ObjectInputStream(is); + } + + @Override + public void initiallyFillFromInternal(ObjectInputStream is) throws IOException, ClassNotFoundException, + InterruptedException { + // send mails only from master + mailProperties = null; + } + + @Override + public void serializeForInitialReplicationInternal(ObjectOutputStream objectOutputStream) throws IOException { + // do nothing + } + + @Override + public Iterable> getOperationExecutionListeners() { + return operationExecutionListeners.keySet(); + } + + @Override + public void addOperationExecutionListener(OperationExecutionListener listener) { + operationExecutionListeners.put(listener, listener); + } + + @Override + public void removeOperationExecutionListener(OperationExecutionListener listener) { + operationExecutionListeners.remove(listener); + } + + @Override + public ReplicationMasterDescriptor getMasterDescriptor() { + return replicatingFromMaster; + } + + @Override + public void startedReplicatingFrom(ReplicationMasterDescriptor master) { + this.replicatingFromMaster = master; + } + + @Override + public void stoppedReplicatingFrom(ReplicationMasterDescriptor master) { + this.replicatingFromMaster = null; + } + + @Override + public void addOperationSentToMasterForReplication( + OperationWithResultWithIdWrapper operationWithResultWithIdWrapper) { + this.operationsSentToMasterForReplication.add(operationWithResultWithIdWrapper); + } + + @Override + public boolean hasSentOperationToMaster(OperationWithResult operation) { + return this.operationsSentToMasterForReplication.remove(operation); + } + + @Override + public boolean isCurrentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster() { + return currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster.get(); + } + + @Override + public void setCurrentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster( + boolean currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster) { + this.currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster + .set(currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster); + } +} diff --git a/java/com.sap.sse.mail/src/com/sap/sse/mail/impl/ReplicableMailService.java b/java/com.sap.sse.mail/src/com/sap/sse/mail/impl/ReplicableMailService.java new file mode 100644 index 00000000000..116ae1f798c --- /dev/null +++ b/java/com.sap.sse.mail/src/com/sap/sse/mail/impl/ReplicableMailService.java @@ -0,0 +1,12 @@ +package com.sap.sse.mail.impl; + +import javax.mail.Multipart; + +import com.sap.sse.common.mail.MailException; +import com.sap.sse.mail.MailService; + +public interface ReplicableMailService extends MailService { + Void internalSendMail(String toAddress, String subject, String body) throws MailException; + + Void internalSendMail(String toAddress, String subject, Multipart multipartContent) throws MailException; +} diff --git a/java/com.sap.sse.mongodb/META-INF/MANIFEST.MF b/java/com.sap.sse.mongodb/META-INF/MANIFEST.MF index d12bd5a9f90..194578782aa 100644 --- a/java/com.sap.sse.mongodb/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.mongodb/META-INF/MANIFEST.MF @@ -5,8 +5,8 @@ Bundle-SymbolicName: com.sap.sse.mongodb Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: com.mongodb.driver;bundle-version="2.6.2", - com.sap.sse.common +Require-Bundle: com.sap.sse.common, + org.mongodb.mongo-java-driver;bundle-version="2.13.0" Export-Package: com.sap.sse.mongodb Bundle-ActivationPolicy: lazy Import-Package: com.sap.sailing.util, diff --git a/java/com.sap.sse.mongodb/src/com/sap/sse/mongodb/internal/MongoDBServiceImpl.java b/java/com.sap.sse.mongodb/src/com/sap/sse/mongodb/internal/MongoDBServiceImpl.java index 12bfb61bd23..1c007c60580 100644 --- a/java/com.sap.sse.mongodb/src/com/sap/sse/mongodb/internal/MongoDBServiceImpl.java +++ b/java/com.sap.sse.mongodb/src/com/sap/sse/mongodb/internal/MongoDBServiceImpl.java @@ -8,6 +8,7 @@ import java.util.logging.Logger; import com.mongodb.DB; import com.mongodb.Mongo; +import com.mongodb.MongoClient; import com.sap.sse.mongodb.AlreadyRegisteredException; import com.sap.sse.mongodb.MongoDBConfiguration; import com.sap.sse.mongodb.MongoDBService; @@ -65,7 +66,7 @@ public class MongoDBServiceImpl implements MongoDBService { if (db == null) { Mongo mongo = mongos.get(key); if (mongo == null) { - mongo = new Mongo(mongoDBConfiguration.getHostName(), mongoDBConfiguration.getPort()); + mongo = new MongoClient(mongoDBConfiguration.getHostName(), mongoDBConfiguration.getPort()); mongos.put(key, mongo); } db = mongo.getDB(mongoDBConfiguration.getDatabaseName()); diff --git a/java/com.sap.sse.replication.testsupport/META-INF/MANIFEST.MF b/java/com.sap.sse.replication.testsupport/META-INF/MANIFEST.MF old mode 100755 new mode 100644 diff --git a/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerReplicationTest.java b/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerReplicationTestSetUp.java old mode 100755 new mode 100644 similarity index 91% rename from java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerReplicationTest.java rename to java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerReplicationTestSetUp.java index 001315e97a8..912a95e821b --- a/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerReplicationTest.java +++ b/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerReplicationTestSetUp.java @@ -22,8 +22,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.GZIPOutputStream; -import org.junit.After; -import org.junit.Before; import org.junit.Rule; import org.junit.rules.Timeout; @@ -42,16 +40,26 @@ import com.sap.sse.replication.impl.ReplicationReceiver; import com.sap.sse.replication.impl.ReplicationServiceImpl; import com.sap.sse.replication.impl.SingletonReplicablesProvider; -public abstract class AbstractServerReplicationTest, ReplicableImpl extends ReplicableInterface> { - private static final Logger logger = Logger.getLogger(AbstractServerReplicationTest.class.getName()); +public abstract class AbstractServerReplicationTestSetUp, ReplicableImpl extends ReplicableInterface> { + private static final Logger logger = Logger.getLogger(AbstractServerReplicationTestSetUp.class.getName()); - protected static final int SERVLET_PORT = 9990; + protected static final int DEFAULT_SERVLET_PORT = 9990; + + private final int servletPort; protected ReplicableImpl replica; protected ReplicableImpl master; protected ReplicationServiceTestImpl replicaReplicator; private ReplicaDescriptor replicaDescriptor; private ReplicationServiceImpl masterReplicator; - protected ReplicationMasterDescriptor masterDescriptor; + protected ReplicationMasterDescriptor masterDescriptor; + + protected AbstractServerReplicationTestSetUp() { + servletPort = DEFAULT_SERVLET_PORT; + } + + protected AbstractServerReplicationTestSetUp(int servletPort) { + this.servletPort = servletPort; + } @Rule public Timeout AbstractTracTracLiveTestTimeout = new Timeout(5 * 60 * 1000); // timeout after 5 minutes private Thread initialLoadTestServerThread; @@ -64,7 +72,6 @@ public abstract class AbstractServerReplicationTest, ReplicationMasterDescriptor> result = basicSetUp( @@ -120,9 +127,9 @@ public abstract class AbstractServerReplicationTest replicaReplicator = new ReplicationServiceTestImpl(exchangeName, exchangeHost, rim, replicaDescriptor, - this.replica, this.master, masterReplicator, masterDescriptor); + this.replica, this.master, masterReplicator, masterDescriptor, servletPort); Pair, ReplicationMasterDescriptor> result = new Pair<>(replicaReplicator, masterDescriptor); logger.info("starting initial load transmission servlet for "+getClass().getName()); initialLoadTestServerThread = replicaReplicator.startInitialLoadTransmissionServlet(); @@ -136,16 +143,15 @@ public abstract class AbstractServerReplicationTest getReplicaReplicator() { + return replicaReplicator; + } + + public ReplicationMasterDescriptor getMasterDescriptor() { + return masterDescriptor; + } } diff --git a/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerWithMultipleServicesReplicationTest.java b/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerWithMultipleServicesReplicationTest.java new file mode 100644 index 00000000000..125c97f6dee --- /dev/null +++ b/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerWithMultipleServicesReplicationTest.java @@ -0,0 +1,25 @@ +package com.sap.sse.replication.testsupport; + +import java.util.HashSet; +import java.util.Set; + +import org.junit.After; +import org.junit.Before; + +public abstract class AbstractServerWithMultipleServicesReplicationTest { + protected final Set> testSetUps = new HashSet<>(); + + @Before + public void setUp() throws Exception { + for (AbstractServerReplicationTestSetUp testSetUp : testSetUps) { + testSetUp.setUp(); + } + } + + @After + public void tearDown() throws Exception { + for (AbstractServerReplicationTestSetUp testSetUp : testSetUps) { + testSetUp.tearDown(); + } + } +} diff --git a/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerWithSingleServiceReplicationTest.java b/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerWithSingleServiceReplicationTest.java new file mode 100755 index 00000000000..2e20ed3ee1c --- /dev/null +++ b/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerWithSingleServiceReplicationTest.java @@ -0,0 +1,63 @@ +package com.sap.sse.replication.testsupport; + +import java.io.IOException; + +import org.junit.After; +import org.junit.Before; + +import com.sap.sse.common.Util.Pair; +import com.sap.sse.replication.Replicable; +import com.sap.sse.replication.ReplicationMasterDescriptor; +import com.sap.sse.replication.testsupport.AbstractServerReplicationTestSetUp.ReplicationServiceTestImpl; + +public abstract class AbstractServerWithSingleServiceReplicationTest, ReplicableImpl extends ReplicableInterface> { + protected final AbstractServerReplicationTestSetUp testSetUp; + protected ReplicableImpl replica; + protected ReplicableImpl master; + protected ReplicationServiceTestImpl replicaReplicator; + protected ReplicationMasterDescriptor masterDescriptor; + + + public AbstractServerWithSingleServiceReplicationTest(AbstractServerReplicationTestSetUp testSetUp) { + this.testSetUp = testSetUp; + } + + @Before + public void setUp() throws Exception { + testSetUp.setUp(); + master = testSetUp.getMaster(); + replica = testSetUp.getReplica(); + replicaReplicator = testSetUp.getReplicaReplicator(); + masterDescriptor = testSetUp.getMasterDescriptor(); + } + + protected Pair, ReplicationMasterDescriptor> basicSetUp(boolean dropDB, + ReplicableImpl master, ReplicableImpl replica) throws Exception { + return testSetUp.basicSetUp(dropDB, master, replica); + } + + @After + public void tearDown() throws Exception { + testSetUp.tearDown(); + } + + protected ReplicableImpl createNewMaster() throws Exception { + return testSetUp.createNewMaster(); + } + + protected ReplicableImpl createNewReplica() throws Exception { + return testSetUp.createNewReplica(); + } + + protected void persistenceSetUp(boolean dropDB) { + testSetUp.persistenceSetUp(dropDB); + } + + protected void persistenceTearDown() { + testSetUp.persistenceTearDown(); + } + + public void stopReplicatingToMaster() throws IOException { + testSetUp.stopReplicatingToMaster(); + } +} diff --git a/java/com.sap.sse.security.common/META-INF/MANIFEST.MF b/java/com.sap.sse.security.common/META-INF/MANIFEST.MF old mode 100755 new mode 100644 diff --git a/java/com.sap.sse.security.replication.test/META-INF/MANIFEST.MF b/java/com.sap.sse.security.replication.test/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index 15b1ae22c52..69111890757 --- a/java/com.sap.sse.security.replication.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.security.replication.test/META-INF/MANIFEST.MF @@ -6,10 +6,14 @@ Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Fragment-Host: com.sap.sse.security Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: org.junit4;bundle-version="4.8.2", +Require-Bundle: org.hamcrest;bundle-version="1.1.0", + org.junit4;bundle-version="4.8.2", com.sap.sse.security.userstore.mongodb, com.sap.sse.mongodb, - com.mongodb.driver, com.rabbitmq.client, + org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sse.replication.testsupport, - com.sap.sse.replication.testsupport + com.sap.sse.mail.replication.testsupport, + org.objenesis;bundle-version="2.1.0", + org.mockito.mockito-core;bundle-version="1.10.14" +Import-Package: org.osgi.util.tracker;version="1.5.1" diff --git a/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/AbstractSecurityReplicationTest.java b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/AbstractSecurityReplicationTest.java index e1b5b5a94fb..97fec10c49c 100755 --- a/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/AbstractSecurityReplicationTest.java +++ b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/AbstractSecurityReplicationTest.java @@ -2,44 +2,40 @@ package com.sap.sse.security.replication.test; import java.io.IOException; import java.net.MalformedURLException; -import java.util.Properties; import com.sap.sse.mongodb.MongoDBService; -import com.sap.sse.replication.testsupport.AbstractServerReplicationTest; +import com.sap.sse.replication.testsupport.AbstractServerReplicationTestSetUp; +import com.sap.sse.replication.testsupport.AbstractServerWithSingleServiceReplicationTest; import com.sap.sse.security.SecurityService; import com.sap.sse.security.impl.SecurityServiceImpl; -import com.sap.sse.security.userstore.mongodb.MongoObjectFactory; -import com.sap.sse.security.userstore.mongodb.PersistenceFactory; import com.sap.sse.security.userstore.mongodb.UserStoreImpl; -public abstract class AbstractSecurityReplicationTest extends AbstractServerReplicationTest { - private MongoDBService mongoDBService; - private MongoObjectFactory mongoObjectFactory; +public abstract class AbstractSecurityReplicationTest extends AbstractServerWithSingleServiceReplicationTest { + public AbstractSecurityReplicationTest() { + super(new SecurityServerReplicationTestSetUp()); + } - @Override - protected void persistenceSetUp(boolean dropDB) { - mongoDBService = MongoDBService.INSTANCE; - if (dropDB) { - mongoDBService.getDB().dropDatabase(); + public static class SecurityServerReplicationTestSetUp extends AbstractServerReplicationTestSetUp { + private MongoDBService mongoDBService; + + @Override + protected void persistenceSetUp(boolean dropDB) { + mongoDBService = MongoDBService.INSTANCE; + if (dropDB) { + mongoDBService.getDB().dropDatabase(); + } } - mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(mongoDBService); - mongoObjectFactory.getDatabase().requestStart(); - } - @Override - protected SecurityServiceImpl createNewMaster() throws MalformedURLException, IOException, InterruptedException { - SecurityServiceImpl result = new SecurityServiceImpl(new UserStoreImpl(), new Properties()); - result.clearReplicaState(); - return result; - } + @Override + protected SecurityServiceImpl createNewMaster() throws MalformedURLException, IOException, InterruptedException { + SecurityServiceImpl result = new SecurityServiceImpl(new UserStoreImpl()); + result.clearReplicaState(); + return result; + } - @Override - protected SecurityServiceImpl createNewReplica() { - return new SecurityServiceImpl(new UserStoreImpl(), new Properties()); - } - - @Override - protected void persistenceTearDown() { - mongoObjectFactory.getDatabase().requestDone(); + @Override + protected SecurityServiceImpl createNewReplica() { + return new SecurityServiceImpl(new UserStoreImpl()); + } } } diff --git a/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SecurityReplicationLeadingToEmailReplicationTest.java b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SecurityReplicationLeadingToEmailReplicationTest.java new file mode 100644 index 00000000000..804ab07da17 --- /dev/null +++ b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SecurityReplicationLeadingToEmailReplicationTest.java @@ -0,0 +1,152 @@ +package com.sap.sse.security.replication.test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import java.io.IOException; +import java.net.MalformedURLException; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.osgi.util.tracker.ServiceTracker; + +import com.sap.sse.common.mail.MailException; +import com.sap.sse.mail.MailService; +import com.sap.sse.mail.impl.MailServiceImpl; +import com.sap.sse.mail.replication.testsupport.AbstractMailServiceReplicationTest; +import com.sap.sse.replication.testsupport.AbstractServerWithMultipleServicesReplicationTest; +import com.sap.sse.security.SecurityService; +import com.sap.sse.security.impl.SecurityServiceImpl; +import com.sap.sse.security.shared.UserManagementException; +import com.sap.sse.security.userstore.mongodb.UserStoreImpl; + +/** + * See if transitively triggered email operation ultimately behaves well and results in only one outbound email. + * + * @author Fredrik Teschke + */ +public class SecurityReplicationLeadingToEmailReplicationTest extends AbstractServerWithMultipleServicesReplicationTest { + private final SecurityServerReplicationTestSetUp securitySetUp = new SecurityServerReplicationTestSetUp(); + private final MailServerReplicationTestSetUp mailSetUp = new MailServerReplicationTestSetUp(); + + private MailServiceImpl masterMailService; + private MailServiceImpl replicaMailService; + + @Before + @Override + public void setUp() throws Exception { + masterMailService = AbstractMailServiceReplicationTest.createMailCountingService(true); + replicaMailService = AbstractMailServiceReplicationTest.createMailCountingService(false); + AbstractMailServiceReplicationTest.numberOfMailsSent.clear(); + super.setUp(); + } + + private class SecurityServerReplicationTestSetUp extends + AbstractSecurityReplicationTest.SecurityServerReplicationTestSetUp { + @Override + protected SecurityServiceImpl createNewMaster() throws MalformedURLException, IOException, InterruptedException { + @SuppressWarnings("unchecked") + ServiceTracker trackerMock = mock(ServiceTracker.class); + doReturn(masterMailService).when(trackerMock).getService(); + SecurityServiceImpl result = new SecurityServiceImpl(trackerMock, new UserStoreImpl()); + result.clearReplicaState(); + return result; + } + + @Override + protected SecurityServiceImpl createNewReplica() { + @SuppressWarnings("unchecked") + ServiceTracker trackerMock = mock(ServiceTracker.class); + doReturn(replicaMailService).when(trackerMock).getService(); + SecurityServiceImpl result = new SecurityServiceImpl(trackerMock, new UserStoreImpl()); + return result; + } + } + + private class MailServerReplicationTestSetUp extends AbstractMailServiceReplicationTest.MailServerReplicationTestSetUp { + private static final int SERVLET_PORT = 9991; + + public MailServerReplicationTestSetUp() { + super(SERVLET_PORT); + } + + @Override + protected MailServiceImpl createNewMaster() throws MailException { + return masterMailService; + } + + @Override + protected MailServiceImpl createNewReplica() throws MailException { + return replicaMailService; + } + } + + public SecurityReplicationLeadingToEmailReplicationTest() { + testSetUps.add(securitySetUp); + testSetUps.add(mailSetUp); + } + + /** + * See if sending an email (triggered by creating the user on the master) results in only one mail being sent + * (on the master). + */ + @Test + public void triggerEmailSendByAddingUserOnMaster() + throws UserManagementException, MailException, IllegalAccessException, InterruptedException { + //TODO IllegalStateExceptions thrown, probably because the two replication services per instance share the + //same message queue, but don't know about each other (unlike actual OSGi setup, where there is only + //one replication service per instance that nows all Replicables) + SecurityService masterSecurityService = securitySetUp.getMaster(); + + final String username = "Ernie"; + final String email = "ernie@sesame-street.com"; + final String password = "BertMyFriend"; + final String validationBaseURL = null; //so that validation email is not sent + + masterSecurityService.createSimpleUser(username, email, password, validationBaseURL); + + masterSecurityService.sendMail(username, "subject", "body"); + + securitySetUp.getReplicaReplicator().waitUntilQueueIsEmpty(); + mailSetUp.getReplicaReplicator().waitUntilQueueIsEmpty(); + Thread.sleep(3000); + + assertThat("mail was not sent on replica", + AbstractMailServiceReplicationTest.numberOfMailsSent.get(replicaMailService), equalTo(null)); + assertThat("mail was sent on master", + AbstractMailServiceReplicationTest.numberOfMailsSent.get(masterMailService), equalTo(1)); + } + + + /** + * Try the other way round - have to ignore for now, no replication test seems to try applying + * operations on the replica. + */ + @Test + @Ignore + public void triggerEmailSendByAddingUserOnReplica() + throws UserManagementException, MailException, IllegalAccessException, InterruptedException { + SecurityService replicaSecurityService = securitySetUp.getReplica(); + + final String username = "Ernie"; + final String email = "ernie@sesame-street.com"; + final String password = "BertMyFriend"; + final String validationBaseURL = null; //so that validation email is not sent + + replicaSecurityService.createSimpleUser(username, email, password, validationBaseURL); + + replicaSecurityService.sendMail(username, "subject", "body"); + + securitySetUp.getReplicaReplicator().waitUntilQueueIsEmpty(); + mailSetUp.getReplicaReplicator().waitUntilQueueIsEmpty(); + Thread.sleep(3000); + + assertThat("mail was not sent on replica", + AbstractMailServiceReplicationTest.numberOfMailsSent.get(replicaMailService), equalTo(null)); + assertThat("mail was sent on master", + AbstractMailServiceReplicationTest.numberOfMailsSent.get(masterMailService), equalTo(1)); + } +} diff --git a/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SimpleSecurityReplicationTest.java b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SimpleSecurityReplicationTest.java index 439018643f9..08b962910ce 100755 --- a/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SimpleSecurityReplicationTest.java +++ b/java/com.sap.sse.security.replication.test/src/com/sap/sse/security/replication/test/SimpleSecurityReplicationTest.java @@ -9,8 +9,8 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; +import com.sap.sse.common.mail.MailException; import com.sap.sse.security.User; -import com.sap.sse.security.shared.MailException; import com.sap.sse.security.shared.UserManagementException; public class SimpleSecurityReplicationTest extends AbstractSecurityReplicationTest { diff --git a/java/com.sap.sse.security.test/META-INF/MANIFEST.MF b/java/com.sap.sse.security.test/META-INF/MANIFEST.MF old mode 100644 new mode 100755 index a1f9525f9a2..c6c6aa543bc --- a/java/com.sap.sse.security.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.security.test/META-INF/MANIFEST.MF @@ -8,5 +8,7 @@ Fragment-Host: com.sap.sse.security Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.junit4;bundle-version="4.8.2", com.sap.sse.security.userstore.mongodb, - com.mongodb.driver, - com.sap.sse.mongodb + org.mongodb.mongo-java-driver;bundle-version="2.13.0", + com.sap.sse.mongodb, + com.sap.sse.mail +Import-Package: org.apache.shiro.session.mgt diff --git a/java/com.sap.sse.security.test/src/com/sap/sse/security/test/LoginTest.java b/java/com.sap.sse.security.test/src/com/sap/sse/security/test/LoginTest.java old mode 100644 new mode 100755 index 71d9f9da6f1..9229f35686b --- a/java/com.sap.sse.security.test/src/com/sap/sse/security/test/LoginTest.java +++ b/java/com.sap.sse.security.test/src/com/sap/sse/security/test/LoginTest.java @@ -6,7 +6,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.net.UnknownHostException; -import java.util.Properties; import org.apache.shiro.SecurityUtils; import org.junit.Before; @@ -40,7 +39,7 @@ public class LoginTest { UsernamePasswordRealm.setTestUserStore(store); Activator.setTestUserStore(store); Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); // to enable shiro to find classes from com.sap.sse.security - new SecurityServiceImpl(store, /* mailProperties */ new Properties()); + Activator.setSecurityService(new SecurityServiceImpl(store)); } @Test diff --git a/java/com.sap.sse.security.test/src/com/sap/sse/security/test/SecurityResourceTest.java b/java/com.sap.sse.security.test/src/com/sap/sse/security/test/SecurityResourceTest.java new file mode 100755 index 00000000000..02cf08f4080 --- /dev/null +++ b/java/com.sap.sse.security.test/src/com/sap/sse/security/test/SecurityResourceTest.java @@ -0,0 +1,83 @@ +package com.sap.sse.security.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import javax.ws.rs.core.Response; + +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import com.sap.sse.common.mail.MailException; +import com.sap.sse.security.SecurityService; +import com.sap.sse.security.UsernamePasswordRealm; +import com.sap.sse.security.impl.Activator; +import com.sap.sse.security.impl.SecurityServiceImpl; +import com.sap.sse.security.jaxrs.api.SecurityResource; +import com.sap.sse.security.shared.UserManagementException; +import com.sap.sse.security.userstore.mongodb.PersistenceFactory; +import com.sap.sse.security.userstore.mongodb.UserStoreImpl; + +public class SecurityResourceTest { + private SecurityResource servlet; + private SecurityServiceImpl service; + + @Before + public void setUp() throws UserManagementException, MailException { + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().getDatabase().dropDatabase(); + final UserStoreImpl store = new UserStoreImpl(); + Activator.setTestUserStore(store); + UsernamePasswordRealm.setTestUserStore(store); + service = new SecurityServiceImpl(/* mailServiceTracker */ null, + store, /* setAsActivatorSecurityService */ true); + SecurityUtils.setSecurityManager(service.getSecurityManager()); + Session session = SecurityUtils.getSubject().getSession(); + assertNotNull(session); + servlet = new SecurityResource() { + @Override + public SecurityService getService() { + return service; + } + }; + store.addPermissionForUser("admin", "can do"); + store.addPermissionForUser("admin", "event:view:*"); + store.addPermissionForUser("admin", "event:edit:123"); + } + + private String createAccessToken() throws ParseException { + String responseJsonString = (String) servlet.accessToken("admin", "admin").getEntity(); + JSONObject responseJson = (JSONObject) new JSONParser().parse(responseJsonString); + assertEquals("admin", responseJson.get("username")); + String accessToken = (String) responseJson.get("access_token"); + assertNotNull(accessToken); + return accessToken; + } + + @Ignore("Ignore on master until we've found out what the problem with unloadable UsernameAndPasswordRealm is") + @Test + public void createAccessTokenAndAuthenticate() throws ParseException { + String accessToken = createAccessToken(); + Response response = servlet.authenticate(accessToken); + JSONObject responseJson = (JSONObject) new JSONParser().parse((String) response.getEntity()); + assertEquals("admin", responseJson.get("username")); + final Subject subject = SecurityUtils.getSubject(); + assertTrue(subject.isAuthenticated()); + assertEquals("admin", subject.getPrincipal()); + assertTrue(subject.isPermitted("can do")); + assertFalse(subject.isPermitted("can't do")); + assertTrue(subject.isPermitted("event:view:999")); + assertTrue(subject.isPermitted("event:edit:123")); + assertFalse(subject.isPermitted("event:edit:234")); + subject.logout(); + assertFalse(subject.isAuthenticated()); + } +} diff --git a/java/com.sap.sse.security.ui/META-INF/MANIFEST.MF b/java/com.sap.sse.security.ui/META-INF/MANIFEST.MF index 347baaf4407..fb55d40f181 100644 --- a/java/com.sap.sse.security.ui/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.security.ui/META-INF/MANIFEST.MF @@ -21,7 +21,8 @@ Require-Bundle: javax.servlet;bundle-version="2.5.0", org.apache.shiro.core;bundle-version="1.2.2", org.apache.shiro.web;bundle-version="1.2.2", com.sap.sse.replication, - com.sap.sse.security.common + com.sap.sse.security.common, + com.sap.sse.mail Web-ContextPath: /security/ui Export-Package: com.sap.sse.security.ui.client, com.sap.sse.security.ui.client.component, diff --git a/java/com.sap.sse.security.ui/Security UI sdm.launch b/java/com.sap.sse.security.ui/Security UI sdm.launch old mode 100644 new mode 100755 index c74715a12d6..7750b7dbad8 --- a/java/com.sap.sse.security.ui/Security UI sdm.launch +++ b/java/com.sap.sse.security.ui/Security UI sdm.launch @@ -1,49 +1,49 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/IconResources.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/IconResources.java index 489510d0ea0..2e82d56e3bd 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/IconResources.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/IconResources.java @@ -8,36 +8,33 @@ public interface IconResources extends ClientBundle { public static final IconResources INSTANCE = GWT.create(IconResources.class); - @Source("com/sap/sse/security/ui/images/logo.png") + @Source("images/logo.png") ImageResource sapLogo(); - @Source("com/sap/sse/security/ui/images/user.png") + @Source("images/user.png") ImageResource user(); - @Source("com/sap/sse/security/ui/images/user_small.png") + @Source("images/user_small.png") ImageResource userSmall(); - @Source("com/sap/sse/security/ui/images/user_icon.png") + @Source("images/user_icon.png") ImageResource userIcon(); - @Source("com/sap/sse/security/ui/images/status_red.png") + @Source("images/status_red.png") ImageResource statusRed(); - @Source("com/sap/sse/security/ui/images/status_green.png") + @Source("images/status_green.png") ImageResource statusGreen(); - @Source("com/sap/sse/security/ui/images/status_yellow.png") + @Source("images/status_yellow.png") ImageResource statusYellow(); - @Source("com/sap/sse/security/ui/images/status_blue.png") + @Source("images/status_blue.png") ImageResource statusBlue(); - @Source("com/sap/sse/security/ui/images/status_grey.png") + @Source("images/status_grey.png") ImageResource statusGrey(); - @Source("com/sap/sse/security/ui/images/delete.png") + @Source("images/delete.png") ImageResource delete(); - - @Source("com/sap/sse/gwt/client/images/remove.png") - ImageResource remove(); } diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementService.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementService.java index 6ae80791520..01a4f952a44 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementService.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementService.java @@ -4,8 +4,8 @@ import java.util.Collection; import java.util.Map; import com.google.gwt.user.client.rpc.RemoteService; +import com.sap.sse.common.mail.MailException; import com.sap.sse.security.shared.DefaultRoles; -import com.sap.sse.security.shared.MailException; import com.sap.sse.security.shared.UserManagementException; import com.sap.sse.security.ui.oauth.client.CredentialDTO; import com.sap.sse.security.ui.oauth.shared.OAuthException; diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserDetailsView.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserDetailsView.java index 839ca489f9d..6ee94c0fe1e 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserDetailsView.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/component/UserDetailsView.java @@ -66,7 +66,7 @@ public class UserDetailsView extends FlowPanel { for (DefaultPermissions defaultPermission : DefaultPermissions.values()) { defaultPermissionNames.add(defaultPermission.getPermissionname()); } - rolesEditor = new StringListEditorComposite(user==null?Collections.emptySet():user.getRoles(), stringMessages, IconResources.INSTANCE.remove(), defaultRoleNames, + rolesEditor = new StringListEditorComposite(user==null?Collections.emptySet():user.getRoles(), stringMessages, com.sap.sse.gwt.client.IconResources.INSTANCE.removeIcon(), defaultRoleNames, stringMessages.enterRoleName()); rolesEditor.addValueChangeHandler(new ValueChangeHandler>() { @Override @@ -95,7 +95,7 @@ public class UserDetailsView extends FlowPanel { })); } }); - permissionsEditor = new StringListEditorComposite(user==null?Collections.emptySet():user.getPermissions(), stringMessages, IconResources.INSTANCE.remove(), defaultPermissionNames, + permissionsEditor = new StringListEditorComposite(user==null?Collections.emptySet():user.getPermissions(), stringMessages, com.sap.sse.gwt.client.IconResources.INSTANCE.removeIcon(), defaultPermissionNames, stringMessages.enterPermissionName()); permissionsEditor.addValueChangeHandler(new ValueChangeHandler>() { @Override diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java index a04ae8a236d..31ef0aa6901 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java @@ -27,6 +27,7 @@ import org.osgi.util.tracker.ServiceTracker; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.sap.sailing.domain.common.impl.NaturalComparator; import com.sap.sse.common.Util; +import com.sap.sse.common.mail.MailException; import com.sap.sse.security.Credential; import com.sap.sse.security.SecurityService; import com.sap.sse.security.SessionUtils; @@ -35,7 +36,6 @@ import com.sap.sse.security.User; import com.sap.sse.security.shared.Account; import com.sap.sse.security.shared.Account.AccountType; import com.sap.sse.security.shared.DefaultRoles; -import com.sap.sse.security.shared.MailException; import com.sap.sse.security.shared.SocialUserAccount; import com.sap.sse.security.shared.UserManagementException; import com.sap.sse.security.shared.UsernamePasswordAccount; diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/delete.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/delete.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/delete.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/delete.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/logo.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/logo.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/logo.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/logo.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_blue.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_blue.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_blue.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_blue.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_green.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_green.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_green.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_green.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_grey.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_grey.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_grey.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_grey.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_red.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_red.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_red.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_red.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_yellow.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_yellow.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/status_yellow.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/status_yellow.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user_icon.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user_icon.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user_icon.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user_icon.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user_small.png b/java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user_small.png similarity index 100% rename from java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/images/user_small.png rename to java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/client/images/user_small.png diff --git a/java/com.sap.sse.security.ui/src/main/resources/shiro.ini b/java/com.sap.sse.security.ui/src/main/resources/shiro.ini index 8e7d14f8c4b..06ec02bbf2f 100755 --- a/java/com.sap.sse.security.ui/src/main/resources/shiro.ini +++ b/java/com.sap.sse.security.ui/src/main/resources/shiro.ini @@ -6,10 +6,10 @@ credentialsMatcher.hashIterations = 1024 upRealm = com.sap.sse.security.UsernamePasswordRealm upRealm.credentialsMatcher = $credentialsMatcher - oauthRealm = com.sap.sse.security.OAuthRealm +accessTokenRealm = com.sap.sse.security.AccessTokenRealm -securityManager.realms = $upRealm, $oauthRealm +securityManager.realms = $upRealm, $oauthRealm, $accessTokenRealm sessionManager = com.sap.sse.security.SecurityWebSessionManager securityManager.sessionManager = $sessionManager diff --git a/java/com.sap.sse.security.userstore.mongodb/META-INF/MANIFEST.MF b/java/com.sap.sse.security.userstore.mongodb/META-INF/MANIFEST.MF index 142723bcd75..12b89a6475f 100644 --- a/java/com.sap.sse.security.userstore.mongodb/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.security.userstore.mongodb/META-INF/MANIFEST.MF @@ -10,7 +10,7 @@ Import-Package: org.osgi.framework;version="1.3.0" Bundle-ActivationPolicy: lazy Bundle-ClassPath: . Require-Bundle: com.sap.sse.security, - com.mongodb.driver;bundle-version="2.6.2", + org.mongodb.mongo-java-driver;bundle-version="2.13.0", org.apache.shiro.core;bundle-version="1.2.2", com.sap.sse.mongodb, com.sap.sse.common, diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/DomainObjectFactory.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/DomainObjectFactory.java index 59f4cf7a7ed..29ecf730a5d 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/DomainObjectFactory.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/DomainObjectFactory.java @@ -15,4 +15,5 @@ public interface DomainObjectFactory { User loadUser(String name); Map> loadPreferences(); + } diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java index 46c3a062db5..28deb3c062f 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java @@ -29,13 +29,20 @@ public class UserStoreImpl implements UserStore { private static final Logger logger = Logger.getLogger(UserStoreImpl.class.getName()); + private static final String ACCESS_TOKEN_KEY = "___access_token___"; + private String name = "MongoDB user store"; private final ConcurrentHashMap users; private final ConcurrentHashMap> usersByEmail; + private final ConcurrentHashMap usersByAccessToken; private final ConcurrentHashMap emailForUsername; private final ConcurrentHashMap settings; private final ConcurrentHashMap> settingTypes; + + /** + * Keys are the usernames, values are the key/value pairs representing the user's preferences + */ private final ConcurrentHashMap> preferences; /** @@ -48,7 +55,8 @@ public class UserStoreImpl implements UserStore { usersByEmail = new ConcurrentHashMap<>(); emailForUsername = new ConcurrentHashMap<>(); settings = new ConcurrentHashMap<>(); - settingTypes = new ConcurrentHashMap>(); + settingTypes = new ConcurrentHashMap<>(); + usersByAccessToken = new ConcurrentHashMap<>(); preferences = new ConcurrentHashMap<>(); final DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(); mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(); @@ -101,6 +109,29 @@ public class UserStoreImpl implements UserStore { } } + @Override + public boolean setAccessToken(String username, String accessToken) { + final boolean result; + final User user = getUserByName(username); + if (user == null) { + result = false; + } else { + result = true; + usersByAccessToken.put(accessToken, user); + setPreference(username, ACCESS_TOKEN_KEY, accessToken); + } + return result; + } + + @Override + public void removeAccessToken(String username, String accessToken) { + User user = usersByAccessToken.remove(accessToken); + if (user != null) { + // the access token actually existed; now we need to update the preferences + unsetPreference(username, ACCESS_TOKEN_KEY); + } + } + private void addToUsersByEmail(User u) { if (u.getEmail() != null && !u.getEmail().isEmpty()) { Set set = usersByEmail.get(u.getEmail()); @@ -175,10 +206,24 @@ public class UserStoreImpl implements UserStore { @Override public User getUserByName(String name) { + final User result; if (name == null) { - return null; + result = null; + } else { + result = users.get(name); } - return users.get(name); + return result; + } + + @Override + public User getUserByAccessToken(String accessToken) { + final User result; + if (accessToken == null) { + result = null; + } else { + result = usersByAccessToken.get(accessToken); + } + return result; } @Override diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/DomainObjectFactoryImpl.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/DomainObjectFactoryImpl.java index 147863f9173..9f6ef354951 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/DomainObjectFactoryImpl.java @@ -33,18 +33,16 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { @Override public Iterable loadAllUsers() { - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); DBCollection userCollection = db.getCollection(CollectionNames.USERS.name()); - try { for (DBObject o : userCollection.find()) { result.add(loadUser(o)); } } catch (Exception e) { - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load events."); - logger.log(Level.SEVERE, "loadAllEvents", e); + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load users."); + logger.log(Level.SEVERE, "loadAllUsers", e); } - return result; } diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java index 53e1fadb6d8..41ebcee5c8f 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java @@ -33,7 +33,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void storeUser(User user) { DBCollection usersCollection = db.getCollection(CollectionNames.USERS.name()); - usersCollection.ensureIndex(FieldNames.User.NAME.name()); + usersCollection.createIndex(new BasicDBObject(FieldNames.User.NAME.name(), null)); DBObject dbUser = new BasicDBObject(); DBObject query = new BasicDBObject(FieldNames.User.NAME.name(), user.getName()); dbUser.put(FieldNames.User.NAME.name(), user.getName()); @@ -46,13 +46,12 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { dbUser.put(FieldNames.User.PERMISSIONS.name(), user.getPermissions()); usersCollection.update(query, dbUser, /* upsrt */true, /* multi */false, WriteConcern.SAFE); } - + @Override public void deleteUser(User user) { DBCollection usersCollection = db.getCollection(CollectionNames.USERS.name()); DBObject dbUser = new BasicDBObject(); dbUser.put(FieldNames.User.NAME.name(), user.getName()); - usersCollection.remove(dbUser); } @@ -84,7 +83,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void storeSettings(Map settings) { DBCollection settingCollection = db.getCollection(CollectionNames.SETTINGS.name()); - settingCollection.ensureIndex(FieldNames.Settings.NAME.name()); + settingCollection.createIndex(new BasicDBObject(FieldNames.Settings.NAME.name(), null)); DBObject dbSettings = new BasicDBObject(); DBObject query = new BasicDBObject(FieldNames.Settings.NAME.name(), FieldNames.Settings.VALUES.name()); dbSettings.put(FieldNames.Settings.NAME.name(), FieldNames.Settings.VALUES.name()); @@ -96,7 +95,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void storePreferences(String username, Map userMap) { DBCollection settingCollection = db.getCollection(CollectionNames.PREFERENCES.name()); - settingCollection.ensureIndex(FieldNames.Preferences.USERNAME.name()); + settingCollection.createIndex(new BasicDBObject(FieldNames.Preferences.USERNAME.name(), null)); BasicDBList dbSettings = new BasicDBList(); for (Entry e : userMap.entrySet()) { DBObject entry = new BasicDBObject(); @@ -113,7 +112,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void storeSettingTypes(Map> settingTypes) { DBCollection settingCollection = db.getCollection(CollectionNames.SETTINGS.name()); - settingCollection.ensureIndex(FieldNames.Settings.NAME.name()); + settingCollection.createIndex(new BasicDBObject(FieldNames.Settings.NAME.name(), null)); DBObject dbSettingTypes = new BasicDBObject(); DBObject query = new BasicDBObject(FieldNames.Settings.NAME.name(), FieldNames.Settings.TYPES.name()); dbSettingTypes.put(FieldNames.Settings.NAME.name(), FieldNames.Settings.TYPES.name()); diff --git a/java/com.sap.sse.security/META-INF/MANIFEST.MF b/java/com.sap.sse.security/META-INF/MANIFEST.MF index 524101252cc..d7c272be079 100644 --- a/java/com.sap.sse.security/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.security/META-INF/MANIFEST.MF @@ -6,11 +6,13 @@ Bundle-Version: 1.0.0.qualifier Bundle-Activator: com.sap.sse.security.impl.Activator Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: javax.mail;version="1.4.0", +Import-Package: com.sap.sse.util, + javax.mail;version="1.4.0", javax.mail.internet;version="1.4.0", javax.ws.rs;version="1.1.1", javax.ws.rs.core;version="1.1.1", javax.ws.rs.ext;version="1.1.1", + org.codehaus.jackson.jaxrs;version="1.9.13", org.osgi.framework;version="1.3.0", org.osgi.util.tracker;version="1.5.1" Bundle-ActivationPolicy: lazy @@ -31,6 +33,7 @@ Require-Bundle: javax.servlet;bundle-version="2.5.0", com.sap.sse.replication, com.sap.sse.operationaltransformation, com.sap.sse.security.common, - com.sap.sse + com.sap.sse, + com.sap.sse.mail Web-ContextPath: /security Export-Package: com.sap.sse.security diff --git a/java/com.sap.sse.security/resources/shiro.ini b/java/com.sap.sse.security/resources/shiro.ini index d751a822a12..0be28cb3e39 100644 --- a/java/com.sap.sse.security/resources/shiro.ini +++ b/java/com.sap.sse.security/resources/shiro.ini @@ -9,10 +9,10 @@ credentialsMatcher.hashIterations = 1024 upRealm = com.sap.sse.security.UsernamePasswordRealm upRealm.credentialsMatcher = $credentialsMatcher - oauthRealm = com.sap.sse.security.OAuthRealm +accessTokenRealm = com.sap.sse.security.AccessTokenRealm -securityManager.realms = $upRealm, $oauthRealm +securityManager.realms = $upRealm, $oauthRealm, $accessTokenRealm sessionManager = com.sap.sse.security.SecurityWebSessionManager securityManager.sessionManager = $sessionManager diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/AccessToken.java b/java/com.sap.sse.security/src/com/sap/sse/security/AccessToken.java new file mode 100755 index 00000000000..bacf4debc85 --- /dev/null +++ b/java/com.sap.sse.security/src/com/sap/sse/security/AccessToken.java @@ -0,0 +1,35 @@ +package com.sap.sse.security; + +import org.apache.shiro.authc.AuthenticationToken; + +import com.sap.sse.security.impl.Activator; + +/** + * An access token as issued by {@link SecurityService#createAccessToken(String)}. The user name which is returned + * by {@link #getPrincipal()} is obtained by looking up the access token using the {@link SecurityService}. + * + * @author Axel Uhl (D043530) + * + */ +public class AccessToken implements AuthenticationToken { + private static final long serialVersionUID = 8528031991813216585L; + private final String accessToken; + + public AccessToken(String accessToken) { + super(); + this.accessToken = accessToken; + } + + @Override + public Object getPrincipal() { + SecurityService securityService = Activator.getSecurityService(); + User user = securityService.getUserByAccessToken(accessToken); + return user == null ? null : user.getName(); + } + + @Override + public String getCredentials() { + return accessToken; + } + +} diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/AccessTokenRealm.java b/java/com.sap.sse.security/src/com/sap/sse/security/AccessTokenRealm.java new file mode 100755 index 00000000000..c920f0f7b80 --- /dev/null +++ b/java/com.sap.sse.security/src/com/sap/sse/security/AccessTokenRealm.java @@ -0,0 +1,38 @@ +package com.sap.sse.security; + +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.SaltedAuthenticationInfo; + +/** + * A realm that authenticates users by an access token which has previously been obtained through + * {@link SecurityService#createAccessToken(String)}. + * + * @author Axel Uhl (D043530) + * + */ +public class AccessTokenRealm extends AbstractUserStoreBasedRealm { + + public AccessTokenRealm() { + super(); + } + + @Override + public boolean supports(AuthenticationToken token) { + return token instanceof AccessToken; + } + + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + AccessToken accessToken = (AccessToken) token; + final User user = getUserStore().getUserByAccessToken(accessToken.getCredentials()); + if (user == null) { + return null; + } + // return salted credentials + SaltedAuthenticationInfo sai = new SimpleSaltedAuthenticationInfo(user.getName(), accessToken.getCredentials(), /* salt */ null); + return sai; + } + +} diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java b/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java index b3840233f21..c04bab7bfef 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java @@ -8,11 +8,11 @@ import javax.servlet.ServletContext; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.mgt.SecurityManager; +import com.sap.sse.common.mail.MailException; import com.sap.sse.replication.impl.ReplicableWithObjectInputStream; import com.sap.sse.security.impl.ReplicableSecurityService; import com.sap.sse.security.operations.SecurityOperation; import com.sap.sse.security.shared.DefaultRoles; -import com.sap.sse.security.shared.MailException; import com.sap.sse.security.shared.SocialUserAccount; import com.sap.sse.security.shared.UserManagementException; @@ -139,4 +139,24 @@ public interface SecurityService extends ReplicableWithObjectInputStreamusername can be + * authenticated using the token. Any access token previously created for same user will be invalidated by this + * call. + * + * @return a new access token if username identifies a known user, null otherwise + */ + String createAccessToken(String username); + + /** + * Looks up a user by an access token that was created before using {@link #createAccessToken(String)} for same user name. + * + * @return null in case the access token is unknown or was deleted / invalidated + */ + User getUserByAccessToken(String accessToken); + + void removeAccessToken(String username, String accessToken); + + User loginByAccessToken(String accessToken); + } diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/SimpleSaltedAuthenticationInfo.java b/java/com.sap.sse.security/src/com/sap/sse/security/SimpleSaltedAuthenticationInfo.java index a8b8fff5a0f..79b2b428079 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/SimpleSaltedAuthenticationInfo.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/SimpleSaltedAuthenticationInfo.java @@ -9,12 +9,12 @@ import org.apache.shiro.util.SimpleByteSource; public class SimpleSaltedAuthenticationInfo implements SaltedAuthenticationInfo { private static final long serialVersionUID = -8423637970683173260L; private String username; - private String password; + private String saltedPassword; private byte[] salt; - public SimpleSaltedAuthenticationInfo(String username, String password, byte[] salt) { + public SimpleSaltedAuthenticationInfo(String username, String saltedPassword, byte[] salt) { this.username = username; - this.password = password; + this.saltedPassword = saltedPassword; this.salt = salt; } @@ -26,7 +26,7 @@ public class SimpleSaltedAuthenticationInfo implements SaltedAuthenticationInfo @Override public Object getCredentials() { - return password; + return saltedPassword; } @Override diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/UserStore.java b/java/com.sap.sse.security/src/com/sap/sse/security/UserStore.java index 4dd17e4947f..f0ad1f20670 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/UserStore.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/UserStore.java @@ -13,6 +13,8 @@ public interface UserStore extends Named { User getUserByName(String name); User getUserByEmail(String email); + + User getUserByAccessToken(String accessToken); User createUser(String name, String email, Account... accounts) throws UserManagementException; @@ -87,4 +89,14 @@ public interface UserStore extends Named { */ void replaceContentsFrom(UserStore newUserStore); + /** + * Stores an access token that can be used to authenticate the user identified by username. + * If there is no user by that name, calling this method has no effect and it will return false. + * + * @return whether a user could be identified by username + */ + boolean setAccessToken(String username, String accessToken); + + void removeAccessToken(String username, String accessToken); + } diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/impl/Activator.java b/java/com.sap.sse.security/src/com/sap/sse/security/impl/Activator.java old mode 100644 new mode 100755 index f8c54dfdbe5..a4e6375a4e3 --- a/java/com.sap.sse.security/src/com/sap/sse/security/impl/Activator.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/impl/Activator.java @@ -1,11 +1,7 @@ package com.sap.sse.security.impl; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; import java.util.Dictionary; import java.util.Hashtable; -import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; @@ -14,11 +10,13 @@ import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import org.osgi.util.tracker.ServiceTracker; +import com.sap.sse.mail.MailService; import com.sap.sse.replication.Replicable; import com.sap.sse.security.SecurityService; import com.sap.sse.security.UserStore; import com.sap.sse.security.UsernamePasswordRealm; import com.sap.sse.util.ClearStateTestSupport; +import com.sap.sse.util.ServiceTrackerFactory; public class Activator implements BundleActivator { private static final Logger logger = Logger.getLogger(Activator.class.getName()); @@ -42,6 +40,10 @@ public class Activator implements BundleActivator { UsernamePasswordRealm.setTestUserStore(theTestUserStore); } + public static void setSecurityService(SecurityService securityService) { + Activator.securityService = securityService; + } + public static BundleContext getContext() { return context; } @@ -57,25 +59,16 @@ public class Activator implements BundleActivator { * registered as an OSGi service. */ public void start(BundleContext bundleContext) throws Exception { - // Load mail properties - final String jettyHome = System.getProperty("jetty.home", "configuration"); - final File propertiesDir = new File(jettyHome).getParentFile(); - File propertiesfile = new File(propertiesDir, "security.properties"); - Properties mailProperties = new Properties(); - try { - mailProperties.load(new FileReader(propertiesfile)); - } catch (IOException ioe) { - logger.log(Level.SEVERE, "Couldn't read security properties from "+propertiesfile.getCanonicalPath(), ioe); - } + context = bundleContext; if (testUserStore != null) { - createAndRegisterSecurityService(testUserStore, mailProperties); + createAndRegisterSecurityService(bundleContext, testUserStore); } else { - waitForUserStoreService(bundleContext, mailProperties); + waitForUserStoreService(bundleContext); } } - private void createAndRegisterSecurityService(UserStore store, Properties mailProperties) { - securityService = new SecurityServiceImpl(store, mailProperties); + private void createAndRegisterSecurityService(BundleContext bundleContext, UserStore store) { + securityService = new SecurityServiceImpl(ServiceTrackerFactory.createAndOpen(context, MailService.class), store, /* setAsActivatorSecurityService */ true); registration = context.registerService(SecurityService.class.getName(), securityService, null); final Dictionary replicableServiceProperties = new Hashtable<>(); @@ -85,7 +78,7 @@ public class Activator implements BundleActivator { Logger.getLogger(Activator.class.getName()).info("Security Service registered."); } - private void waitForUserStoreService(BundleContext bundleContext, final Properties mailProperties) { + private void waitForUserStoreService(BundleContext bundleContext) { context = bundleContext; final ServiceTracker tracker = new ServiceTracker<>(bundleContext, UserStore.class, /* customizer */ null); tracker.open(); @@ -97,7 +90,7 @@ public class Activator implements BundleActivator { logger.info("Waiting for UserStore service..."); UserStore userStore = tracker.waitForService(0); logger.info("Obtained UserStore service "+userStore); - createAndRegisterSecurityService(userStore, mailProperties); + createAndRegisterSecurityService(bundleContext, userStore); } catch (InterruptedException e) { logger.log(Level.SEVERE, "Interrupted while waiting for UserStore service", e); } diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/impl/ReplicableSecurityService.java b/java/com.sap.sse.security/src/com/sap/sse/security/impl/ReplicableSecurityService.java index e248a93c404..b51e3094c1c 100755 --- a/java/com.sap.sse.security/src/com/sap/sse/security/impl/ReplicableSecurityService.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/impl/ReplicableSecurityService.java @@ -19,6 +19,10 @@ public interface ReplicableSecurityService extends SecurityService { Void internalSetPreference(String username, String key, String value); Void internalUnsetPreference(String username, String key); + + Void internalSetAccessToken(String username, String accessToken); + + Void internalRemoveAccessToken(String username, String accessToken); Boolean internalSetSetting(String key, Object setting); diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java b/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java old mode 100644 new mode 100755 index db50118e4bc..830403f7b44 --- a/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java @@ -13,20 +13,12 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; -import java.util.Properties; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; -import javax.mail.Message.RecipientType; -import javax.mail.MessagingException; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; import javax.servlet.Filter; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; @@ -54,6 +46,7 @@ import org.apache.shiro.web.filter.mgt.FilterChainResolver; import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver; import org.apache.shiro.web.util.SavedRequest; import org.apache.shiro.web.util.WebUtils; +import org.osgi.util.tracker.ServiceTracker; import org.scribe.builder.ServiceBuilder; import org.scribe.builder.api.FacebookApi; import org.scribe.builder.api.FlickrApi; @@ -71,10 +64,13 @@ import org.scribe.oauth.OAuthService; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.sap.sse.common.Util; +import com.sap.sse.common.mail.MailException; +import com.sap.sse.mail.MailService; import com.sap.sse.replication.OperationExecutionListener; import com.sap.sse.replication.OperationWithResult; import com.sap.sse.replication.ReplicationMasterDescriptor; import com.sap.sse.replication.impl.OperationWithResultWithIdWrapper; +import com.sap.sse.security.AccessToken; import com.sap.sse.security.ClientUtils; import com.sap.sse.security.Credential; import com.sap.sse.security.GithubApi; @@ -89,7 +85,6 @@ import com.sap.sse.security.User; import com.sap.sse.security.UserStore; import com.sap.sse.security.shared.Account.AccountType; import com.sap.sse.security.shared.DefaultRoles; -import com.sap.sse.security.shared.MailException; import com.sap.sse.security.shared.SocialUserAccount; import com.sap.sse.security.shared.UserManagementException; import com.sap.sse.security.shared.UsernamePasswordAccount; @@ -111,7 +106,7 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica private final ReplicatingCacheManager cacheManager; private UserStore store; - private final Properties mailProperties; + private final ServiceTracker mailServiceTracker; private final ConcurrentHashMap, OperationExecutionListener> operationExecutionListeners; /** @@ -129,18 +124,37 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica shiroConfiguration = new Ini(); shiroConfiguration.loadFromPath("classpath:shiro.ini"); } + + public SecurityServiceImpl(UserStore store) { + this(null, store); + } /** * @param mailProperties must not be null */ - public SecurityServiceImpl(UserStore store, Properties mailProperties) { - assert mailProperties != null; - logger.info("Initializing Security Service with user store " + store+" and mail properties "+mailProperties); + public SecurityServiceImpl(ServiceTracker mailServiceTracker, UserStore store) { + this(mailServiceTracker, store, /* setAsActivatorTestSecurityService */ false); + } + + /** + * @param setAsActivatorSecurityService + * when true, the {@link Activator#setSecurityService(com.sap.sse.security.SecurityService)} + * will be called with this new instance as argument so that the cache manager can already be accessed + * when the security manager is created. {@link ReplicatingCacheManager#getCache(String)} fetches the + * activator's security service and passes it to the cache entries created. They need it, in turn, for + * replication. + * + */ + public SecurityServiceImpl(ServiceTracker mailServiceTracker, UserStore store, boolean setAsActivatorSecurityService) { + logger.info("Initializing Security Service with user store " + store); + if (setAsActivatorSecurityService) { + Activator.setSecurityService(this); + } operationsSentToMasterForReplication = new HashSet<>(); cacheManager = new ReplicatingCacheManager(); this.operationExecutionListeners = new ConcurrentHashMap<>(); this.store = store; - this.mailProperties = mailProperties; + this.mailServiceTracker = mailServiceTracker; // Create default users if no users exist yet. initEmptyStore(); Factory factory = new WebIniSecurityManagerFactory(shiroConfiguration); @@ -188,45 +202,24 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica } } } - - private class SMTPAuthenticator extends javax.mail.Authenticator { - public PasswordAuthentication getPasswordAuthentication() { - String username = mailProperties.getProperty("mail.smtp.user"); - String password = mailProperties.getProperty("mail.smtp.password"); - return new PasswordAuthentication(username, password); - } + + private MailService getMailService() { + return mailServiceTracker == null ? null : mailServiceTracker.getService(); } @Override public void sendMail(String username, String subject, String body) throws MailException { - if (this.mailProperties != null && this.mailProperties.containsKey("mail.transport.protocol")) { - final User user = getUserByName(username); - if (user != null) { - final String toAddress = user.getEmail(); - if (toAddress != null) { - Session session = Session.getInstance(this.mailProperties, new SMTPAuthenticator()); - MimeMessage msg = new MimeMessage(session); - try { - msg.setFrom(new InternetAddress(mailProperties.getProperty("mail.from", "root@sapsailing.com"))); - msg.setSubject(subject); - msg.setContent(body, "text/plain"); - msg.addRecipient(RecipientType.TO, new InternetAddress(toAddress.trim())); - Transport ts = session.getTransport(); - ts.connect(); - ts.sendMessage(msg, msg.getRecipients(RecipientType.TO)); - ts.close(); - logger.info("mail sent to user " + username + " with e-mail address " + toAddress - + " with subject " + subject); - } catch (MessagingException e) { - logger.log(Level.SEVERE, "Error trying to send mail to user " + username - + " with e-mail address " + toAddress, e); - throw new MailException(e.getMessage()); - } + final User user = getUserByName(username); + if (user != null) { + final String toAddress = user.getEmail(); + if (toAddress != null) { + MailService mailService = getMailService(); + if (mailService == null) { + logger.warning(String.format("Could not send mail to user %s: no MailService found", username)); + } else { + getMailService().sendMail(username, subject, body); } } - } else { - logger.warning("No mail properties provided. Cannot send e-mail about "+subject+" to user "+username+ - ". This could also mean that this is running on a replica server in which case this is perfectly fine."); } } @@ -295,6 +288,22 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica logger.info("Redirecturl: " + redirectUrl); return redirectUrl; } + + @Override + public User loginByAccessToken(String accessToken) { + AccessToken token = new AccessToken(accessToken); + logger.info("Trying to login with access token"); + Subject subject = SecurityUtils.getSubject(); + try { + subject.login(token); + final String username = (String) token.getPrincipal(); + SessionUtils.saveUsername(username); + return store.getUserByName(username); + } catch (AuthenticationException e) { + logger.log(Level.INFO, "Authentication failed with access token "+accessToken); + throw e; + } + } @Override public void logout() { @@ -307,6 +316,11 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica public User getUserByName(String name) { return store.getUserByName(name); } + + @Override + public User getUserByAccessToken(String accessToken) { + return store.getUserByAccessToken(accessToken); + } @Override public User getUserByEmail(String email) { @@ -890,6 +904,18 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica return null; } + @Override + public Void internalSetAccessToken(String username, String accessToken) { + store.setAccessToken(username, accessToken); + return null; + } + + @Override + public Void internalRemoveAccessToken(String username, String accessToken) { + store.removeAccessToken(username, accessToken); + return null; + } + @Override public String getPreference(String username, String key) { Subject subject = SecurityUtils.getSubject(); @@ -900,11 +926,30 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica + " does not have permission to read preferences of user " + username); } } + + @Override + public String createAccessToken(String username) { + User user = getUserByName(username); + final String token; + if (user != null) { + RandomNumberGenerator rng = new SecureRandomNumberGenerator(); + byte[] salt = rng.nextBytes().getBytes(); + token = hashPassword(new String(rng.nextBytes().getBytes()), salt); + apply(s -> s.internalSetAccessToken(user.getName(), token)); + } else { + token = null; + } + return token; + } + + @Override + public void removeAccessToken(String username, String accessToken) { + apply(s -> s.internalRemoveAccessToken(username, accessToken)); + } // ----------------- Replication ------------- @Override public void clearReplicaState() throws MalformedURLException, IOException, InterruptedException { - mailProperties.clear(); store.clear(); } diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java index a2199c495bd..3baf3a3c261 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java @@ -11,6 +11,9 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +import org.json.simple.JSONObject; + +import com.sap.sse.security.User; import com.sap.sse.security.jaxrs.AbstractSecurityResource; import com.sap.sse.security.shared.UserManagementException; @@ -42,6 +45,41 @@ public class SecurityResource extends AbstractSecurityResource { } return Response.ok("Logged in!", MediaType.TEXT_PLAIN).build(); } + + @POST + @Path("/access_token") + @Produces("application/json;charset=UTF-8") + public Response accessToken(@FormParam("username") String username, @FormParam("password") String password) { + try { + getService().login(username, password); + logger.info("Successfully logged in " + username + " with password"); + JSONObject response = new JSONObject(); + response.put("username", username); + response.put("access_token", getService().createAccessToken(username)); + return Response.ok(response.toJSONString(), MediaType.APPLICATION_JSON).build(); + } catch (UserManagementException e) { + logger.info("Logging in " + username + " with password failed: "+e.getMessage()); + return getSecurityErrorResponse(e.getMessage()); + } + } + + @POST + @Path("/authenticate") + @Produces("application/json;charset=UTF-8") + public Response authenticate(@FormParam("access_token") String accessToken) { + User user = getService().loginByAccessToken(accessToken); + if (user == null) { + logger.info("Invalid access token " + accessToken); + return Response.status(Status.UNAUTHORIZED).entity("Access token " + accessToken + " not recognized") + .build(); + } else { + logger.info("Authenticated " + user.getName() + " with access token"); + } + JSONObject response = new JSONObject(); + response.put("username", user.getName()); + response.put("email", user.getEmail()); + return Response.ok(response.toJSONString(), MediaType.APPLICATION_JSON).build(); + } @GET @Path("/logout") diff --git a/java/com.sap.sse.shared.android/META-INF/MANIFEST.MF b/java/com.sap.sse.shared.android/META-INF/MANIFEST.MF old mode 100755 new mode 100644 diff --git a/java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/NonGwtUrlHelper.java b/java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/NonGwtUrlHelper.java new file mode 100644 index 00000000000..5a19f9d7fd8 --- /dev/null +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/NonGwtUrlHelper.java @@ -0,0 +1,23 @@ +package com.sap.sse.util.impl; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; + +import com.sap.sse.common.util.UrlHelper; + +public enum NonGwtUrlHelper implements UrlHelper { + INSTANCE; + + public String encodeUrl(String decodedUrlString) { + try { + URL url = new URL(decodedUrlString); + URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), + url.getQuery(), url.getRef()); + return uri.toString(); + } catch (MalformedURLException | URISyntaxException f) { + return null; + } + } +} diff --git a/java/com.sap.sse/META-INF/MANIFEST.MF b/java/com.sap.sse/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index ecb82aed73d..f241ed100a1 --- a/java/com.sap.sse/META-INF/MANIFEST.MF +++ b/java/com.sap.sse/META-INF/MANIFEST.MF @@ -10,12 +10,14 @@ Export-Package: com.sap.sse, com.sap.sse.i18n, com.sap.sse.i18n.impl, com.sap.sse.osgi, + com.sap.sse.qrcode, com.sap.sse.util, com.sap.sse.util.impl, com.sap.sse.util.kmeans Bundle-ActivationPolicy: lazy Require-Bundle: com.sap.sse.common, - com.sap.sse.shared.android + com.sap.sse.shared.android, + org.apache.servicemix.bundles.zxing;bundle-version="3.1.0" Import-Package: javax.servlet;version="3.1.0", javax.servlet.http;version="3.1.0", org.osgi.framework;version="1.8.0", diff --git a/java/com.sap.sse/src/com/sap/sse/i18n/ResourceBundleStringMessages.java b/java/com.sap.sse/src/com/sap/sse/i18n/ResourceBundleStringMessages.java index b752847d119..7db6f7f48d0 100644 --- a/java/com.sap.sse/src/com/sap/sse/i18n/ResourceBundleStringMessages.java +++ b/java/com.sap.sse/src/com/sap/sse/i18n/ResourceBundleStringMessages.java @@ -6,6 +6,16 @@ import java.util.Map; /** * Allow server-side internationalization similar to GWT client-side by using property files. + * + * Get Locale in GWT-Context by calling + *
    + * LocaleInfo.getCurrentLocale().getLocaleName();
    + * 
    + * + * Then transform back to {@link Locale} on server by calling + *
    + * ResourceBundleStringMessages.Util.getLocaleFor(localeInfoName);
    + * 
    */ public interface ResourceBundleStringMessages { diff --git a/java/com.sap.sse/src/com/sap/sse/qrcode/QRCodeGenerationUtil.java b/java/com.sap.sse/src/com/sap/sse/qrcode/QRCodeGenerationUtil.java new file mode 100644 index 00000000000..b4353f7139a --- /dev/null +++ b/java/com.sap.sse/src/com/sap/sse/qrcode/QRCodeGenerationUtil.java @@ -0,0 +1,66 @@ +package com.sap.sse.qrcode; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Hashtable; + +import javax.imageio.ImageIO; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.QRCodeWriter; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; + +/** + * QRCode generator based on the ZXing library. + * + * TODO have a look at repackaging QRGen as OSGi bundle. + * + * @author Fredrik Teschke + * + */ +public class QRCodeGenerationUtil { + public static InputStream create(String text, int sizeInPixels) throws WriterException, IOException { + Hashtable hintMap = new Hashtable(); + hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); + return create(text, sizeInPixels, hintMap); + } + + public static InputStream create(String text, int sizeInPixels, + Hashtable hintMap) throws WriterException, IOException { + //taken from http://crunchify.com/java-simple-qr-code-generator-example/ + + QRCodeWriter qrCodeWriter = new QRCodeWriter(); + BitMatrix byteMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, sizeInPixels, sizeInPixels, hintMap); + int matrixSize = byteMatrix.getWidth(); + BufferedImage image = new BufferedImage(matrixSize, matrixSize, BufferedImage.TYPE_INT_RGB); + image.createGraphics(); + + Graphics2D graphics = (Graphics2D) image.getGraphics(); + graphics.setColor(Color.WHITE); + graphics.fillRect(0, 0, matrixSize, matrixSize); + graphics.setColor(Color.BLACK); + + for (int i = 0; i < matrixSize; i++) { + for (int j = 0; j < matrixSize; j++) { + if (byteMatrix.get(i, j)) { + graphics.fillRect(i, j, 1, 1); + } + } + } + + //TODO create InputStream from streamed output of image instead of handling complete byte arrays + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ImageIO.write(image, "gif", os); + InputStream is = new ByteArrayInputStream(os.toByteArray()); + return is; + } +} diff --git a/java/com.sap.sse/src/com/sap/sse/util/ServiceTrackerFactory.java b/java/com.sap.sse/src/com/sap/sse/util/ServiceTrackerFactory.java new file mode 100644 index 00000000000..3af71035c02 --- /dev/null +++ b/java/com.sap.sse/src/com/sap/sse/util/ServiceTrackerFactory.java @@ -0,0 +1,18 @@ +package com.sap.sse.util; + +import org.osgi.framework.BundleContext; +import org.osgi.util.tracker.ServiceTracker; + +public class ServiceTrackerFactory { + /** + * @return {@code null} if {@code context} is {@code null} + */ + public static ServiceTracker createAndOpen(BundleContext context, Class clazz) { + if (context == null) { + return null; + } + ServiceTracker result = new ServiceTracker(context, clazz, null); + result.open(); + return result; + } +} diff --git a/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF b/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF index b2f04cadba2..b10a81fdeaa 100644 --- a/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF +++ b/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: TracTrac Client module Bundle-SymbolicName: com.tractrac.clientmodule -Bundle-Version: 3.0.7 +Bundle-Version: 3.0.9 Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: ., lib/TracAPI.jar diff --git a/java/com.tractrac.clientmodule/README.txt b/java/com.tractrac.clientmodule/README.txt index 31ed42bd96f..08aed822c98 100644 --- a/java/com.tractrac.clientmodule/README.txt +++ b/java/com.tractrac.clientmodule/README.txt @@ -16,6 +16,42 @@ It contains also some files: - test.sh -> script that compiles the code in the src folder, creates the test.jar library and execute the code of the example. - Manifest.txt -> manifest used to create the test.jar file +******************************************** +************* TracAPI 3.0.9 **************** +******************************************** +This is a final version. Only fixes bugs in the implementation + +Release date: 13/02/2015 +Build number: 9904 + + 1) Bugs + + - There is a ConcurrentModificationException in the IConnectionStatusListener subscription, when a thread + is adding subscriptions/unsubscriptions and other thread is sending events through this listener (Reported + by Axel Uhl,07/02/2015) + +******************************************** +************* TracAPI 3.0.8 **************** +******************************************** +This is a final version. It fixes bugs in the implementation and it adds a some features. +These features add methods to the API, but they keep the backward compatibility. +This version provides a new JavaDoc version. + +Release date: 07/02/2015 +Build number: 9826 + + 1) New features + + - Adding the method IEvent.getEventType that returns the type of the event (e.g: Sailing, Orienteering...). + (Requested by Jorge Piera, 01/02/2014) + + 2) Bugs + + - The changes in the static fields of the route (including the metadata) were not propagated through + the subscription library. Following the same approach used for the races, controls and competitors, + a new listener IRoutesListener has been added to manage these changes. (Reported by Axel Uhl, + 06/02/2015) + ******************************************** ************* TracAPI 3.0.7 **************** ******************************************** diff --git a/java/com.tractrac.clientmodule/lib/TracAPI.jar b/java/com.tractrac.clientmodule/lib/TracAPI.jar index 57e8e32f66f..f3d5016f5d8 100644 Binary files a/java/com.tractrac.clientmodule/lib/TracAPI.jar and b/java/com.tractrac.clientmodule/lib/TracAPI.jar differ diff --git a/java/com.tractrac.clientmodule/pom.xml b/java/com.tractrac.clientmodule/pom.xml index 93c4be791b1..a9ac043c7fe 100755 --- a/java/com.tractrac.clientmodule/pom.xml +++ b/java/com.tractrac.clientmodule/pom.xml @@ -8,6 +8,6 @@ 1.0.0-SNAPSHOT com.tractrac.clientmodule - 3.0.7 + 3.0.9 eclipse-plugin diff --git a/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF b/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF old mode 100755 new mode 100644 index 7a4966d0521..f4258435c9b --- a/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF +++ b/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF @@ -1,22 +1,22 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Moxie Apps GWT Highcharts -Bundle-SymbolicName: org.moxieapps.gwt.highcharts -Bundle-Version: 1.6.0.qualifier -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Export-Package: org.moxieapps.gwt.highcharts.client.plotOptions;uses:="o - rg.moxieapps.gwt.highcharts.client,com.google.gwt.json.client,org.moxie - apps.gwt.highcharts.client.events,org.moxieapps.gwt.highcharts.client.l - abels";version="1.5.0",org.moxieapps.gwt.highcharts;version="1.5.0",org - .moxieapps.gwt.highcharts.client;uses:="com.google.gwt.core.client,com. - google.gwt.dom.client,com.google.gwt.json.client,org.moxieapps.gwt.high - charts.client.plotOptions,com.google.gwt.user.client,org.moxieapps.gwt. - highcharts.client.events,org.moxieapps.gwt.highcharts.client.labels,com - .google.gwt.user.client.ui";version="1.5.0",org.moxieapps.gwt.highchart - s.client.events;uses:="com.google.gwt.core.client,com.google.gwt.dom.cl - ient,org.moxieapps.gwt.highcharts.client";version="1.5.0",org.moxieapps - .gwt.highcharts.client.labels;uses:="com.google.gwt.core.client,org.mox - ieapps.gwt.highcharts.client,com.google.gwt.json.client";version="1.5.0 - " -Bundle-ActivationPolicy: lazy -Require-Bundle: com.google.gwt.osgi;bundle-version="2.6.0" +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Moxie Apps GWT Highcharts +Bundle-SymbolicName: org.moxieapps.gwt.highcharts +Bundle-Version: 1.6.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Export-Package: org.moxieapps.gwt.highcharts.client.plotOptions;uses:="o + rg.moxieapps.gwt.highcharts.client,com.google.gwt.json.client,org.moxie + apps.gwt.highcharts.client.events,org.moxieapps.gwt.highcharts.client.l + abels";version="1.5.0",org.moxieapps.gwt.highcharts;version="1.5.0",org + .moxieapps.gwt.highcharts.client;uses:="com.google.gwt.core.client,com. + google.gwt.dom.client,com.google.gwt.json.client,org.moxieapps.gwt.high + charts.client.plotOptions,com.google.gwt.user.client,org.moxieapps.gwt. + highcharts.client.events,org.moxieapps.gwt.highcharts.client.labels,com + .google.gwt.user.client.ui";version="1.5.0",org.moxieapps.gwt.highchart + s.client.events;uses:="com.google.gwt.core.client,com.google.gwt.dom.cl + ient,org.moxieapps.gwt.highcharts.client";version="1.5.0",org.moxieapps + .gwt.highcharts.client.labels;uses:="com.google.gwt.core.client,org.mox + ieapps.gwt.highcharts.client,com.google.gwt.json.client";version="1.5.0 + " +Bundle-ActivationPolicy: lazy +Require-Bundle: com.google.gwt.osgi;bundle-version="2.6.0" diff --git a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java index 74201014580..cbffc78b2f6 100755 --- a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java +++ b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java @@ -2198,6 +2198,7 @@ public abstract class BaseChart extends Widget { public T redraw() { if (isRendered()) { nativeRedraw(chart); + nativeAdjustCheckboxPosition(chart); } return returnThis(); } @@ -2903,6 +2904,24 @@ public abstract class BaseChart extends Widget { return seriesList.get(seriesIndex).getPlotOptions().getDataLabels().getFormatter().format(new DataLabelsData(nativeData)); } + /** + * Fixing a bug currently in the base Highcharts implementation regarding the placement of the checkbox in the legend. + * Requires the symbol padding (see {@link Legend#setSymbolPadding(Number)}) to be set to 25. Invoked + * whenever the chart is rendered.

    + * + * The implementation moves the checkbox between the legend symbol and the legend item, using the space made by setting the symbol + * padding to 25px. + */ + private static native JavaScriptObject nativeAdjustCheckboxPosition(JavaScriptObject chart) /*-{ + var series = chart.series; + for(var i= 0; icom.sap.sse com.sap.sse.common com.sap.sse.shared.android + com.sap.sse.mail + com.sap.sse.mail.replication.test + com.sap.sse.mail.replication.testsupport com.sap.sse.mongodb com.sap.sse.gwt com.sap.sse.gwt.adminconsole @@ -60,7 +63,6 @@ com.google.gwt.osgi com.tractrac.clientmodule org.json.simple - com.mongodb.driver com.googlecode.java-diff-utils com.googlecode.mgwt com.sap.sailing.dashboards.gwt @@ -151,13 +153,13 @@ -Dfile.encoding=cp1252 -Dmongo.dbName=winddbTest -DspatialWind=true - -ea -Xmx1024m -XX:PermSize=256m -XX:+UseG1GC + -ea -Xmx1024m -XX:+UseG1GC -Dtractrac.tunnel=true -Dtractrac.tunnel.host=localhost - -Dmongo.host=localhost + -Dmongo.host=127.0.0.1 -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y @@ -186,7 +188,7 @@ no-debug.without-proxy - ${parameters.common} ${parameters.vm-settings} + ${parameters.common} ${parameters.vm-settings} ${parameters.mongodb} @@ -194,7 +196,7 @@ debug.with-proxy - ${parameters.common} ${parameters.vm-settings} ${parameters.proxy} ${parameters.debug} + ${parameters.common} ${parameters.vm-settings} ${parameters.proxy} ${parameters.debug} ${parameters.mongodb} @@ -202,7 +204,7 @@ debug.without-proxy - ${parameters.common} ${parameters.vm-settings} ${parameters.debug} + ${parameters.common} ${parameters.vm-settings} ${parameters.debug} ${parameters.mongodb} diff --git a/java/target/configuration/security.properties b/java/target/configuration/mail.properties similarity index 100% rename from java/target/configuration/security.properties rename to java/target/configuration/mail.properties diff --git a/java/target/env.sh b/java/target/env.sh index 8ef97faa381..80556db3319 100644 --- a/java/target/env.sh +++ b/java/target/env.sh @@ -41,7 +41,7 @@ EXPEDITION_PORT=2010 # set the REPLICATE_MASTER_EXCHANGE_NAME variable to the # same channel the master is using in its REPLICATION_CHANNEL variable -# REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl +# REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl # Host where the master Java instance is running # Make sure firewall configurations allow access diff --git a/mobile/com.sap.sailing.racecommittee.app/lint.xml b/mobile/com.sap.sailing.racecommittee.app/lint.xml index 12d0844263e..5320a5bc7ac 100644 --- a/mobile/com.sap.sailing.racecommittee.app/lint.xml +++ b/mobile/com.sap.sailing.racecommittee.app/lint.xml @@ -1,4 +1,5 @@ + diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java index 17a2e2fbb73..90c34fcf353 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java @@ -90,11 +90,11 @@ public class OfflineDataManager extends DataManager { medal), new EmptyRegattaConfiguration()); List competitors = new ArrayList(); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.BLUE, null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", Color.LIGHT_GRAY, null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", Color.RED, null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", Color.GREEN, null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", Color.BLACK, null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.BLUE, null, null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", Color.LIGHT_GRAY, null, null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", Color.RED, null, null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", Color.GREEN, null, null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", Color.BLACK, null, null, null)); RaceLogEventFactory factory = new RaceLogEventFactoryImpl(); RaceLog log = new RaceLogImpl(UUID.randomUUID()); diff --git a/wiki/tracking-app/api-v1.md b/wiki/tracking-app/api-v1.md index 3e056c0c939..78db7439ae0 100644 --- a/wiki/tracking-app/api-v1.md +++ b/wiki/tracking-app/api-v1.md @@ -7,18 +7,32 @@ We have decided to handle checkins etc. at the level of ``Leaderboard``s instead This document supplements the [documentation of the existing REST API](http://www.sapsailing.com/sailingserver/webservices/api/v1/index.html), highlighting those resources necessary for the tracking app, and specifying such resources that are not yet present in the API. +For the moment, this document also contains the API for the proposed [Buoy Tender (Tonnenleger) App](#buoy-tender-app), which can be moved to a separate document at some point. + ### URL base ``` http:///sailingserver/api/v1/ ``` All relative URLs given below are relative to this base URL. +## Process + +The endpoints listed below should mostly be called in the order they are listed here. +That is, after + +1. receiving the [Checkin Information](#tracking-checkin-info), the App can +2. then perform the [Check-In](#checkin) for the competitor in question +3. and proceed with sending [GPS Fixes](#fixes). + + ## Push Notifications +_not yet implemented_ + Event data can be updated via push notifications. These are limited on iOS to 256 bytes (not characters). For this reason, on receiving a push notification, the app must GET the event data. - -## Checkin Information +## Check-In Information +

    ### URL and QRCode @@ -105,6 +119,7 @@ _**Note:** Consider using the leaderboard-dependent verison below - which includ ## Check-In +
    After the user has received the event data with the short URL, the smartphone is mapped to a competitor. @@ -162,6 +177,7 @@ Ends the device to competitor coupling. Does not delete it, but rather marks the ## Send Measurements (to the Fix Store) +
    The main data sent by the app. @@ -251,4 +267,97 @@ $ curl -H "Content-Type:image/jpeg" --data-binary @ \ { "teamImageUri" : "http://training.sapsailing.com/team_images/9871d3a2c554b27151cacf1422eec048.jpeg" } -``` \ No newline at end of file +``` + +# Buoy Tender (Tonnenleger) App +
    + +An app aimed at buoy tenders. In v1, this only allows marks of a race to be _pinged_. The steps for doing so are + +1. provide the information for which leaderboard and race to ping marks +2. get the marks for that race (potentially form the RaceLog, if no TrackedRace is yet present) +3. ping the marks by submitting fixes + +## Check-In Information +
    + +_see [bug 2650](http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=2650)_ + +In contrast to the _Tracking App_, we won't perform a check-in. However, we can deliver the information on leaderboard and race analogously through a URL (potentially QRCode), which is why this section is also called _Check-In Information_. + +This information is represented in a URL with the following structure: +``` +http:///buoy-tender/checkin + &leaderboard_name= + &race_name= +``` + +_also see [Tracking App Check-In Information](#tracking-checkin-info) for additional notes that might apply_ + +## Get Marks + +_see [bug 2651](http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=2651)_ + +Do not use the course to get the list of marks to ping. Instead, use the ``RaceLogDefineMarkEvent``s in the RaceLog, or ``TrackedRace#getMarks()``. As the JavaDoc of the latter states, not all marks for a race are necessarily present in the course - e.g. if they are backup buoys to be used in the case of a wind shift. + +**Path:** ``leaderboards/{leaderboard-name}/marks?raceColumn={race-column-name}&fleet={fleet-name}`` + +**Verb:** ``GET`` + +**Response:** +``` +[ + { + "@class": "Mark", + "name": "Start (1)", + "id": "Start (1)", + "type": "BUOY" + }, + { + "@class": "Mark", + "name": "Start (2)", + "id": "Start (2)", + "type": "BUOY" + }, + { + "@class": "Mark", + "name": "Windward", + "id": "22a53380-046e-0132-0da7-60a44ce903c3", + "type": "BUOY" + } +] +``` + +## Ping Marks + +_see [bug 2652](http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=2652)_ + +Instead of the checkin/checkout process of the tracking app, marks can be pinged using an API that hides the inner workings on the server completely. The server creates a device-mapping in the regatta-log for the exact timepoint of every fix, and adds the fixes to the GPSFixStore. + +The interface (apart from the path) is identical to [Send Measurements](#fixes). Several fixes can be sent at once, but in the interest of pinging a mark, this should usually just be a single fix. + +**Path:** ``leaderboards/{leaderboard-name}/marks/{mark-id}/gps_fixes`` + +**Verb:** ``POST`` + +**Request:** +``` +{ + "deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf", + "fixes" : [ + { + "timestamp" : 14144160080000, + "latitude" : 54.325246, + "longitude" : 10.148556, + "speed" : 3.61, + "course" : 258.11, + } + ] +} +``` + +**Additional Notes:** +* the path for this endpoint intentionally has the leaderboard as a parent item + * each mark should have a unique ID (``SharedDomainFactory#getOrCreateMark(String toStringRepresentationOfID, String name)``) + * however, the mark cannot be pinged without the leaderboard as context, however, as the GPSFixStore contains only fixes with a device ID, and the mapping from that device to a mark has to be established through a RegattaLog (or RaceLog), which is attached to a (Flexible|Regatta)Leaderboard + * an alternative endpoint definition might be ``POST marks/{mid}/gps_fixes?leaderboard_name={ln}`` \ No newline at end of file