From 680f3a0441a838c3971df1e2ce0043598de7ec09 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Wed, 29 Nov 2017 14:09:35 +0100 Subject: [PATCH 01/14] added UserStore.hasUsers for efficient check whether there are none Change-Id: Ifacc9c84bda961399b866e860757e8ebe0d78b71 --- .../sap/sse/security/userstore/mongodb/UserStoreImpl.java | 5 +++++ .../src/com/sap/sse/security/UserStore.java | 2 ++ .../src/com/sap/sse/security/impl/SecurityServiceImpl.java | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) 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 39c73208926..4c5766cd0c3 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 @@ -318,6 +318,11 @@ public class UserStoreImpl implements UserStore { return new ArrayList(users.values()); } + @Override + public boolean hasUsers() { + return !users.isEmpty(); + } + @Override public User getUserByName(String name) { final User result; 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 56a35a4f49e..57cb5e3192d 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 @@ -10,6 +10,8 @@ import com.sap.sse.security.shared.UserManagementException; public interface UserStore extends Named { Iterable getUsers(); + + boolean hasUsers(); /** * The user with that {@link User#getName() name} or {@code null} if no such user exists 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 index 14995ccfb79..f4ed105a781 100644 --- 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 @@ -191,7 +191,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat * is empty. */ private void initEmptyStore() { - if (Util.isEmpty(store.getUsers())) { + if (!store.hasUsers()) { try { logger.info("No users found, creating default user \"admin\" with password \"admin\""); createSimpleUser("admin", "nobody@sapsailing.com", "admin", From 24d8f66ffcc85d47be22cd11786972ba7c2873f7 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 29 Nov 2017 13:31:00 +0000 Subject: [PATCH 02/14] Updated bug2822 review (markdown) --- wiki/bug2822-review.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/wiki/bug2822-review.md b/wiki/bug2822-review.md index 4d699b36b76..1663e0d89f5 100644 --- a/wiki/bug2822-review.md +++ b/wiki/bug2822-review.md @@ -106,7 +106,26 @@ Make sure that attribute changes of competitors and boats in the admin console a ## 7. Competitor Import (Manage2Sail connector) -Import competitors from a Manage2Sail event and check if the competitors and boats are created in the right way. +Precondition: Create a result import provider for Manage2Sail +E.g.: http://manage2sail.com/api/public/links/event/c19b811f-8dd0-4d6f-b846-7d07bd0dead9?accesstoken=bDAv8CwsTM94ujZ&mediaType=json + +### 7.1 Import Competitors into regatta where boats CAN change + +Check: + +- Create a simple regatta where boats can change per race +- Go to 'Connectors' -> 'Smartphone Tracking -> Select the regatta -> Click on 'Competitor registrations' +- Select some competitors and import them +- The competitors will be created and stored but without boats using the RegattaLogRegisterCompetitorEvent + +### 7.2 Import Competitors into regatta where boats CAN NOT change + +Check: + +- Create a simple regatta where boats can NOT change per race +- Go to 'Connectors' -> 'Smartphone Tracking -> Select the regatta -> Click on 'Competitor registrations' +- Select some competitors and import them +- The competitors will be created and stored WITH linked boats using the RegattaLogRegisterCompetitorAndBoatEvent ## 8. WebService API From dd61d70b0e722e769dcdd83acf01df34b4921b0a Mon Sep 17 00:00:00 2001 From: "service.tip.git" Date: Wed, 29 Nov 2017 13:48:02 +0000 Subject: [PATCH 03/14] [INTERNAL] Translation delivery: commit by SLS Change-Id: I5bf8769da727998e697808f7c1fd31e953037e1b --- .../ui/client/StringMessages_es.properties | 43 +++++++++++++++++ .../ui/client/StringMessages_fr.properties | 47 ++++++++++++++++++- .../ui/client/StringMessages_ja.properties | 45 +++++++++++++++++- .../ui/client/StringMessages_pt.properties | 45 +++++++++++++++++- .../ui/client/StringMessages_ru.properties | 43 +++++++++++++++++ .../ui/client/StringMessages_zh.properties | 45 +++++++++++++++++- 6 files changed, 263 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties index 1df06918d9e..1c9082786c7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties @@ -183,6 +183,7 @@ in=en secondsUnit=s secondsPerNauticalMileUnit=s/NM metersUnit=m +millimetersUnit=mm degreesUnit=° close=Cerrar compareCompetitors=Comparar competidores @@ -992,6 +993,7 @@ overwriteRacingProceduresConfiguration=Activar configuración de regata overwriteRacingProceduresConfigurationHelpText=Si se activa esta opción, se proporcionará una configuración de regata base para todas las opciones no configuradas en la configuración específica de regata. setStartTime=Fijar hora de salida currentPass=Pase actual +setFinishingAndFinishTimeDescription=Seleccione las horas de llegada y de fin nuevas para la carrera. setStartTimeDescription=Seleccione una hora de salida nueva para la prueba. Si desea fijar la hora de salida en el pasado, deberá habilitar la casilla de selección para actualizar el recuento de pases. Tenga en cuenta que si cambia el recuento de pases se perderá toda la información del pase anterior (como eventos de bandera) setTrackingTimesDescription=Defina la salida y la llegada del rastreo para la carrera. hasAdditionalGolfDownTime=Activar tiempo de descanso de golf adicional @@ -1020,6 +1022,7 @@ searchTag=Etiqueta de búsqueda doYouReallyWantToRemoveLeaderboard=¿Desea realmente eliminar la tabla de clasificación: "{0}"? metaLeaderboardCannotBeChanged=Se trata de una metatabla de clasificación. No se puede modificar aquí. failedToSetNewStartTime=No se ha podido fijar una nueva hora de salida. Esto puede ocurrir si ya existe la misma hora de salida en el registro de la carrera o si alguna persona ha añadido una hora de salida más reciente (en términos de un ID de paso y de una hora lógica) que la hora que acaba de añadir. +failedToSetNewFinishingAndFinishTime=Ha fallado la fijación de la hora de llegada y de fin nueva. doYouReallyWantToRemoveIgtimiAccount=¿Desea realmente eliminar la cuenta de Igtimi otorgando acceso a los datos del usuario {0}? igtimiWindImport=Importar viento desde Igtimi seeIgtimiTabForAccountSettings=Consulte la pestaña "Igtimi" para conocer los ajustes de la cuenta que determinan qué datos de Igtimi deben tenerse en cuenta. @@ -1915,6 +1918,10 @@ currentStbdRudderRake=Inclinación del timón a estribor currentStbdRudderRakeTooltip=La inclinación actual del timón a estribor currentMastRotationInDegree=Rotación del mástil currentMastRotationInDegreeTooltip=La rotación actual del mástil en grados +finishingTime=Hora de llegada +finishTimeString=Hora de fin +setFinishingAndFinishTime=Fijar hora de llegada y de fin +finishTimeMustBeAtOrAfterFinishingTime=Hora de fin debe ser a la hora de llegada o posterior boatNameMustNotBeEmpty=Proporcione un nombre de embarcación que no esté en blanco errorUpdatingExpeditionDeviceConfiguration=Error al actualizar la configuración del dispositivo con la expedición "{0}": {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=¿Desea realmente eliminar la configuración del dispositivo con la expedición "{0}"? @@ -1926,3 +1933,39 @@ editExpeditionDeviceConfiguration=Tratar configuración de dispositivo con exped expeditionBoatId=ID de embarcación (por ejemplo 0, 1, o 2) doYouReallyWantToRemoveTheSelectedExpeditionDeviceConfigurations=¿Desea realmente eliminar las configuraciones del dispositivo con expedición seleccionadas? doYouReallyWantToRemoveTheSelectedIgtimiAccounts=¿Desea realmente eliminar las cuentas Igtimi seleccionadas? +currentDepthInMeters=Profundidad +currentDriftInDegrees=Desviación +currentLeewayInDegrees=Deriva +currentRudderInDegrees=Timón +currentSet=Conjunto +currentTackAngleInDegrees=Ángulo de bordo +currentDeflectorInMillimeters=Distancia de deflector +currentDeflectorPercentage=Ratio de deflector +currentForestayLoad=Carga de estay de proa +currentForestayPressure=Presión de estay de proa +currentRakeInDegrees=Rastrillo +currentTargetBoatspeedPercentage=Velocidad de embarcación objetivo +currentTargetHeelAngleInDegrees=Escora objetivo +percent=% +currentTargetHeelAngleInDegreesTooltip=Ángulo de escora objetivo para mejor rendimiento +currentTargetBoatspeedPercentageTooltip=Porcentaje alcanzado de velocidad de embarcación objetivo calculada +currentRakeInDegreesTooltip=Ángulo del mástil +currentForestayLoadTooltip=Carga de estay de proa, medida por célula de carga +currentForestayPressureTooltip=Presión de estay de proa +currentDeflectorPercentageTooltip=Porcentaje de deflector +currentDeflectorInMillimetersTooltip=Distancia de deflector +currentTackAngleInDegreesTooltip=El ángulo de bordo óptimo calculado +currentSetTooltip=Conjunto (???) +currentRudderInDegreesTooltip=Ángulo de timón; valores negativos significan a puerto; positivos, a estribor +currentLeewayInDegreesTooltip=Deriva +currentDriftInDegreesTooltip=Ángulo entre dirección y rumbo sobre fondo +currentDepthInMetersTooltip=Profundidad del agua +tonsUnit=t +currentDistanceFoiledInMeters=Distancia con foils +currentDurationFoiled=Tiempo con foils +currentDistanceFoiledInMetersTooltip=Distancia con foils en metros +currentDurationFoiledTooltip=Tiempo empleado con foils +totalDurationFoiledInSeconds=Tiempo total con foils +totalDistanceFoiledInMeters=Distancia total con foils +totalDurationFoiledInSecondsTooltip=Tiempo total con foils, a lo largo de todas la clasificación +totalDistanceFoiledInMetersTooltip=Distancia total con foils, a lo largo de todas la clasificación diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties index 1a62cc4e400..26cd8b5a886 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties @@ -182,7 +182,8 @@ distance=Distance in=en secondsUnit=s secondsPerNauticalMileUnit=s/NM -metersUnit=nm +metersUnit=m +millimetersUnit=mm degreesUnit=° close=Fermer compareCompetitors=Comparer concurrents @@ -992,7 +993,8 @@ overwriteRacingProceduresConfiguration=Activer configuration de la régate overwriteRacingProceduresConfigurationHelpText=L''activation de cette option fournira une configuration de base de la régate pour toutes les options non configurées dans la configuration spécifique de la régate. setStartTime=Définir heure de départ currentPass=Passage actuel -setStartTimeDescription=Sélectionnez une nouvelle heure de départ pour la course. Si vous voulez définir une heure de départ qui corresponde à une heure du passé, vous devez cocher cette case pour mettre à jour le nombre de passages. Notez qu''en modifiant le nombre de passages, vous perdrez toutes les informations concernant le passage précédent (comme les pavillons et manifestations). +setFinishingAndFinishTimeDescription=Sélectionnez l''heure d''arrivée du premier et l''heure de fermeture de la ligne d''arrivée pour la course. +setStartTimeDescription=Sélectionnez une nouvelle heure de départ pour la course. Si vous voulez définir une heure de départ dans le passé, vous devez cocher cette case pour mettre à jour le nombre de passages. Notez qu''en modifiant le nombre de passages, vous perdrez toutes les informations concernant le passage précédent (comme les pavillons et manifestations). setTrackingTimesDescription=Définissez le début et la fin du suivi pour la course. hasAdditionalGolfDownTime=Activer temps d''arrêt supplémentaire additionalGolfDownTimeHelpText=Activer temps d''arrêt supplémentaire @@ -1020,6 +1022,7 @@ searchTag=Balise de recherche doYouReallyWantToRemoveLeaderboard=Voulez-vous vraiment supprimer le palmarès "{0}" ? metaLeaderboardCannotBeChanged=Ce palmarès est de type méta. Vous ne pouvez pas le modifier ici. failedToSetNewStartTime=Définition de la nouvelle heure de départ échouée. Cela peut arriver lorsque la même heure de départ existe déjà dans le journal de course ou lorsque quelqu''un d''autre a ajouté une heure de départ plus récente (sous forme d''ID de passage et d''heure logique) que celle que vous venez d''ajouter. +failedToSetNewFinishingAndFinishTime=Échec de la définition des nouvelles heures d''arrivée du premier et de fermeture de la ligne d''arrivée. doYouReallyWantToRemoveIgtimiAccount=Souhaitez-vous réellement supprimer le compte Igtimi qui permet à l''utilisateur {0} d''accéder aux données ? igtimiWindImport=Importer le vent depuis Igtimi seeIgtimiTabForAccountSettings=Afficher l''onglet "Igtimi" pour voir les options de compte qui déterminent quelles données Igtimi seront prises en compte. @@ -1915,6 +1918,10 @@ currentStbdRudderRake=Inclinaison du gouvernail tribord currentStbdRudderRakeTooltip=Inclinaison actuelle du gouvernail tribord currentMastRotationInDegree=Rotation du mât currentMastRotationInDegreeTooltip=Rotation actuelle du mât en degrés +finishingTime=Heure d''arrivée du premier +finishTimeString=Heure de fermeture de la ligne d''arrivée +setFinishingAndFinishTime=Définir heure d''arrivée du premier et de fermeture de la ligne d''arrivée +finishTimeMustBeAtOrAfterFinishingTime=L''heure de fermeture de la ligne d''arrivée doit être égale ou ultérieure à l''heure d''arrivée du premier. boatNameMustNotBeEmpty=Veuillez indiquer un nom de bateau. errorUpdatingExpeditionDeviceConfiguration=Erreur lors de la mise à jour de la configuration du terminal Expedition "{0}" : {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=Voulez-vous vraiment supprimer la configuration du terminal Expedition "{0}" ? @@ -1926,3 +1933,39 @@ editExpeditionDeviceConfiguration=Modifier configuration du terminal Expedition expeditionBoatId=ID du bateau (par exemple 0, 1 ou 2) doYouReallyWantToRemoveTheSelectedExpeditionDeviceConfigurations=Voulez-vous vraiment supprimer les configurations du terminal Expedition sélectionnées ? doYouReallyWantToRemoveTheSelectedIgtimiAccounts=Voulez-vous vraiment supprimer les comptes lgtimi sélectionnés ? +currentDepthInMeters=Profondeur +currentDriftInDegrees=Vitesse du courant +currentLeewayInDegrees=Dérive +currentRudderInDegrees=Gouvernail +currentSet=Direction du courant +currentTackAngleInDegrees=Angle de virement de bord +currentDeflectorInMillimeters=Distance déflecteur +currentDeflectorPercentage=Ratio déflecteur +currentForestayLoad=Charge étai avant +currentForestayPressure=Pression étai avant +currentRakeInDegrees=Inclinaison +currentTargetBoatspeedPercentage=Vitesse cible du bateau +currentTargetHeelAngleInDegrees=Gîte cible +percent=% +currentTargetHeelAngleInDegreesTooltip=Angle de gîte cible pour obtenir de meilleures performances +currentTargetBoatspeedPercentageTooltip=Pourcentage de la vitesse cible du bateau calculée atteinte +currentRakeInDegreesTooltip=Inclinaison du mât +currentForestayLoadTooltip=Charge étai avant, mesurée par un capteur de force +currentForestayPressureTooltip=Pression étai avant +currentDeflectorPercentageTooltip=Pourcentage déflecteur +currentDeflectorInMillimetersTooltip=Distance déflecteur +currentTackAngleInDegreesTooltip=Angle de virement optimal calculé +currentSetTooltip=Direction du courant (???) +currentRudderInDegreesTooltip=Angle du gouvernail : valeurs négatives = à bâbord, valeurs positives = à tribord +currentLeewayInDegreesTooltip=Dérive +currentDriftInDegreesTooltip=Angle entre le cap et la route fond +currentDepthInMetersTooltip=Hauteur d''eau +tonsUnit=t +currentDistanceFoiledInMeters=Distance parcourue en planing +currentDurationFoiled=Temps de planing +currentDistanceFoiledInMetersTooltip=Distance parcourue en planing en mètres +currentDurationFoiledTooltip=Temps passé en planing +totalDurationFoiledInSeconds=Temps total passé en planing +totalDistanceFoiledInMeters=Distance totale parcourue en planing +totalDurationFoiledInSecondsTooltip=Temps total passé en planing, sur la totalité du palmarès +totalDistanceFoiledInMetersTooltip=Distance totale parcourue en planing, sur la totalité du palmarès diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties index 947942ec0f9..9cb256c04d5 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties @@ -183,6 +183,7 @@ in=in secondsUnit=s secondsPerNauticalMileUnit=s/NM metersUnit=m +millimetersUnit=mm degreesUnit=° close=閉じる compareCompetitors=競技者比較 @@ -992,7 +993,8 @@ overwriteRacingProceduresConfiguration=レガッタ設定の有効化 overwriteRacingProceduresConfigurationHelpText=このオプションを有効化すると、レガッタ固有の設定で未設定のすべてのオプションに対して基本レガッタ設定が与えられます。 setStartTime=スタート時刻の設定 currentPass=現在のパス -setStartTimeDescription=レースの新規スタート時刻を選択してください。スタート時刻を過去の時点に設定する場合は、パスカウントを更新するチェックボックスを有効化する必要があります。パスカウントを変更すると (信号旗イベントなどの) 以前のパスからの情報がすべて解放されるということに注意してください。 +setFinishingAndFinishTimeDescription=レースのフィニッシュ予定時刻とフィニッシュ時刻を新たに選択してください。 +setStartTimeDescription=レースの新規スタート時刻を選択してください。スタート時刻を過去の時点に設定する場合は、パスカウントを更新するチェックボックスを有効化する必要があります。パスカウントを変更すると (信号旗イベントなどの) 以前のパスからの情報がすべて失われることに注意してください。 setTrackingTimesDescription=レース追跡の開始および終了を設定してください。 hasAdditionalGolfDownTime=追加ゴルフダウンタイムの有効化 additionalGolfDownTimeHelpText=追加ゴルフダウンタイムの有効化 @@ -1020,6 +1022,7 @@ searchTag=検索タグ doYouReallyWantToRemoveLeaderboard=リーダーボード ''{0}'' を削除しますか。 metaLeaderboardCannotBeChanged=これはメタリーダーボードです。ここで変更することはできません。 failedToSetNewStartTime=新規スタート時刻の設定に失敗しました。これは、同じスタート時刻がすでにレースログに存在しているか、いま追加したものよりも (パス ID および論理時間の点で) 新しいスタート時間を誰かが追加している場合に発生することがあります。 +failedToSetNewFinishingAndFinishTime=新規フィニッシュ時刻の設定に失敗しました。 doYouReallyWantToRemoveIgtimiAccount=ユーザ {0} のデータへのアクセスを付与する Igtimi アカウントを削除しますか。 igtimiWindImport=Igtimi から風をインポート seeIgtimiTabForAccountSettings=''Igtimi'' タブで、Igtimi からのどのデータを考慮するかを指定するアカウント設定を参照してください。 @@ -1915,6 +1918,10 @@ currentStbdRudderRake=右舷ラダー傾斜角 currentStbdRudderRakeTooltip=現在の右舷ラダー傾斜角 currentMastRotationInDegree=マスト回転 currentMastRotationInDegreeTooltip=現在のマスト回転 (度) +finishingTime=フィニッシュ予定時刻 +finishTimeString=フィニッシュ時刻 +setFinishingAndFinishTime=フィニッシュ予定時刻とフィニッシュ時刻の設定 +finishTimeMustBeAtOrAfterFinishingTime=フィニッシュ時刻はフィニッシュ予定時刻以降であることが必要 boatNameMustNotBeEmpty=空でない艇名を指定してください errorUpdatingExpeditionDeviceConfiguration=Expedition デバイス設定 "{0}" の更新でエラーが発生: {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=Expedition デバイス設定 "{0}" を削除しますか @@ -1926,3 +1933,39 @@ editExpeditionDeviceConfiguration=Expedition デバイス設定の編集 expeditionBoatId=艇 ID (たとえば 0、1、2 など) doYouReallyWantToRemoveTheSelectedExpeditionDeviceConfigurations=選択した Expedition デバイス設定を削除しますか doYouReallyWantToRemoveTheSelectedIgtimiAccounts=選択した Igtimi アカウントを削除しますか +currentDepthInMeters=深さ +currentDriftInDegrees=ドリフト +currentLeewayInDegrees=リーウェイ +currentRudderInDegrees=ラダー +currentSet=セット +currentTackAngleInDegrees=タック角 +currentDeflectorInMillimeters=ディフレクター距離 +currentDeflectorPercentage=ディフレクター比 +currentForestayLoad=フォアステイ負荷 +currentForestayPressure=フォアステイ圧 +currentRakeInDegrees=レーキ +currentTargetBoatspeedPercentage=目標艇速 +currentTargetHeelAngleInDegrees=目標ヒール +percent=% +currentTargetHeelAngleInDegreesTooltip=最高パフォーマンスの目標ヒール角 +currentTargetBoatspeedPercentageTooltip=計算による目標艇速に達した比率 (%) +currentRakeInDegreesTooltip=マストレーキ +currentForestayLoadTooltip=フォアステイ負荷 (ロードセルによる計測) +currentForestayPressureTooltip=フォアステイ圧 +currentDeflectorPercentageTooltip=ディフレクター比 (%) +currentDeflectorInMillimetersTooltip=ディフレクター距離 +currentTackAngleInDegreesTooltip=計算による最適タック角 +currentSetTooltip=セット (???) +currentRudderInDegreesTooltip=ラダー角 (マイナス値は左舷、プラス値は右舷を意味) +currentLeewayInDegreesTooltip=リーウェイ +currentDriftInDegreesTooltip=針路と対地コースの間の角度 +currentDepthInMetersTooltip=水深 +tonsUnit=t +currentDistanceFoiledInMeters=フォイリング距離 +currentDurationFoiled=フォイリング時間 +currentDistanceFoiledInMetersTooltip=フォイリングに使われた距離 (m) +currentDurationFoiledTooltip=フォイリング時間 +totalDurationFoiledInSeconds=合計フォイリング時間 +totalDistanceFoiledInMeters=合計フォイリング距離 +totalDurationFoiledInSecondsTooltip=合計フォイリング時間 (リーダーボード全体) +totalDistanceFoiledInMetersTooltip=合計フォイリング距離 (リーダーボード全体) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties index 1d96bf51018..0d538714349 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties @@ -183,6 +183,7 @@ in=em secondsUnit=s secondsPerNauticalMileUnit=s/NM metersUnit=m +millimetersUnit=mm degreesUnit=° close=Encerrar compareCompetitors=Comparar competidores @@ -992,7 +993,8 @@ overwriteRacingProceduresConfiguration=Ativar configuração de regata overwriteRacingProceduresConfigurationHelpText=A ativação desta opção fornecerá uma configuração básica da regata para todas as opções não configuradas na configuração específica da regata. setStartTime=Definir hora de partida currentPass=Passagem atual -setStartTimeDescription=Selecione uma nova hora de início para a corrida. Se você quiser definir a hora de início para uma data/hora no passado, então precisa ativar o campo de seleção para atualizar a contagem das passagens. Tenha em atenção que a modificação da contagem das passagens fará com que sejam perdidas todas as informações da passagem anterior (como eventos de bandeira). +setFinishingAndFinishTimeDescription=Selecionar novas horas de chegada e conclusão para a corrida. +setStartTimeDescription=Selecione uma nova hora de partida para a corrida. Se você quiser definir a hora de partida para uma data/hora no passado, então precisa ativar o campo de seleção para atualizar a contagem das passagens. Tenha em atenção que a modificação da contagem das passagens fará com que sejam perdidas todas as informações da passagem anterior (como eventos de bandeira). setTrackingTimesDescription=Definir o início e o fim do rastreamento para a corrida. hasAdditionalGolfDownTime=Ativar pausa Golf adicional additionalGolfDownTimeHelpText=Ativar pausa Golf adicional @@ -1020,6 +1022,7 @@ searchTag=Etiqueta de pesquisa doYouReallyWantToRemoveLeaderboard=Você tem a certeza que quer remover o painel de classificação: ''{0}''? metaLeaderboardCannotBeChanged=Este é um painel de classificação meta. Não é possível modificá-lo aqui. failedToSetNewStartTime=Falha ao definir nova hora de início. Isto pode suceder se a mesma hora de início já existir no registro de corridas ou se alguém tiver adicionado uma hora de início mais recente (em termos de um ID de passagem e hora lógica) que aquela que você acabou de adicionar. +failedToSetNewFinishingAndFinishTime=Falha ao definir nova hora de chegada e conclusão. doYouReallyWantToRemoveIgtimiAccount=Você quer realmente remover a conta de Igtimi concedendo acesso a dados do usuário {0}? igtimiWindImport=Importar vento de Igtimi seeIgtimiTabForAccountSettings=Consulte a ficha ''Igtimi'' para as configurações da conta que determinam que dados de Igtimi serão considerados. @@ -1915,6 +1918,10 @@ currentStbdRudderRake=Inclinação leme boreste currentStbdRudderRakeTooltip=A inclinação atual do leme para boreste currentMastRotationInDegree=Rotação do mastro currentMastRotationInDegreeTooltip=A rotação atual do mastro em graus +finishingTime=Hora de chegada +finishTimeString=Hora de conclusão +setFinishingAndFinishTime=Definir hora de chegada e conclusão +finishTimeMustBeAtOrAfterFinishingTime=A hora de conclusão deve ser igual ou posterior à hora de chegada boatNameMustNotBeEmpty=Forneça um nome de barco não vazio errorUpdatingExpeditionDeviceConfiguration=Erro ao atualizar configuração de dispositivo Expedition "{0}": {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=Você quer realmente remover a configuração do dispositivo Expedition "{0}"? @@ -1926,3 +1933,39 @@ editExpeditionDeviceConfiguration=Processar configuração do dispositivo Expedi expeditionBoatId=ID do barco (por ex., 0, 1 ou 2) doYouReallyWantToRemoveTheSelectedExpeditionDeviceConfigurations=Você quer realmente remover as configurações do dispositivo Expedition selecionado? doYouReallyWantToRemoveTheSelectedIgtimiAccounts=Você quer realmente remover as contas de Igtimi selecionadas? +currentDepthInMeters=Profundidade +currentDriftInDegrees=Deriva +currentLeewayInDegrees=Abatimento +currentRudderInDegrees=Leme +currentSet=Curso +currentTackAngleInDegrees=Ângulo de cambada +currentDeflectorInMillimeters=Distância de defletor +currentDeflectorPercentage=Proporção de defletor +currentForestayLoad=Carga de estai +currentForestayPressure=Pressão de estai +currentRakeInDegrees=Inclinação +currentTargetBoatspeedPercentage=Velocidade prevista do barco +currentTargetHeelAngleInDegrees=Inclinação prevista +percent=% +currentTargetHeelAngleInDegreesTooltip=Ângulo previsto de inclinação para melhor desempenho +currentTargetBoatspeedPercentageTooltip=Porcentagem da velocidade prevista do barco calculada atingida +currentRakeInDegreesTooltip=Inclinação do mastro +currentForestayLoadTooltip=Carga de estai, medida por uma célula de carga +currentForestayPressureTooltip=Pressão de estai +currentDeflectorPercentageTooltip=Porcentagem de defletor +currentDeflectorInMillimetersTooltip=Distância de defletor +currentTackAngleInDegreesTooltip=O ângulo de cambada ideal calculado +currentSetTooltip=Curso (???) +currentRudderInDegreesTooltip=Ângulo do leme; valores negativos indicam bombordo, positivos boreste +currentLeewayInDegreesTooltip=Abatimento +currentDriftInDegreesTooltip=Ângulo entre orientação e percurso no fundo +currentDepthInMetersTooltip=Profundidade da água +tonsUnit=t +currentDistanceFoiledInMeters=Distância com hidrofólio +currentDurationFoiled=Tempo com hidrofólio +currentDistanceFoiledInMetersTooltip=Distância percorrida em navegação com hidrofólio em metros +currentDurationFoiledTooltip=Tempo gasto em navegação com hidrofólio +totalDurationFoiledInSeconds=Total de tempo com hidrofólio +totalDistanceFoiledInMeters=Total de distância com hidrofólio +totalDurationFoiledInSecondsTooltip=Total de tempo com hidrofólio, em todo o painel de classificação +totalDistanceFoiledInMetersTooltip=Total de distância com hidrofólio, em todo o painel de classificação 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 a71a6103445..090e5d2be3c 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 @@ -183,6 +183,7 @@ in=в secondsUnit=с secondsPerNauticalMileUnit=с/NM metersUnit=м +millimetersUnit=мм degreesUnit=° close=Закрыть compareCompetitors=Сравнить участников @@ -992,6 +993,7 @@ overwriteRacingProceduresConfiguration=Активировать конфигур overwriteRacingProceduresConfigurationHelpText=Включение этого параметра предоставит базовую конфигурацию регаты для всех не настроенных параметров в конфигурации данной регаты. setStartTime=Установить время старта currentPass=Текущее прохождение +setFinishingAndFinishTimeDescription=Выберите новое время финиширования и финиша для гонки. setStartTimeDescription=Выберите новое время старта для гонки. Если требуется назначить старт на время в прошлом, установите флажок для обновления счетчика прохождений. Учтите, что при изменении числа прохождений будут потеряны все сведения из предыдущих прохождений (такие как события флагов). setTrackingTimesDescription=Установка времени начала и окончания отслеживания гонки. hasAdditionalGolfDownTime=Активировать дополнительное время @@ -1020,6 +1022,7 @@ searchTag=Тег поиска doYouReallyWantToRemoveLeaderboard=Действительно удалить таблицу лидеров ''{0}''? metaLeaderboardCannotBeChanged=Это метатаблица лидеров. Изменить ее здесь невозможно. failedToSetNewStartTime=Не удалось установить новое время старта. Возможно, такое же время старта уже присутствует в журнале гонки или кто-то добавить более новое (ид. прохождения и логическое время) время старта, чем добавленное вами. +failedToSetNewFinishingAndFinishTime=Не удалось установить новое время финиширования и финиша. doYouReallyWantToRemoveIgtimiAccount=Действительно удалить учетную запись Igtimi, предоставляющую доступ к данным пользователя {0}? igtimiWindImport=Импортировать ветер из Igtimi seeIgtimiTabForAccountSettings=Параметры учетной записи, определяющие учитываемые данные из Igtimi, см. на вкладке ''Igtimi''. @@ -1915,6 +1918,10 @@ currentStbdRudderRake=Скос задней кромки руля на прав currentStbdRudderRakeTooltip=Текущий скос задней кромки руля на правый борт currentMastRotationInDegree=Вращение мачты currentMastRotationInDegreeTooltip=Текущее значение вращения мачты в градусах +finishingTime=Время финиширования +finishTimeString=Время финиша +setFinishingAndFinishTime=Указать время финиширования и финиша +finishTimeMustBeAtOrAfterFinishingTime=Время финиша должно совпадать или быть после времени финиширования boatNameMustNotBeEmpty=Укажите непустое имя лодки errorUpdatingExpeditionDeviceConfiguration=Ошибка при обновлении конфигурации устройства Expedition "{0}": {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=Действительно удалить конфигурацию устройства Expedition "{0}"? @@ -1926,3 +1933,39 @@ editExpeditionDeviceConfiguration=Редактировать конфигура expeditionBoatId=Ид. лодки (например, 0, 1, или 2) doYouReallyWantToRemoveTheSelectedExpeditionDeviceConfigurations=Действительно удалить выбранные конфигурации устройства Expedition? doYouReallyWantToRemoveTheSelectedIgtimiAccounts=Действительно удалить выбранные учетные записи Igtimi? +currentDepthInMeters=Глубина +currentDriftInDegrees=Скорость течения +currentLeewayInDegrees=Дрейф +currentRudderInDegrees=Перо руля +currentSet=Направление течения +currentTackAngleInDegrees=Галсовый угол +currentDeflectorInMillimeters=Дистанция для отражателя +currentDeflectorPercentage=Коэффициент отражателя +currentForestayLoad=Нагрузка форштага +currentForestayPressure=Давление форштага +currentRakeInDegrees=Продольный наклон мачты +currentTargetBoatspeedPercentage=Целевая скорость лодки +currentTargetHeelAngleInDegrees=Целевой крен +percent=% +currentTargetHeelAngleInDegreesTooltip=Целевой угол крена для улучшения эффективности +currentTargetBoatspeedPercentageTooltip=Процент достижения расчетной целевой скорости лодки +currentRakeInDegreesTooltip=Наклон мачты +currentForestayLoadTooltip=Нагрузка форштага, измеренная датчиком нагрузки +currentForestayPressureTooltip=Давление форштага +currentDeflectorPercentageTooltip=Процент отражателя +currentDeflectorInMillimetersTooltip=Дистанция для отражателя +currentTackAngleInDegreesTooltip=Расчетный оптимальный галсовый угол +currentSetTooltip=Направление течения (???) +currentRudderInDegreesTooltip=Угол отклонения руля; отрицательные значения означают отклонение по левому борту, положительные - отклонение по правому +currentLeewayInDegreesTooltip=Боковой снос +currentDriftInDegreesTooltip=Угол между направлением и курсом лодки относительно земли +currentDepthInMetersTooltip=Глубина воды +tonsUnit=т +currentDistanceFoiledInMeters=Дистанция в крыльевом режиме +currentDurationFoiled=Время в крыльевом режиме +currentDistanceFoiledInMetersTooltip=Дистанция в метрах, пройденная в крыльевом режиме +currentDurationFoiledTooltip=Время в крыльевом режиме +totalDurationFoiledInSeconds=Общее время в крыльевом режиме +totalDistanceFoiledInMeters=Общая дистанция в крыльевом режиме +totalDurationFoiledInSecondsTooltip=Общее время в крыльевом режиме, по всей таблице лидеров +totalDistanceFoiledInMetersTooltip=Общая дистанция в крыльевом режиме, по всей таблице лидеров diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties index 92fbab7c54b..e8cda9966b8 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties @@ -183,6 +183,7 @@ in=于 secondsUnit=s secondsPerNauticalMileUnit=s/NM metersUnit=m +millimetersUnit=mm degreesUnit=° close=关闭 compareCompetitors=比较参赛队 @@ -992,7 +993,8 @@ overwriteRacingProceduresConfiguration=激活比赛配置 overwriteRacingProceduresConfigurationHelpText=启用此选项将为比赛特定的配置中所有未配置的选项提供基本比赛配置。 setStartTime=设置开始时间 currentPass=当前绕标 -setStartTimeDescription=为比赛轮次选择新开始时间。 如果要将开始时间设置为过去的时间点,需要启用此复选框更新场次计数。 请注意,更改场次计数将丢失先前场次的所有信息(例如旗标活动)。 +setFinishingAndFinishTimeDescription=为比赛轮次选择新终点和结束时间。 +setStartTimeDescription=为比赛轮次选择新开始时间。如果要将开始时间设置为过去的时间点,需要启用此复选框更新场次计数。请注意,更改场次计数将丢失先前场次的所有信息(例如旗标活动)。 setTrackingTimesDescription=设置比赛轮次跟踪的开始和结束。 hasAdditionalGolfDownTime=激活附加高尔夫故障时间 additionalGolfDownTimeHelpText=激活附加高尔夫故障时间 @@ -1020,6 +1022,7 @@ searchTag=搜索标记 doYouReallyWantToRemoveLeaderboard=是否确定移除积分榜:''''{0}''''? metaLeaderboardCannotBeChanged=此为元积分榜。无法在此处更改。 failedToSetNewStartTime=设置新开始时间失败。 相同的开始时间可能已存在于比赛轮次日志中或某人已添加(场次编号和逻辑时间)更新的开始时间。 +failedToSetNewFinishingAndFinishTime=设置新结束和完成时间失败。 doYouReallyWantToRemoveIgtimiAccount=是否确定移除授予用户{0}访问数据权限的 Igtimi 账户? igtimiWindImport=从 Igtimi 导入风力数据 seeIgtimiTabForAccountSettings=请查看 "Igtimi" 选项卡了解账户设置,确定将考虑的 Igtimi 数据。 @@ -1915,6 +1918,10 @@ currentStbdRudderRake=右舵倾斜度 currentStbdRudderRakeTooltip=当前右舵倾斜度 currentMastRotationInDegree=桅杆旋转度 currentMastRotationInDegreeTooltip=当前桅杆旋转度数 +finishingTime=结束时间 +finishTimeString=终点线时间 +setFinishingAndFinishTime=设置结束和终点线时间 +finishTimeMustBeAtOrAfterFinishingTime=终点线时间必须与结束时间相同或在其之后 boatNameMustNotBeEmpty=请提供非空船只名称 errorUpdatingExpeditionDeviceConfiguration=更新导航图设备配置 "{0}" 出错:{1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=是否确定移除导航图设备配置 "{0}"? @@ -1926,3 +1933,39 @@ editExpeditionDeviceConfiguration=编辑导航图设备配置 expeditionBoatId=船只编号(例如 0、1 或 2) doYouReallyWantToRemoveTheSelectedExpeditionDeviceConfigurations=是否确定移除所选的导航图设备配置? doYouReallyWantToRemoveTheSelectedIgtimiAccounts=是否确定移除所选的 Igtimi 账户? +currentDepthInMeters=深度 +currentDriftInDegrees=漂移 +currentLeewayInDegrees=航差角 +currentRudderInDegrees=船舵 +currentSet=扬帆 +currentTackAngleInDegrees=迎风转向角度 +currentDeflectorInMillimeters=转向器距离 +currentDeflectorPercentage=转向器比率 +currentForestayLoad=前桅支索负荷 +currentForestayPressure=前桅支索压力 +currentRakeInDegrees=倾斜度 +currentTargetBoatspeedPercentage=目标船只速度 +currentTargetHeelAngleInDegrees=目标侧倾 +percent=% +currentTargetHeelAngleInDegreesTooltip=实现最佳性能的目标侧倾角 +currentTargetBoatspeedPercentageTooltip=达到计算的目标船只速度的百分比 +currentRakeInDegreesTooltip=桅倾度 +currentForestayLoadTooltip=前桅支索负荷,通过负荷传感器测量 +currentForestayPressureTooltip=前桅支索压力 +currentDeflectorPercentageTooltip=转向器百分比 +currentDeflectorInMillimetersTooltip=转向器距离 +currentTackAngleInDegreesTooltip=计算的最佳迎风转向角度 +currentSetTooltip=扬帆 (???) +currentRudderInDegreesTooltip=舵角;负值表示左舵,正值表示右舵 +currentLeewayInDegreesTooltip=航差角 +currentDriftInDegreesTooltip=航向与对地航向之间的角度 +currentDepthInMetersTooltip=水深 +tonsUnit=t +currentDistanceFoiledInMeters=水翼腾空距离 +currentDurationFoiled=水翼腾空时间 +currentDistanceFoiledInMetersTooltip=水翼腾空所用的距离(米) +currentDurationFoiledTooltip=水翼腾空所用时间 +totalDurationFoiledInSeconds=水翼腾空总时间 +totalDistanceFoiledInMeters=水翼腾空总距离 +totalDurationFoiledInSecondsTooltip=水翼腾空总时间(在整个积分榜中) +totalDistanceFoiledInMetersTooltip=水翼腾空总距离(在整个积分榜中) From ef95077c9d42a3025ffe8c6183e63d0fde843e1f Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 29 Nov 2017 14:24:11 +0000 Subject: [PATCH 04/14] Updated bug2822 review (markdown) --- wiki/bug2822-review.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wiki/bug2822-review.md b/wiki/bug2822-review.md index 1663e0d89f5..3dfa92c5f73 100644 --- a/wiki/bug2822-review.md +++ b/wiki/bug2822-review.md @@ -27,6 +27,14 @@ Check: ### 1.3 Migrate the raceLog and regattaLog? +We need to be very careful with refactoring here as the logic to load RaceLog/RegattaLog events relies on the class names, see com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl.loadRaceLogEvent(DBObject dbObject)... + + if (eventClass.equals(RaceLogRegisterCompetitorEvent.class.getSimpleName())) { + return loadRaceLogRegisterCompetitorEvent(..., dbObject); + } + +So we really need to keep the class names also for legacy events or we must rewrite the 'RACE_LOG_EVENT_CLASS' or 'REGATTA_LOG_EVENT_CLASS' property of the RaceLog/RegattaLog database entries. + ## 2. Managing boats Boats can be created now in different ways: From 8f569c324161d05157ff1c90c692bb7dbf0f51ae Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 29 Nov 2017 15:41:01 +0000 Subject: [PATCH 05/14] Updated bug2822 review (markdown) --- wiki/bug2822-review.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/wiki/bug2822-review.md b/wiki/bug2822-review.md index 3dfa92c5f73..32490a55d21 100644 --- a/wiki/bug2822-review.md +++ b/wiki/bug2822-review.md @@ -108,6 +108,16 @@ Check: ## 5. Smartphone Tracking (SPT) +### 5.1 Regatta where boats CAN NOT change per race - Competitors (with boats) are registered on regatta level + +Check: + +- Create a simple SPT regatta where boats can not change per race +- Open 'Competitor registrations' dialog +- Dialog must show 'Add Competitor' button +- Dialog must show only competitors with a linked boat in the 'Competitor pool' table on the right side +- The registered competitor must be added to regattaLog via the RegattaLogRegisterCompetitorAndBoatEvent + ## 6. Incremental Leaderboard Make sure that attribute changes of competitors and boats in the admin console are reflected in the leaderboard shown to the user From 0e0e65fb8af9cc0caf4af98f7e63a60a04642b23 Mon Sep 17 00:00:00 2001 From: Jonas Dann Date: Thu, 30 Nov 2017 13:27:32 +0000 Subject: [PATCH 06/14] Updated permission concept (markdown) --- wiki/info/security/permission-concept.md | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/wiki/info/security/permission-concept.md b/wiki/info/security/permission-concept.md index 965ae52798c..aeff1626c06 100644 --- a/wiki/info/security/permission-concept.md +++ b/wiki/info/security/permission-concept.md @@ -201,3 +201,36 @@ With such an extensive existing system as the Sailing Analytics Suite, migration Another challenge besides the code changes is the data migration. For every existing data object an ACL has to be created and filled with the right permissions so the users do not notice a big change. Besides creating an ACL for every data objects that is access controlled, an owner has to be defined for each existing data object, so that in combination with the ACLs no user loses permissions they need to have. In order to do this, where will have to be a script that associates all data objects on a server with a tenant and a specific user as owner (e.g. on the archive all data objects are associated with the tenant “archive” and owned by the user “Axel”). Thereafter, the users on the server are assigned their respective role. + +**Role Migration** + +Following roles have to be migrated to dynamic roles. Beforehand they were hard coded in the SailingPermissionsForRoleProvider class. However, aside from the admin role, all roles listed here are only containing permissions that are checked in the frontend for showing/hiding tabs in the different menus. + +* admin + * "*" +* eventmanager + * "manage_media" + * "manage_mark_passings" + * "manage_mark_positions" + * "manage_all_competitors" + * "manage_course_layout" + * "manage_device_configuration" + * "manage_events" + * "manage_igtimi_accounts" + * "manage_leaderboard_groups" + * "manage_leaderboards" + * "manage_leaderboard_results" + * "manage_racelog_tracking" + * "manage_regattas" + * "manage_result_import_urls" + * "manage_structure_import_urls" + * "manage_tracked_races" + * "manage_wind" + * "event" + * "regatta" + * "leaderboard" + * "leaderboard_group" +* mediaeditor + * "manage_media" +* moderator + * "can_replay_during_live_races" From 36204b2ef115ab7d4fd24b420621079d6d9bf92a Mon Sep 17 00:00:00 2001 From: Jonas Dann Date: Thu, 30 Nov 2017 16:31:32 +0000 Subject: [PATCH 07/14] Updated permission concept (markdown) --- wiki/info/security/permission-concept.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wiki/info/security/permission-concept.md b/wiki/info/security/permission-concept.md index aeff1626c06..387b164d892 100644 --- a/wiki/info/security/permission-concept.md +++ b/wiki/info/security/permission-concept.md @@ -234,3 +234,6 @@ Following roles have to be migrated to dynamic roles. Beforehand they were hard * "manage_media" * moderator * "can_replay_during_live_races" + +## Implementation + From 841f1daf94545f96f16bc43e73149075ab3f666f Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Thu, 30 Nov 2017 16:36:40 +0000 Subject: [PATCH 08/14] Updated bug2822 review (markdown) --- wiki/bug2822-review.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wiki/bug2822-review.md b/wiki/bug2822-review.md index 32490a55d21..9b20fe6178a 100644 --- a/wiki/bug2822-review.md +++ b/wiki/bug2822-review.md @@ -10,7 +10,8 @@ Bug 2822 changes the way competitors and boats are handled. Specifically the 1:1 Check: -- Existing COMPETITORS Collection is migrated to COMPETITORS_WITH_BOAT_REFERENCES and BOATS collection +- Existing COMPETITORS Collection is renamed to COMPETITORS_BAK collection +- Competitors from COMPETITORS_BAK collection will be migrated to COMPETITORS and BOATS collection - All migrated competitors have a link to a boat from boats collection - The attribute 'name' is cleared in new all created boat objects as the old names were not meaningful and not used @@ -21,7 +22,7 @@ In case of a server instance with already created competitors we don't know to w Check: - Before server start an existing competitor with emedded boat does exist in the COMPETITORS collection -- After server start and migration according to 1.1 this competitor does exist in the COMPETITORS_WITH_BOAT_REFERENCES collection and does have a link to a boat in the BOATS collection +- After server start and migration according to 1.1 this competitor does exist in the COMPETITORS collection and does have a link to a boat in the BOATS collection - After starting the tractrac tracking of a race where this competitor is contained the tractrac connector recognizes the need for the migration and calls the corresponding function on the CompetitorStore - After the migration the competitor does not have a boat reference anymore and the migrated boat has the right properties From c7f50c389ffd3ec1250845e84bb93bfeeb061638 Mon Sep 17 00:00:00 2001 From: Jonas Dann Date: Thu, 30 Nov 2017 16:46:04 +0000 Subject: [PATCH 09/14] Updated permission concept (markdown) --- wiki/info/security/permission-concept.md | 29 +++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/wiki/info/security/permission-concept.md b/wiki/info/security/permission-concept.md index 387b164d892..c18a528f104 100644 --- a/wiki/info/security/permission-concept.md +++ b/wiki/info/security/permission-concept.md @@ -16,6 +16,8 @@ * [Use Cases](#use cases) * [Algorithm for Composite Realm](#algorithm-bool-haspermission-wildcardpermission-permission-for-composite-realm) * [Migration](#migration) +* [Implementation Details](#implementation-details) +* [TODOs](#todos) ## Introduction @@ -235,5 +237,30 @@ Following roles have to be migrated to dynamic roles. Beforehand they were hard * moderator * "can_replay_during_live_races" -## Implementation +## Implementation Details + + +## TODOs + +Dump of TODOs. More structured in Bugzilla. + +* Ownership/Access control list as expandable column in all access controlled data object tables +* Permission checking for every domain data object type +* Changing ownership (incl. replication) +* Masterdataimport +* Tenant management UI + * Tenant in create dialog check if tenant exists (red outline of text input field) + * Refresh tenant selection in tenant list on the left correctly + * String messages +* User management UI + * Auto complete for roles and permissions +* Access control list / Roles / Ownership UI +* User role for editing own user parametrized by user name +* Do we want to throw unauthorized exceptions or how should this work? (See addUserToTenant or removeUserFromTenant) / UnauthorizedException handling (i.e. popup that shows some text) +* Create ownerships from config / Server-wide default owner and default tenant owner +* Create test setup for final test +* Button to transfer ownership of all objects from one user/tenant to another user/tenant (chgroup recursive?) +* Rework meta permissions (rework to also check all permissions that are granted or revoked?) +* Permission reloading without site refresh / Frontend update elements that require permission when permissions change (Refresh call on panels) +* Default tenant input field in login popup From faf47f9d17764da57d64631738a968342fd0c45e Mon Sep 17 00:00:00 2001 From: Jonas Dann Date: Thu, 30 Nov 2017 17:04:33 +0000 Subject: [PATCH 10/14] Updated permission concept (markdown) --- wiki/info/security/permission-concept.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki/info/security/permission-concept.md b/wiki/info/security/permission-concept.md index c18a528f104..f2c4fa8aead 100644 --- a/wiki/info/security/permission-concept.md +++ b/wiki/info/security/permission-concept.md @@ -239,7 +239,7 @@ Following roles have to be migrated to dynamic roles. Beforehand they were hard ## Implementation Details - +Access control relevant objects are stored in the AccessControlStore, while user related objects are stored in the user, i.e. the UserStore. Tenants are currently stored as UserGroups in the user store. The algorithm outlined above is implemented in the PermissionChecker, which is one of the most central classes in the permission system. Therefrom it should be possible to find all other relevant classes. Other relevant classes include the AbstractCompositeAuthorizingRealm that implements permission checking in Shiro. Therefor it uses the PermissionChecker and is connected to the UserStore and the AccessControlStore. Furthermore the RolePermissionModel implements how roles imply permissions. The RolePermissionModel as well as the parameterization of roles need more work and are just a rough sketch. The UserManagementService exposes most of the access control relevant parts to the frontend. It works through the SecurityService with the AccessControlStore and the UserStore. Permission checking in the frontend is also done with the PermissionChecker. To ease the creation of WildcardPermissions, a PermissionBuilder was introduced that also needs some more work. All access control relevant UI parts can be found in the "Advanced" tab under "User management" and "Tenant management". A further tab "Access Control Management" should be introduced. Unit tests can be found in the package com.sap.sse.security.test. ## TODOs From 0be5519db933b4a646a2ec556e71027065ae5959 Mon Sep 17 00:00:00 2001 From: Simon Pamies Date: Fri, 1 Dec 2017 18:51:36 +0100 Subject: [PATCH 11/14] Updated HttpUrlConnectionHelper to support setting a longer read timeout. This is especially useful when expecting responses that are very big and need a long time to compute on the client. --- .../sailing/gwt/ui/server/SailingServiceImpl.java | 3 ++- .../com/sap/sse/util/HttpUrlConnectionHelper.java | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index cf84f828d7f..d8da768a915 100644 --- 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 @@ -4815,7 +4815,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S URL base = createBaseUrl(urlAsString); String path = "/sailingserver/spi/v1/masterdata/leaderboardgroups"; serverAddress = createUrl(base, path, query); - connection = HttpUrlConnectionHelper.redirectConnection(serverAddress); + // the response can take a very long time for MDI that include foiling data or such + connection = HttpUrlConnectionHelper.redirectConnection(serverAddress, Duration.ONE_HOUR.times(2)); getService().createOrUpdateDataImportProgressWithReplication(importOperationId, 0.02, DataImportSubProgress.CONNECTION_ESTABLISH, 0.5); if (compress) { diff --git a/java/com.sap.sse/src/com/sap/sse/util/HttpUrlConnectionHelper.java b/java/com.sap.sse/src/com/sap/sse/util/HttpUrlConnectionHelper.java index 777c1447674..49d5020371c 100644 --- a/java/com.sap.sse/src/com/sap/sse/util/HttpUrlConnectionHelper.java +++ b/java/com.sap.sse/src/com/sap/sse/util/HttpUrlConnectionHelper.java @@ -10,7 +10,11 @@ import com.sap.sse.common.Duration; public class HttpUrlConnectionHelper { private static final int HTTP_MAX_REDIRECTS = 5; - public static HttpURLConnection redirectConnection(URL url) throws MalformedURLException, IOException { + /** + * Redirects the connection using the Location header. Make sure to set + * the timeout if you expect the response to take longer. + */ + public static HttpURLConnection redirectConnection(URL url, Duration timeout) throws MalformedURLException, IOException { HttpURLConnection connection = null; URL nextUrl = url; for (int counterOfRedirects = 0; counterOfRedirects <= HTTP_MAX_REDIRECTS; counterOfRedirects++) { @@ -21,8 +25,7 @@ public class HttpUrlConnectionHelper { connection.setInstanceFollowRedirects(false); connection.setRequestProperty("User-Agent", "Mozilla/5.0..."); connection.setDoOutput(true); - // Initial timeout needs to be big enough to allow the first parts of the response to reach this server - connection.setReadTimeout((int) Duration.ONE_MINUTE.times(10).asMillis()); + connection.setReadTimeout((int) timeout.asMillis()); if (connection.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM || connection.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP) { String location = connection.getHeaderField("Location"); @@ -33,4 +36,8 @@ public class HttpUrlConnectionHelper { } return connection; } + + public static HttpURLConnection redirectConnection(URL url) throws MalformedURLException, IOException { + return redirectConnection(url, Duration.ONE_MINUTE.times(10)); + } } From dc24184baa0f6f68a199030155b09eea4d1d7531 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sun, 3 Dec 2017 13:56:35 +0100 Subject: [PATCH 12/14] bug 4387: notify listeners about sensor track addition outside of write lock Change-Id: I1a6f8630f381848acd579787e9a8022f10438110 --- .../tracking/impl/DynamicTrackedRaceImpl.java | 7 ++--- .../domain/tracking/impl/TrackedRaceImpl.java | 26 ++++++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java index 66312ec0b68..1639d123330 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java @@ -13,6 +13,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NavigableSet; +import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; @@ -609,7 +610,7 @@ DynamicTrackedRace, GPSTrackListener { notifyListeners(listener -> listener.markPassingReceived(competitor, oldMarkPassings, markPassings)); } - private void notifyListeners(DynamicSensorFixTrack track) { + private void notifyListenersAboutSensorTrackAdded(DynamicSensorFixTrack track) { notifyListeners(listener -> listener.competitorSensorTrackAdded(track)); } @@ -1206,7 +1207,7 @@ DynamicTrackedRace, GPSTrackListener { } @Override - protected void addSensorTrackInternal(Pair key, + protected Optional addSensorTrackInternal(Pair key, DynamicSensorFixTrack track) { super.addSensorTrackInternal(key, track); track.addListener(new SensorFixTrackListener() { @@ -1222,6 +1223,6 @@ DynamicTrackedRace, GPSTrackListener { notifyListeners(item, trackName, fix); } }); - notifyListeners(track); + return Optional.of(()->notifyListenersAboutSensorTrackAdded(track)); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index 3767441eff5..c33750f7576 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NavigableSet; +import java.util.Optional; import java.util.Set; import java.util.Timer; import java.util.TimerTask; @@ -4147,40 +4148,53 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl protected > TrackT getOrCreateSensorTrack( Competitor competitor, String trackName, TrackFactory newTrackFactory) { Pair key = new Pair<>(competitor, trackName); + Optional executeAfterReleasingLock = Optional.empty(); + TrackT result; LockUtil.lockForWrite(sensorTracksLock); try { - TrackT result = getTrackInternal(key); + result = getTrackInternal(key); if (result == null && tracks.containsKey(competitor)) { // A track is only added if the given Competitor is known to participate in this race result = newTrackFactory.get(); - addSensorTrackInternal(key, result); + executeAfterReleasingLock = addSensorTrackInternal(key, result); } - return result; } finally { LockUtil.unlockAfterWrite(sensorTracksLock); } + executeAfterReleasingLock.ifPresent(r->r.run()); + return result; } protected void addSensorTrack(Competitor competitor, String trackName, DynamicSensorFixTrack track) { Pair key = new Pair<>(competitor, trackName); + Optional executeAfterReleasingLock = Optional.empty(); LockUtil.lockForWrite(sensorTracksLock); try { - if(getTrackInternal(key) != null) { + if (getTrackInternal(key) != null) { if (logger != null && logger.getLevel() != null && logger.getLevel().equals(Level.WARNING)) { logger.warning(SensorFixTrack.class.getName() + " already exists for competitor: " + competitor.getName() + "; trackName: " + trackName); } } else { - this.addSensorTrackInternal(key, track); + executeAfterReleasingLock = this.addSensorTrackInternal(key, track); } } finally { LockUtil.unlockAfterWrite(sensorTracksLock); } + executeAfterReleasingLock.ifPresent(r->r.run()); } - protected void addSensorTrackInternal(Pair key, + /** + * To call this method, the caller must have obtained the write lock of {@link #sensorTracksLock}. + * Optionally, the method may return a {@link Runnable} to execute after the lock has been released. + * This may, e.g., be a routine that notifies listeners. Callers are responsible for invoking this + * {@link Runnable} after releasing the write lock. + */ + protected Optional addSensorTrackInternal(Pair key, DynamicSensorFixTrack track) { + assert sensorTracksLock.isWriteLockedByCurrentThread(); sensorTracks.put(key, track); + return Optional.empty(); } @SuppressWarnings("unchecked") From 28ffdac19f9180a35759a9d39de75253d7b90d8e Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sun, 3 Dec 2017 15:07:02 +0100 Subject: [PATCH 13/14] bug 4387: fix for comment #4, making gpsTrack transient on BravoFixTrackImpl, filling when track is added to TrackedRace Change-Id: Icba632c7cf033aeadf7db8cffaa1010be6183e69 --- .../impl/BravoDataFixMapper.java | 4 +-- .../impl/BravoExtendedDataFixMapper.java | 4 +-- .../impl/ExpeditionExtendedDataFixMapper.java | 4 +-- .../tracking/DynamicSensorFixTrack.java | 6 +++- .../tracking/impl/BravoFixTrackImpl.java | 28 ++++++++++++++----- .../impl/CompetitorBravoFixTrackImpl.java | 26 +++++++++++++++++ .../domain/tracking/impl/TrackedRaceImpl.java | 1 + 7 files changed, 59 insertions(+), 14 deletions(-) create mode 100755 java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompetitorBravoFixTrackImpl.java diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/BravoDataFixMapper.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/BravoDataFixMapper.java index 3415d44f166..da5934327e4 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/BravoDataFixMapper.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/BravoDataFixMapper.java @@ -10,7 +10,7 @@ import com.sap.sailing.domain.racelog.tracking.SensorFixMapper; import com.sap.sailing.domain.tracking.BravoFixTrack; import com.sap.sailing.domain.tracking.DynamicSensorFixTrack; import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.impl.BravoFixTrackImpl; +import com.sap.sailing.domain.tracking.impl.CompetitorBravoFixTrackImpl; /** * {@link SensorFixMapper} implementation to handle {@link BravoFix}es. @@ -20,7 +20,7 @@ public class BravoDataFixMapper implements SensorFixMapper getTrack(DynamicTrackedRace race, Competitor key) { return race.getOrCreateSensorTrack(key, BravoFixTrack.TRACK_NAME, - () -> new BravoFixTrackImpl(key, BravoFixTrack.TRACK_NAME, /* hasExtendedFixes */ false, + () -> new CompetitorBravoFixTrackImpl(key, BravoFixTrack.TRACK_NAME, /* hasExtendedFixes */ false, race.getTrack(key))); } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/BravoExtendedDataFixMapper.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/BravoExtendedDataFixMapper.java index f35509b8ec3..15f96e22bc9 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/BravoExtendedDataFixMapper.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/BravoExtendedDataFixMapper.java @@ -11,7 +11,7 @@ import com.sap.sailing.domain.racelog.tracking.SensorFixMapper; import com.sap.sailing.domain.tracking.BravoFixTrack; import com.sap.sailing.domain.tracking.DynamicSensorFixTrack; import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.impl.BravoFixTrackImpl; +import com.sap.sailing.domain.tracking.impl.CompetitorBravoFixTrackImpl; /** * {@link SensorFixMapper} implementation to handle {@link BravoExtendedFix}es. @@ -21,7 +21,7 @@ public class BravoExtendedDataFixMapper implements SensorFixMapper getTrack(DynamicTrackedRace race, Competitor key) { return race.getOrCreateSensorTrack(key, BravoFixTrack.TRACK_NAME, - () -> new BravoFixTrackImpl(key, BravoFixTrack.TRACK_NAME, /* hasExtendedFixes */ true, + () -> new CompetitorBravoFixTrackImpl(key, BravoFixTrack.TRACK_NAME, /* hasExtendedFixes */ true, race.getTrack(key))); } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/ExpeditionExtendedDataFixMapper.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/ExpeditionExtendedDataFixMapper.java index 5dcf9db8119..09405591969 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/ExpeditionExtendedDataFixMapper.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/ExpeditionExtendedDataFixMapper.java @@ -11,7 +11,7 @@ import com.sap.sailing.domain.racelog.tracking.SensorFixMapper; import com.sap.sailing.domain.tracking.BravoFixTrack; import com.sap.sailing.domain.tracking.DynamicSensorFixTrack; import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.impl.BravoFixTrackImpl; +import com.sap.sailing.domain.tracking.impl.CompetitorBravoFixTrackImpl; /** * {@link SensorFixMapper} implementation to product {@link BravoExtendedFix}es from {@link DoubleVectorFix}es @@ -25,7 +25,7 @@ public class ExpeditionExtendedDataFixMapper implements SensorFixMapper getTrack(DynamicTrackedRace race, Competitor key) { return race.getOrCreateSensorTrack(key, BravoFixTrack.TRACK_NAME, - () -> new BravoFixTrackImpl(key, BravoFixTrack.TRACK_NAME, /* hasExtendedFixes */ true, + () -> new CompetitorBravoFixTrackImpl(key, BravoFixTrack.TRACK_NAME, /* hasExtendedFixes */ true, race.getTrack(key))); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicSensorFixTrack.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicSensorFixTrack.java index e6dd60f720c..86afdb43785 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicSensorFixTrack.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicSensorFixTrack.java @@ -13,5 +13,9 @@ import com.sap.sse.common.WithID; */ public interface DynamicSensorFixTrack extends SensorFixTrack, DynamicTrack { - + /** + * Invoked when this track is added to a tracked race. This default implementation + * does nothing. + */ + default void addedToTrackedRace(TrackedRace trackedRace) {} } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java index bb6e27ca4c1..f05020eefd6 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java @@ -45,7 +45,7 @@ public class BravoFixTrackImpl extends S * If a GPS track was provided at construction time, remember it non-transiently. It is needed when restoring * the object after de-serialization, so the cache invalidation listener can be re-established. */ - private GPSFixTrack gpsTrack; + private transient GPSFixTrack gpsTrack; private class CacheInvalidationGpsTrackListener implements GPSTrackListener { private static final long serialVersionUID = 6395529765232404414L; @@ -89,6 +89,23 @@ public class BravoFixTrackImpl extends S this.foilingTimeCache = createFoilingTimeCache(trackedItem); this.foilingDistanceCache = createFoilingDistanceCache(trackedItem); this.averageRideHeightCache = createAverageRideHeightCache(trackedItem); + setGpsTrack(gpsTrack); + } + + protected GPSFixTrack getGpsTrack() { + return gpsTrack; + } + + /** + * Sets the {@link #gpsTrack} field and registers a cache invalidation listener + * on the {@code gpsTrack} to ensure that the foiling distance is invalidated if needed.

+ * + * Must be called only once for a non-{@code null} {@code gpsTrack}. + */ + protected void setGpsTrack(GPSFixTrack gpsTrack) { + if (gpsTrack != null) { + assert this.gpsTrack == null; + } this.gpsTrack = gpsTrack; if (gpsTrack != null) { gpsTrack.addListener(new CacheInvalidationGpsTrackListener()); @@ -119,9 +136,6 @@ public class BravoFixTrackImpl extends S this.foilingTimeCache = createFoilingTimeCache(getTrackedItem()); this.foilingDistanceCache = createFoilingDistanceCache(getTrackedItem()); this.averageRideHeightCache = createAverageRideHeightCache(getTrackedItem()); - if (gpsTrack != null) { - gpsTrack.addListener(new CacheInvalidationGpsTrackListener()); - } } @Override @@ -215,8 +229,8 @@ public class BravoFixTrackImpl extends S @Override public Distance getDistanceSpentFoiling(TimePoint from, TimePoint to) { - assert gpsTrack != null; - return getValueSum(from, to, /* nullElement */ Distance.NULL, Distance::add, foilingDistanceCache, + return getGpsTrack() == null ? null : + getValueSum(from, to, /* nullElement */ Distance.NULL, Distance::add, foilingDistanceCache, /* valueCalculator */ new Track.TimeRangeValueCalculator() { @Override public Distance calculate(TimePoint from, TimePoint to) { @@ -226,7 +240,7 @@ public class BravoFixTrackImpl extends S for (final BravoFix fix : getFixes(from, true, to, true)) { final boolean fixFoils = isFoiling(fix); if (isFoiling && fixFoils) { - result = result.add(gpsTrack.getDistanceTraveled(last, fix.getTimePoint())); + result = result.add(getGpsTrack().getDistanceTraveled(last, fix.getTimePoint())); } last = fix.getTimePoint(); isFoiling = fixFoils; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompetitorBravoFixTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompetitorBravoFixTrackImpl.java new file mode 100755 index 00000000000..261e1393c4e --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompetitorBravoFixTrackImpl.java @@ -0,0 +1,26 @@ +package com.sap.sailing.domain.tracking.impl; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.TrackedRace; + +public class CompetitorBravoFixTrackImpl extends BravoFixTrackImpl { + private static final long serialVersionUID = 569731925060211875L; + + public CompetitorBravoFixTrackImpl(Competitor trackedItem, String trackName, boolean hasExtendedFixes, + GPSFixTrack gpsTrack) { + super(trackedItem, trackName, hasExtendedFixes, gpsTrack); + } + + public CompetitorBravoFixTrackImpl(Competitor trackedItem, String trackName, boolean hasExtendedFixes) { + super(trackedItem, trackName, hasExtendedFixes); + } + + @Override + public void addedToTrackedRace(TrackedRace trackedRace) { + if (this.getGpsTrack() == null) { + this.setGpsTrack(trackedRace.getTrack(getTrackedItem())); + } + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index c33750f7576..934a2c1ffdb 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -4194,6 +4194,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl DynamicSensorFixTrack track) { assert sensorTracksLock.isWriteLockedByCurrentThread(); sensorTracks.put(key, track); + track.addedToTrackedRace(this); return Optional.empty(); } From 2e071764102a6e102e2a864fe77866873ff7255e Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sun, 3 Dec 2017 15:22:14 +0100 Subject: [PATCH 14/14] added failing test case for bug 4387 Change-Id: I5059f3cc94db585fa3a5da64ac50a285b13a1e6f --- .../tracking/DynamicSensorFixTrack.java | 5 ----- .../sailing/domain/tracking/DynamicTrack.java | 6 +++++ .../tracking/impl/BravoFixTrackImpl.java | 2 +- .../domain/tracking/impl/TrackedRaceImpl.java | 3 +++ .../TrackedRaceContentsReplicationTest.java | 22 +++++++++++++++++++ 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicSensorFixTrack.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicSensorFixTrack.java index 86afdb43785..04ae5bd1059 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicSensorFixTrack.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicSensorFixTrack.java @@ -13,9 +13,4 @@ import com.sap.sse.common.WithID; */ public interface DynamicSensorFixTrack extends SensorFixTrack, DynamicTrack { - /** - * Invoked when this track is added to a tracked race. This default implementation - * does nothing. - */ - default void addedToTrackedRace(TrackedRace trackedRace) {} } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java index 970e9fbf522..e857186da0d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrack.java @@ -25,4 +25,10 @@ public interface DynamicTrack extends Track { * @return true if the element was added, false otherwise. */ boolean add(FixType fix, boolean replace); + + /** + * Invoked when this track is added to a tracked race. The method is also invoked after de-serializing the + * containing {@link TrackedRace}. This default implementation does nothing. + */ + default void addedToTrackedRace(TrackedRace trackedRace) {} } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java index f05020eefd6..43f7fd881b4 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java @@ -92,7 +92,7 @@ public class BravoFixTrackImpl extends S setGpsTrack(gpsTrack); } - protected GPSFixTrack getGpsTrack() { + public GPSFixTrack getGpsTrack() { return gpsTrack; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index 934a2c1ffdb..d70a1e0f8a5 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -636,6 +636,9 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException, PatchFailedException { ois.defaultReadObject(); getRace().getCourse().addCourseListener(this); + for (DynamicTrack sensorTrack : sensorTracks.values()) { + sensorTrack.addedToTrackedRace(this); + } raceStates = new WeakHashMap<>(); attachedRaceLogs = new ConcurrentHashMap<>(); attachedRegattaLogs = new ConcurrentHashMap<>(); 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 ddc6f533c46..3a082388195 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 @@ -3,6 +3,7 @@ package com.sap.sailing.server.replication.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; import java.net.UnknownHostException; import java.util.ArrayList; @@ -45,11 +46,13 @@ import com.sap.sailing.domain.persistence.MongoWindStore; import com.sap.sailing.domain.persistence.MongoWindStoreFactory; import com.sap.sailing.domain.persistence.PersistenceFactory; import com.sap.sailing.domain.test.PositionAssert; +import com.sap.sailing.domain.tracking.BravoFixTrack; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.WindTrack; +import com.sap.sailing.domain.tracking.impl.CompetitorBravoFixTrackImpl; import com.sap.sailing.server.operationaltransformation.AddDefaultRegatta; import com.sap.sailing.server.operationaltransformation.AddRaceDefinition; import com.sap.sailing.server.operationaltransformation.CreateTrackedRace; @@ -138,6 +141,25 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio } } + /** + * See also bug4387: test that after replicating the TrackedRace the CompetitorBravoFixTrackImpl's gpsTrack object + * points to the track from the TrackedRace to which the CompetitorBravoFixTrackImpl belongs. + */ + @Test + public void testBravoFixTrackReplication() throws InterruptedException { + trackedRace.getOrCreateSensorTrack(competitor, BravoFixTrack.TRACK_NAME, () -> new CompetitorBravoFixTrackImpl(competitor, BravoFixTrack.TRACK_NAME, /* hasExtendedFixes */ false, + trackedRace.getTrack(competitor))); + Thread.sleep(1000); + DynamicTrackedRace replicaTrackedRace = replica.getTrackedRace(raceIdentifier); + Competitor replicaCompetitor = replicaTrackedRace.getRace().getCompetitors().iterator().next(); + assertNotNull(replicaCompetitor); + GPSFixTrack competitorTrack = replicaTrackedRace.getTrack(replicaCompetitor); + CompetitorBravoFixTrackImpl competitorSensorTrack = replicaTrackedRace.getOrCreateSensorTrack( + replicaCompetitor, BravoFixTrack.TRACK_NAME, () -> new CompetitorBravoFixTrackImpl(replicaCompetitor, BravoFixTrack.TRACK_NAME, /* hasExtendedFixes */ false, + replicaTrackedRace.getTrack(replicaCompetitor))); + assertSame(competitorTrack, competitorSensorTrack.getGpsTrack()); + } + @Test public void testMarkFixReplication() throws InterruptedException { final GPSFixMovingImpl fix = new GPSFixMovingImpl(new DegreePosition(2, 3), new MillisecondsTimePoint(3456),