mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-21 05:05:31 +00:00
Merge branch 'master' into bug2823
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
FROM donaldduck70/sapjvm8:8.1.073
|
||||
FROM donaldduck70/sapjvm8:8.1.078
|
||||
LABEL maintainer=axel.uhl@sap.com
|
||||
# Download and extract the release
|
||||
WORKDIR /home/sailing/servers/server
|
||||
@@ -12,6 +12,7 @@ RUN wget -O /tmp/RELEASE.tar.gz http://releases.sapsailing.com/RELEASE/RELEASE.t
|
||||
&& tar xzvpf /tmp/RELEASE.tar.gz \
|
||||
&& rm /tmp/RELEASE.tar.gz
|
||||
COPY env.sh .
|
||||
RUN cat env-default-rules.sh >>env.sh
|
||||
COPY start .
|
||||
COPY JavaSE-11.profile .
|
||||
EXPOSE 8888 14888 8000 7091 6666
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
FROM buildpack-deps:stretch-scm
|
||||
FROM buildpack-deps:latest
|
||||
LABEL maintainer=axel.uhl@sap.com
|
||||
# Download and extract the SAP JVM 8
|
||||
ENV PATH=${PATH}:/opt/sapjvm_8/bin
|
||||
ENV JAVA_HOME=/opt/sapjvm_8
|
||||
WORKDIR /opt
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y wget unzip \
|
||||
&& curl --cookie eula_3_1_agreed=tools.hana.ondemand.com/developer-license-3_1.txt "https://tools.hana.ondemand.com/additional/sapjvm-7.1.073-linux-x64.zip" --output sapjvm8-linux-x64.zip \
|
||||
&& apt-get install -y wget apt-utils unzip \
|
||||
&& apt-get -y upgrade \
|
||||
&& curl --cookie eula_3_1_agreed=tools.hana.ondemand.com/developer-license-3_1.txt "https://tools.hana.ondemand.com/additional/sapjvm-8.1.078-linux-x64.zip" --output sapjvm8-linux-x64.zip \
|
||||
&& unzip sapjvm8-linux-x64.zip \
|
||||
&& rm sapjvm8-linux-x64.zip \
|
||||
&& echo "export JAVA_HOME=/opt/sapjvm_8; export PATH=\${PATH}:/opt/sapjvm_8/bin" > /etc/profile.d/javahome.sh
|
||||
|
||||
+2
@@ -31,6 +31,7 @@ import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
@@ -131,6 +132,7 @@ public class WebSocketTest {
|
||||
Activator.getInstance().setSecurityService(null);
|
||||
}
|
||||
|
||||
@Ignore("echo.websocket.org is (2021-08-19) down; http://www.websocket.org/index.html says ''Service no longer available''")
|
||||
@Test
|
||||
public void simpleWebSocketEchoTest() throws Exception {
|
||||
String destUri = "ws://echo.websocket.org"; // wss currently doesn't seem to work with Jetty 9.0.4 WebSocket implementation
|
||||
|
||||
+1
-2
@@ -149,8 +149,7 @@ public class TracTracConnectivityParamsHandler extends AbstractRaceTrackingConne
|
||||
final String creatorName = SessionUtils.getPrincipal().toString();
|
||||
final TracTracConfigurationImpl tracTracConfiguration = new TracTracConfigurationImpl(creatorName, tractracRace.getEvent().getName(), jsonURL,
|
||||
(params.getLiveURI() == null ? null : params.getLiveURI().toString()),
|
||||
/* stored URI */ params.isPreferReplayIfAvailable() && params.isReplayRace(tractracRace)
|
||||
? null // we mainly want to enable the user to list the event's races again in case they are removed;
|
||||
/* stored URI */ params.isReplayRace(tractracRace) ? null // we mainly want to enable the user to list the event's races again in case they are removed;
|
||||
: (params.getStoredURI() == null ? null : params.getStoredURI().toString()), // live/stored stuff comes from the tracking params
|
||||
params.getCourseDesignUpdateURI()==null?null:params.getCourseDesignUpdateURI().toString(), params.getTracTracUsername(), params.getTracTracPassword());
|
||||
tractracMongoObjectFactory.updateTracTracConfiguration(tracTracConfiguration);
|
||||
|
||||
-1
@@ -56,7 +56,6 @@ public interface TracTracConfiguration extends WithQualifiedObjectIdentifier {
|
||||
}
|
||||
|
||||
public static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String jsonUrl, String username) {
|
||||
|
||||
return username == null ? new TypeRelativeObjectIdentifier(jsonUrl)
|
||||
: new TypeRelativeObjectIdentifier(jsonUrl, username);
|
||||
}
|
||||
|
||||
+1
-1
@@ -542,7 +542,7 @@ widthInPx=Bredde (pixel)
|
||||
heightInPx=Højde (pixel)
|
||||
tags=Tags
|
||||
size=Størrelse
|
||||
duration=Varighed (t:mm:ss.ms)
|
||||
duration=Varighed (t:mm:ss)
|
||||
addMediaTrack=Tilføj lyd/video
|
||||
addYoutubeTrack=Tilføj Youtube
|
||||
youtubeId=Youtube-id
|
||||
|
||||
+1
-1
@@ -542,7 +542,7 @@ widthInPx=Ancho (píxeles)
|
||||
heightInPx=Alto (píxeles)
|
||||
tags=Etiquetas
|
||||
size=Tamaño
|
||||
duration=Duración (h:mm:ss.ms)
|
||||
duration=Duración (h:mm:ss)
|
||||
addMediaTrack=Añadir audio/vídeo
|
||||
addYoutubeTrack=Añadir Youtube
|
||||
youtubeId=ID de Youtube
|
||||
|
||||
+1
-1
@@ -542,7 +542,7 @@ widthInPx=Largeur (pixel)
|
||||
heightInPx=Hauteur (pixel)
|
||||
tags=Balises
|
||||
size=Taille
|
||||
duration=Durée (h:mm:ss.ms)
|
||||
duration=Durée (h:mm:ss)
|
||||
addMediaTrack=Ajouter audio/vidéo
|
||||
addYoutubeTrack=Ajouter Youtube
|
||||
youtubeId=ID Youtube
|
||||
|
||||
+1
-1
@@ -542,7 +542,7 @@ widthInPx=Larghezza (pixel)
|
||||
heightInPx=Altezza (pixel)
|
||||
tags=Tags
|
||||
size=Dimensione
|
||||
duration=Durata (h:mm:ss.ms)
|
||||
duration=Durata (h:mm:ss)
|
||||
addMediaTrack=Aggiungi audio/video
|
||||
addYoutubeTrack=Aggiungi Youtube
|
||||
youtubeId=ID Youtube
|
||||
|
||||
+1
-1
@@ -542,7 +542,7 @@ widthInPx=幅 (ピクセル)
|
||||
heightInPx=高さ (ピクセル)
|
||||
tags=タグ
|
||||
size=サイズ
|
||||
duration=時間 (h:mm:ss.ms)
|
||||
duration=時間 (h:mm:ss)
|
||||
addMediaTrack=音声/動画追加
|
||||
addYoutubeTrack=YouTube 追加
|
||||
youtubeId=YouTube ID
|
||||
|
||||
+1
-1
@@ -542,7 +542,7 @@ widthInPx=Largura (pixels)
|
||||
heightInPx=Altura (pixels)
|
||||
tags=Etiquetas
|
||||
size=Tamanho
|
||||
duration=Duração (h:mm:ss.ms)
|
||||
duration=Duração (h:mm:ss)
|
||||
addMediaTrack=Adicionar áudio/vídeo
|
||||
addYoutubeTrack=Adicionar Youtube
|
||||
youtubeId=ID do Youtube
|
||||
|
||||
+1
-1
@@ -542,7 +542,7 @@ widthInPx=Ширина (в пикселях)
|
||||
heightInPx=Высота (в пикселях)
|
||||
tags=Теги
|
||||
size=Размер
|
||||
duration=Длительность (ч:мм:сс.мс)
|
||||
duration=Длительность (ч:мм:сс)
|
||||
addMediaTrack=Добавить аудио/видео
|
||||
addYoutubeTrack=Добавить Youtube
|
||||
youtubeId=Ид. Youtube
|
||||
|
||||
+1
-1
@@ -542,7 +542,7 @@ widthInPx=Širina (slikovne pike)
|
||||
heightInPx=Višina (slikovne pike)
|
||||
tags=Oznake
|
||||
size=Velikost
|
||||
duration=Trajanje (h:mm:ss.ms)
|
||||
duration=Trajanje (h:mm:ss)
|
||||
addMediaTrack=Dodaj zvok/video
|
||||
addYoutubeTrack=Dodaj Youtube
|
||||
youtubeId=ID za Youtube
|
||||
|
||||
+1
-1
@@ -542,7 +542,7 @@ widthInPx=宽度(像素)
|
||||
heightInPx=高度(像素)
|
||||
tags=标记
|
||||
size=大小
|
||||
duration=持续时间 (h:mm:ss.ms)
|
||||
duration=持续时间 (h:mm:ss)
|
||||
addMediaTrack=添加音频/视频
|
||||
addYoutubeTrack=添加 Youtube
|
||||
youtubeId=Youtube 编号
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
DELETE FROM SAILING."CompetitorRace" CASCADE;
|
||||
DELETE FROM SAILING."Event" CASCADE;
|
||||
DELETE FROM SAILING."RaceResult" CASCADE;
|
||||
DELETE FROM SAILING."RaceStats" CASCADE;
|
||||
DELETE FROM SAILING."Leg" CASCADE;
|
||||
@@ -7,6 +6,7 @@ DELETE FROM SAILING."LegStats" CASCADE;
|
||||
DELETE FROM SAILING."Maneuver" CASCADE;
|
||||
DELETE FROM SAILING."Race" CASCADE;
|
||||
DELETE FROM SAILING."Regatta" CASCADE;
|
||||
DELETE FROM SAILING."Event" CASCADE;
|
||||
DELETE FROM SAILING."Competitor" CASCADE;
|
||||
DELETE FROM SAILING."BoatClass" CASCADE;
|
||||
DELETE FROM SAILING."IRM" CASCADE;
|
||||
|
||||
@@ -6,7 +6,7 @@ CREATE COLUMN TABLE SAILING."Event" (
|
||||
"venue" NVARCHAR(255),
|
||||
"isListed" BOOLEAN,
|
||||
"description" NVARCHAR(5000),
|
||||
"location" ST_POINT
|
||||
"location" ST_POINT(3857)
|
||||
);
|
||||
CREATE ROW TABLE SAILING."ScoringScheme" (
|
||||
"id" NVARCHAR(255) PRIMARY KEY,
|
||||
|
||||
+2
-1
@@ -2,11 +2,12 @@ package com.sap.sailing.hanaexport;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.sap.sailing.hanaexport.impl.HanaConnectionFactoryImpl;
|
||||
|
||||
public interface HanaConnectionFactory {
|
||||
static HanaConnectionFactory INSTANCE = new HanaConnectionFactoryImpl();
|
||||
|
||||
Connection getConnection() throws SQLException;
|
||||
Connection getConnection(Optional<String> dbEndpoint, Optional<String> dbUser, Optional<String> dbPassword) throws SQLException;
|
||||
}
|
||||
|
||||
+28
-5
@@ -6,6 +6,7 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.common.BoatClassMasterdata;
|
||||
@@ -20,7 +21,7 @@ public class HanaConnectionFactoryImpl implements HanaConnectionFactory {
|
||||
public void test() throws SQLException {
|
||||
System.out.println("Java version: " + com.sap.db.jdbc.Driver.getJavaVersion());
|
||||
System.out.println("Minimum supported Java version and SAP driver version number: " + com.sap.db.jdbc.Driver.getVersionInfo());
|
||||
final Connection connection = getConnection();
|
||||
final Connection connection = getConnection(Optional.empty(), Optional.empty(), Optional.empty());
|
||||
if (connection == null) {
|
||||
logger.warning("Couldn't get database connection for end point "+System.getProperty(HANADB_ENDPOINT_PROPERTY_NAME));
|
||||
} else {
|
||||
@@ -42,11 +43,33 @@ public class HanaConnectionFactoryImpl implements HanaConnectionFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
public Connection getConnection(Optional<String> dbEndpoint, Optional<String> dbUser, Optional<String> dbPassword) throws SQLException {
|
||||
final String dbEndpointFromSystemProperty = System.getProperty(HANADB_ENDPOINT_PROPERTY_NAME);
|
||||
final String dbUserFromSystemProperty = System.getProperty(HANADB_USERNAME_SYSTEM_PROPERTY_NAME);
|
||||
final String dbPasswordFromSystemProperty = System.getProperty(HANADB_PASSWORD_SYSTEM_PROPERTY_NAME);
|
||||
final String dbUrl = "jdbc:sap://"+dbEndpoint.orElseGet(()->{
|
||||
if (dbEndpointFromSystemProperty != null) {
|
||||
return dbEndpointFromSystemProperty;
|
||||
} else {
|
||||
throw new IllegalStateException("Missing DB URL, either as parameter or from system property "+HANADB_ENDPOINT_PROPERTY_NAME);
|
||||
}
|
||||
});
|
||||
return DriverManager.getConnection(
|
||||
"jdbc:sap://"+System.getProperty(HANADB_ENDPOINT_PROPERTY_NAME)+"/?encrypt=true&validateCertificate=false",
|
||||
System.getProperty(HANADB_USERNAME_SYSTEM_PROPERTY_NAME),
|
||||
System.getProperty(HANADB_PASSWORD_SYSTEM_PROPERTY_NAME));
|
||||
dbUrl,
|
||||
dbUser.orElseGet(()->{
|
||||
if (dbUserFromSystemProperty != null) {
|
||||
return dbUserFromSystemProperty;
|
||||
} else {
|
||||
throw new IllegalStateException("Missing DB user name, either as parameter or from system property "+HANADB_USERNAME_SYSTEM_PROPERTY_NAME);
|
||||
}
|
||||
}),
|
||||
dbPassword.orElseGet(()->{
|
||||
if (dbPasswordFromSystemProperty != null) {
|
||||
return dbPasswordFromSystemProperty;
|
||||
} else {
|
||||
throw new IllegalStateException("Missing DB password, either as parameter or from system property "+HANADB_PASSWORD_SYSTEM_PROPERTY_NAME);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws SQLException {
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.Duration;
|
||||
|
||||
public abstract class AbstractPreparedInsertStatement<T> implements PreparedInsertStatement<T> {
|
||||
private final PreparedStatement preparedStatement;
|
||||
|
||||
protected AbstractPreparedInsertStatement(PreparedStatement preparedStatement) {
|
||||
this.preparedStatement = preparedStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement getPreparedStatement() {
|
||||
return preparedStatement;
|
||||
}
|
||||
|
||||
protected void setDouble(int parameterIndex, double value) throws SQLException {
|
||||
if (Double.isNaN(value) || Double.isInfinite(value)) {
|
||||
setDouble(parameterIndex, 0.0);
|
||||
} else {
|
||||
getPreparedStatement().setDouble(parameterIndex, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected int intOr0ForNull(Integer i) {
|
||||
return i==null?0:i;
|
||||
}
|
||||
|
||||
protected double metersOr0ForNull(final Distance distance) {
|
||||
return distance == null ? 0 : distance.getMeters();
|
||||
}
|
||||
|
||||
protected double secondsOr0ForNull(final Duration duration) {
|
||||
return duration == null ? 0 : duration.asSeconds();
|
||||
}
|
||||
}
|
||||
+127
-316
@@ -3,14 +3,18 @@ package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Date;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.ws.rs.FormParam;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
@@ -20,40 +24,30 @@ import javax.ws.rs.core.Response;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorWithBoat;
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.SpeedWithConfidence;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.LegType;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
|
||||
import com.sap.sailing.domain.tracking.WindPositionMode;
|
||||
import com.sap.sailing.hanaexport.HanaConnectionFactory;
|
||||
import com.sap.sailing.hanaexport.jaxrs.api.InsertRegattaStatement.RegattaAndEvent;
|
||||
import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
import com.sap.sailing.shared.server.gateway.jaxrs.SharedAbstractSailingServerResource;
|
||||
import com.sap.sse.ServerInfo;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Speed;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
|
||||
@@ -63,37 +57,72 @@ import com.sap.sse.security.shared.impl.SecuredSecurityTypes;
|
||||
public class HanaCloudSacExportResource extends SharedAbstractSailingServerResource {
|
||||
private static final Logger logger = Logger.getLogger(HanaCloudSacExportResource.class.getName());
|
||||
|
||||
private class AlreadyInsertedContent {
|
||||
private final Set<Event> events;
|
||||
private final Set<Competitor> competitors;
|
||||
private final InsertCompetitorStatement insertCompetitors;
|
||||
private final InsertEventStatement insertEvents;
|
||||
public AlreadyInsertedContent(InsertEventStatement insertEvents, InsertCompetitorStatement insertCompetitors) {
|
||||
events = new HashSet<>();
|
||||
competitors = new HashSet<>();
|
||||
this.insertEvents = insertEvents;
|
||||
this.insertCompetitors = insertCompetitors;
|
||||
}
|
||||
|
||||
public void ensureEventIsInserted(Event event) throws SQLException {
|
||||
if (!events.contains(event)) {
|
||||
events.add(event);
|
||||
insertEvents.insert(event);
|
||||
}
|
||||
}
|
||||
|
||||
public void ensureCompetitorIsInserted(Competitor competitor) throws SQLException {
|
||||
if (!competitors.contains(competitor)) {
|
||||
competitors.add(competitor);
|
||||
insertCompetitors.insert(competitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("clear")
|
||||
public Response clear() throws SQLException, IOException {
|
||||
public Response clear(
|
||||
@FormParam("dbendpoint") String dbEndpoint,
|
||||
@FormParam("dbuser") String dbUser,
|
||||
@FormParam("dbpassword") String dbPassword) throws SQLException, IOException {
|
||||
SecurityUtils.getSubject().checkPermission(SecuredSecurityTypes.SERVER.getStringPermissionForTypeRelativeIdentifier(
|
||||
SecuredSecurityTypes.ServerActions.CAN_EXPORT_MASTERDATA,
|
||||
new TypeRelativeObjectIdentifier(ServerInfo.getName())));
|
||||
logger.info("Clearing HANA Cloud SAILING DB on behalf of user "+SecurityUtils.getSubject().getPrincipal());
|
||||
final Connection connection = HanaConnectionFactory.INSTANCE.getConnection();
|
||||
final Connection connection = HanaConnectionFactory.INSTANCE.getConnection(Optional.ofNullable(dbEndpoint),
|
||||
Optional.ofNullable(dbUser), Optional.ofNullable(dbPassword));
|
||||
tryExecutingQueriesFromSqlResource("/cleartables.sql", connection);
|
||||
logger.info("Done learing HANA Cloud SAILING DB on behalf of user "+SecurityUtils.getSubject().getPrincipal());
|
||||
logger.info("Done clearing HANA Cloud SAILING DB on behalf of user "+SecurityUtils.getSubject().getPrincipal());
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("export")
|
||||
public Response export() throws SQLException {
|
||||
public Response export(@QueryParam("leaderboardgroupid") List<String> leaderboardGroupIds,
|
||||
@QueryParam("eventid") List<String> eventIds,
|
||||
@FormParam("dbendpoint") String dbEndpoint,
|
||||
@FormParam("dbuser") String dbUser,
|
||||
@FormParam("dbpassword") String dbPassword) throws SQLException {
|
||||
SecurityUtils.getSubject().checkPermission(SecuredSecurityTypes.SERVER.getStringPermissionForTypeRelativeIdentifier(
|
||||
SecuredSecurityTypes.ServerActions.CAN_EXPORT_MASTERDATA,
|
||||
new TypeRelativeObjectIdentifier(ServerInfo.getName())));
|
||||
logger.info("Exporting HANA Cloud SAILING DB content on behalf of user "+SecurityUtils.getSubject().getPrincipal());
|
||||
final RacingEventService racingEventService = getService();
|
||||
try {
|
||||
final Connection connection = HanaConnectionFactory.INSTANCE.getConnection();
|
||||
final Connection connection = HanaConnectionFactory.INSTANCE.getConnection(Optional.ofNullable(dbEndpoint),
|
||||
Optional.ofNullable(dbUser), Optional.ofNullable(dbPassword));
|
||||
exportBoatClasses(racingEventService, connection);
|
||||
exportIrms(racingEventService, connection);
|
||||
exportScoringSchemes(racingEventService, connection);
|
||||
exportCompetitors(racingEventService, connection);
|
||||
exportEvents(racingEventService, connection);
|
||||
exportRaces(racingEventService, connection);
|
||||
final Iterable<Regatta> regattasToExport = getRegattasToExport(racingEventService, leaderboardGroupIds, eventIds);
|
||||
exportRaces(racingEventService, regattasToExport, connection);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Problem exporting data to HANA", e);
|
||||
throw e;
|
||||
@@ -102,127 +131,92 @@ public class HanaCloudSacExportResource extends SharedAbstractSailingServerResou
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
private void exportCompetitors(RacingEventService racingEventService, Connection connection) throws SQLException {
|
||||
final PreparedStatement insertCompetitors = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Competitor\" (\"id\", \"name\", \"shortName\", \"nationality\", \"sailNumber\") VALUES (?, ?, ?, ?, ?);");
|
||||
for (final Competitor competitor : racingEventService.getCompetitorAndBoatStore().getAllCompetitors()) {
|
||||
insertCompetitors.setString(1, competitor.getId().toString());
|
||||
insertCompetitors.setString(2, competitor.getName());
|
||||
insertCompetitors.setString(3, competitor.getShortName());
|
||||
insertCompetitors.setString(4, competitor.getNationality() == null ? " " : competitor.getNationality().getThreeLetterIOCAcronym());
|
||||
insertCompetitors.setString(5, competitor.hasBoat() ? ((CompetitorWithBoat) competitor).getBoat().getSailID() : null);
|
||||
insertCompetitors.execute();
|
||||
private Iterable<Regatta> getRegattasToExport(RacingEventService racingEventService, List<String> leaderboardGroupIds, List<String> eventIds) {
|
||||
final Set<LeaderboardGroup> leaderboardGroups = new HashSet<>();
|
||||
final Iterable<Regatta> result;
|
||||
boolean atLeastOneIdProvided = false;
|
||||
if (leaderboardGroupIds != null) {
|
||||
for (final String leaderboardGroupIdAsString : leaderboardGroupIds) {
|
||||
atLeastOneIdProvided = true;
|
||||
try {
|
||||
leaderboardGroups.add(racingEventService.getLeaderboardGroupByID(UUID.fromString(leaderboardGroupIdAsString)));
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.log(Level.WARNING, "Couldn't parse "+leaderboardGroupIdAsString+" as a leaderboard group's UUID. Ignoring.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (eventIds != null) {
|
||||
for (final String eventIdAsString : eventIds) {
|
||||
atLeastOneIdProvided = true;
|
||||
try {
|
||||
final Event event = racingEventService.getEvent(UUID.fromString(eventIdAsString));
|
||||
Util.addAll(event.getLeaderboardGroups(), leaderboardGroups);
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.log(Level.WARNING, "Couldn't parse "+eventIdAsString+" as an event's UUID. Ignoring.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (atLeastOneIdProvided) {
|
||||
final Set<Regatta> resultSet = new HashSet<>();
|
||||
for (final LeaderboardGroup leaderboardGroup : leaderboardGroups) {
|
||||
for (final Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) {
|
||||
if (leaderboard.getLeaderboardType().isRegattaLeaderboard()) {
|
||||
resultSet.add(((RegattaLeaderboard) leaderboard).getRegatta());
|
||||
}
|
||||
}
|
||||
}
|
||||
result = resultSet;
|
||||
} else {
|
||||
result = racingEventService.getAllRegattas();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void exportIrms(RacingEventService racingEventService, Connection connection) throws SQLException {
|
||||
final PreparedStatement insertBoatClasses = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"IRM\" (\"name\", \"discardable\", \"advanceCompetitorsTrackedWorse\", \"appliesAtStartOfRace\") VALUES (?, ?, ?, ?);");
|
||||
for (final MaxPointsReason irm : MaxPointsReason.values()) {
|
||||
insertBoatClasses.setString(1, irm.name());
|
||||
insertBoatClasses.setBoolean(2, irm.isDiscardable());
|
||||
insertBoatClasses.setBoolean(3, irm.isAdvanceCompetitorsTrackedWorse());
|
||||
insertBoatClasses.setBoolean(4, irm.isAppliesAtStartOfRace());
|
||||
insertBoatClasses.execute();
|
||||
}
|
||||
final InsertIrmStatement insertIrms = new InsertIrmStatement(connection);
|
||||
insertIrms.insertBatch(Arrays.asList(MaxPointsReason.values()));
|
||||
insertIrms.executeBatch();
|
||||
}
|
||||
|
||||
private void exportScoringSchemes(RacingEventService racingEventService, Connection connection) throws SQLException {
|
||||
final PreparedStatement insertBoatClasses = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"ScoringScheme\" (\"id\", \"higherIsBetter\") VALUES (?, ?);");
|
||||
final InsertScoringSchemeStatement insertScoringScheme = new InsertScoringSchemeStatement(connection);
|
||||
for (final ScoringSchemeType scoringSchemeType : ScoringSchemeType.values()) {
|
||||
final ScoringScheme scoringScheme = racingEventService.getBaseDomainFactory().createScoringScheme(scoringSchemeType);
|
||||
insertBoatClasses.setString(1, scoringScheme.getType().name());
|
||||
insertBoatClasses.setBoolean(2, scoringScheme.isHigherBetter());
|
||||
insertBoatClasses.execute();
|
||||
insertScoringScheme.insertBatch(scoringScheme);
|
||||
}
|
||||
insertScoringScheme.executeBatch();
|
||||
}
|
||||
|
||||
private void exportBoatClasses(final RacingEventService racingEventService, final Connection connection)
|
||||
throws SQLException {
|
||||
final PreparedStatement insertBoatClasses = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"BoatClass\" (\"id\", \"description\", \"hullLengthInMeters\", \"hullBeamInMeters\", \"hullType\") VALUES (?, ?, ?, ?, ?);");
|
||||
for (final BoatClass boatClass : racingEventService.getBaseDomainFactory().getBoatClasses()) {
|
||||
if (boatClass.getName() == null) {
|
||||
insertBoatClasses.setString(1, "<null>");
|
||||
} else {
|
||||
insertBoatClasses.setString(1, boatClass.getName().substring(0, Math.min(boatClass.getName().length(), 255)));
|
||||
}
|
||||
insertBoatClasses.setString(2, "Type "+boatClass.getHullType().name()+", length "+
|
||||
boatClass.getHullLength().getMeters()+"m, beam "+boatClass.getHullBeam().getMeters()+"m");
|
||||
setDouble(insertBoatClasses, 3, boatClass.getHullLength().getMeters());
|
||||
setDouble(insertBoatClasses, 4, boatClass.getHullBeam().getMeters());
|
||||
insertBoatClasses.setString(5, boatClass.getHullType().name());
|
||||
insertBoatClasses.execute();
|
||||
}
|
||||
final InsertBoatClassStatement insertBoatClasses = new InsertBoatClassStatement(connection);
|
||||
insertBoatClasses.insertBatch(racingEventService.getBaseDomainFactory().getBoatClasses());
|
||||
insertBoatClasses.executeBatch();
|
||||
}
|
||||
|
||||
private void exportEvents(RacingEventService racingEventService, Connection connection) throws SQLException {
|
||||
final PreparedStatement insertEvents = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Event\" (\"id\", \"name\", \"startDate\", \"endDate\", \"venue\", \"isListed\", \"description\", \"location\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, NEW ST_POINT(?));");
|
||||
for (final Event event : racingEventService.getAllEvents()) {
|
||||
insertEvents.setString(1, event.getId().toString());
|
||||
insertEvents.setString(2, event.getName());
|
||||
insertEvents.setDate(3, event.getStartDate()==null?null:new Date(event.getStartDate().asMillis()));
|
||||
insertEvents.setDate(4, event.getEndDate()==null?null:new Date(event.getEndDate().asMillis()));
|
||||
insertEvents.setString(5, event.getVenue().getName());
|
||||
insertEvents.setBoolean(6, event.isPublic());
|
||||
insertEvents.setString(7, event.getDescription());
|
||||
final Position location = event.getLocation();
|
||||
insertEvents.setString(8, location != null ? String.format("POINT(%1.5f %1.5f)", location.getLatDeg(), location.getLngDeg()) : null);
|
||||
insertEvents.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private void exportRaces(RacingEventService racingEventService, Connection connection) throws SQLException {
|
||||
private void exportRaces(RacingEventService racingEventService, Iterable<Regatta> regattasToExport, Connection connection) throws SQLException {
|
||||
final TimePoint now = TimePoint.now();
|
||||
final PreparedStatement insertRegattas = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Regatta\" (\"name\", \"boatClass\", \"scoringScheme\", \"rankingMetric\", \"eventId\") "+
|
||||
"VALUES (?, ?, ?, ?, ?);");
|
||||
final PreparedStatement insertRaces = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Race\" (\"name\", \"regatta\", \"raceColumn\", \"fleet\", \"startOfTracking\", "+
|
||||
"\"startOfRace\", \"endOfTracking\", \"endOfRace\", \"avgWindSpeedInKnots\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||
final PreparedStatement insertRaceResults = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"RaceResult\" (\"regatta\", \"raceColumn\", \"competitorId\", \"points\", "+
|
||||
"\"discarded\", \"irm\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?);");
|
||||
final PreparedStatement insertRaceStats = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"RaceStats\" (\"race\", \"regatta\", \"competitorId\", \"rankOneBased\", \"distanceSailedInMeters\", \"elapsedTimeInSeconds\", "+
|
||||
"\"avgCrossTrackErrorInMeters\", \"absoluteAvgCrossTrackErrorInMeters\", \"numberOfTacks\", "+
|
||||
"\"numberOfGybes\", \"numberOfPenaltyCircles\", \"startDelayInSeconds\", \"distanceFromStartLineInMetersAtStart\", "+
|
||||
"\"speedWhenCrossingStartLineInKnots\", \"startTack\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||
final PreparedStatement insertLegs = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Leg\" (\"race\", \"regatta\", \"number\", \"type\") "+
|
||||
"VALUES (?, ?, ?, ?);");
|
||||
final PreparedStatement insertLegStats = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"LegStats\" (\"race\", \"regatta\", \"number\", \"competitorId\", \"rankOneBased\", \"distanceSailedInMeters\", \"elapsedTimeInSeconds\", "+
|
||||
"\"avgCrossTrackErrorInMeters\", \"absoluteAvgCrossTrackErrorInMeters\", \"numberOfTacks\", "+
|
||||
"\"numberOfGybes\", \"numberOfPenaltyCircles\", \"avgVelocityMadeGoodInKnots\", \"gapToLeaderInSeconds\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||
final PreparedStatement insertManeuvers = connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Maneuver\" (\"race\", \"regatta\", \"competitorId\", \"timepoint\", \"type\", \"newTack\", "+
|
||||
"\"lossInMeters\", \"speedBeforeInKnots\", \"speedAfterInKnots\", "+
|
||||
"\"courseBeforeInTrueDegrees\", \"courseAfterInTrueDegrees\", \"directionChangeInDegrees\", \"maximumTurningRateInDegreesPerSecond\", "+
|
||||
"\"lowestSpeedInKnots\", \"toSide\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||
for (final Regatta regatta : racingEventService.getAllRegattas()) {
|
||||
final InsertEventStatement insertEvents = new InsertEventStatement(connection);
|
||||
final InsertCompetitorStatement insertCompetitors = new InsertCompetitorStatement(connection);
|
||||
final AlreadyInsertedContent alreadyInsertedContent = new AlreadyInsertedContent(insertEvents, insertCompetitors);
|
||||
final InsertRegattaStatement insertRegattas = new InsertRegattaStatement(connection);
|
||||
final InsertRaceStatement insertRaces = new InsertRaceStatement(connection);
|
||||
final InsertRaceResultStatement insertRaceResults = new InsertRaceResultStatement(connection);
|
||||
final InsertRaceStatsStatement insertRaceStats = new InsertRaceStatsStatement(connection);
|
||||
final InsertLegStatement insertLegs = new InsertLegStatement(connection);
|
||||
final InsertLegStatsStatement insertLegStats = new InsertLegStatsStatement(connection);
|
||||
final InsertManeuverStatement insertManeuvers = new InsertManeuverStatement(connection);
|
||||
for (final Regatta regatta : regattasToExport) {
|
||||
final Leaderboard leaderboard = racingEventService.getLeaderboardByName(regatta.getName());
|
||||
if (leaderboard != null) {
|
||||
final Event event = racingEventService.findEventContainingLeaderboardAndMatchingAtLeastOneCourseArea(leaderboard);
|
||||
insertRegattas.setString(1, regatta.getName());
|
||||
insertRegattas.setString(2, regatta.getBoatClass().getName());
|
||||
insertRegattas.setString(3, regatta.getScoringScheme().getType().name());
|
||||
insertRegattas.setString(4, regatta.getRankingMetricType().name());
|
||||
insertRegattas.setString(5, event == null ? null : event.getId().toString());
|
||||
insertRegattas.execute();
|
||||
alreadyInsertedContent.ensureEventIsInserted(event);
|
||||
insertRegattas.insert(new RegattaAndEvent(regatta, event));
|
||||
if (leaderboard != null) {
|
||||
for (final RaceColumn raceColumn : leaderboard.getRaceColumns()) {
|
||||
for (final Competitor competitor : raceColumn.getAllCompetitors()) {
|
||||
parameterizeInsertRaceResult(insertRaceResults, now, competitor, leaderboard, raceColumn, regatta);
|
||||
insertRaceResults.addBatch();
|
||||
alreadyInsertedContent.ensureCompetitorIsInserted(competitor);
|
||||
insertRaceResults.insertBatch(new InsertRaceResultStatement.RaceResult(regatta, leaderboard, competitor, raceColumn, now));
|
||||
}
|
||||
insertRaceResults.executeBatch();
|
||||
for (final Fleet fleet : raceColumn.getFleets()) {
|
||||
@@ -230,22 +224,18 @@ public class HanaCloudSacExportResource extends SharedAbstractSailingServerResou
|
||||
if (trackedRace != null) {
|
||||
final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(now);
|
||||
final WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache = new LeaderboardDTOCalculationReuseCache(now);
|
||||
parameterizeInsertRacesStatement(insertRaces, regatta, raceColumn, fleet, trackedRace);
|
||||
insertRaces.addBatch();
|
||||
insertRaces.insertBatch(new InsertRaceStatement.TrackedRaceWithRaceColumnAndFleet(trackedRace, raceColumn, fleet));
|
||||
for (final TrackedLeg trackedLeg : trackedRace.getTrackedLegs()) {
|
||||
parameterizeInsertLegsStatement(insertLegs, now, regatta, trackedRace, trackedLeg);
|
||||
insertLegs.addBatch();
|
||||
insertLegs.insertBatch(new InsertLegStatement.TrackedLegAndNow(now, trackedLeg));
|
||||
for (final Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
parameterizeInsertLegStatsStatement(insertLegStats, now, trackedLeg.getTrackedLeg(competitor), rankingInfo, cache);
|
||||
insertLegStats.addBatch();
|
||||
insertLegStats.insertBatch(new InsertLegStatsStatement.TrackedLegOfCompetitorRankingInfoCacheAndNow(now, rankingInfo, cache, trackedLeg.getTrackedLeg(competitor)));
|
||||
}
|
||||
}
|
||||
}
|
||||
final Waypoint startWaypoint = trackedRace == null ? null : trackedRace.getRace().getCourse().getFirstWaypoint();
|
||||
if (trackedRace != null) {
|
||||
for (final Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
parameterizeInsertRaceStats(insertRaceStats, now, startWaypoint, competitor, trackedRace);
|
||||
insertRaceStats.addBatch();
|
||||
insertRaceStats.insertBatch(new InsertRaceStatsStatement.TrackedRaceWithCompetitorAndStartWaypoint(now, startWaypoint, competitor, trackedRace));
|
||||
final LinkedHashMap<TimePoint, Maneuver> timepointUniqueManeuvers = new LinkedHashMap<>();
|
||||
for (final Maneuver maneuver : trackedRace.getManeuvers(competitor, /* waitForLatest */ false)) {
|
||||
if (maneuver.getType() == ManeuverType.TACK || maneuver.getType() == ManeuverType.JIBE || maneuver.getType() == ManeuverType.PENALTY_CIRCLE) {
|
||||
@@ -253,8 +243,7 @@ public class HanaCloudSacExportResource extends SharedAbstractSailingServerResou
|
||||
}
|
||||
}
|
||||
for (final Maneuver maneuver : timepointUniqueManeuvers.values()) {
|
||||
parameterizeInsertManeuvers(insertManeuvers, competitor, maneuver, trackedRace);
|
||||
insertManeuvers.addBatch();
|
||||
insertManeuvers.insertBatch(new InsertManeuverStatement.ManeuverTrackedRaceAndCompetitor(maneuver, trackedRace, competitor));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,188 +259,18 @@ public class HanaCloudSacExportResource extends SharedAbstractSailingServerResou
|
||||
}
|
||||
}
|
||||
|
||||
private void parameterizeInsertManeuvers(PreparedStatement insertManeuvers, Competitor competitor, Maneuver maneuver, TrackedRace trackedRace) throws SQLException {
|
||||
insertManeuvers.setString(1, trackedRace.getRace().getName());
|
||||
insertManeuvers.setString(2, trackedRace.getTrackedRegatta().getRegatta().getName());
|
||||
insertManeuvers.setString(3, competitor.getId().toString());
|
||||
insertManeuvers.setDate(4, new Date(maneuver.getTimePoint().asMillis()));
|
||||
insertManeuvers.setString(5, maneuver.getType().name());
|
||||
insertManeuvers.setString(6, maneuver.getNewTack().name());
|
||||
if (maneuver.getManeuverLoss() != null) {
|
||||
setDouble(insertManeuvers, 7,
|
||||
maneuver.getManeuverLoss().getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle().getMeters()
|
||||
-maneuver.getManeuverLoss().getDistanceSailedProjectedOnMiddleManeuverAngle().getMeters());
|
||||
} else {
|
||||
setDouble(insertManeuvers, 7, 0);
|
||||
}
|
||||
setDouble(insertManeuvers, 8, maneuver.getSpeedWithBearingBefore().getKnots());
|
||||
setDouble(insertManeuvers, 9, maneuver.getSpeedWithBearingAfter().getKnots());
|
||||
setDouble(insertManeuvers, 10, maneuver.getSpeedWithBearingBefore().getBearing().getDegrees());
|
||||
setDouble(insertManeuvers, 11, maneuver.getSpeedWithBearingAfter().getBearing().getDegrees());
|
||||
setDouble(insertManeuvers, 12, maneuver.getDirectionChangeInDegrees());
|
||||
setDouble(insertManeuvers, 13, maneuver.getMaxTurningRateInDegreesPerSecond());
|
||||
setDouble(insertManeuvers, 14, maneuver.getLowestSpeed().getKnots());
|
||||
insertManeuvers.setString(15, maneuver.getToSide().name());
|
||||
}
|
||||
|
||||
private void parameterizeInsertLegStatsStatement(PreparedStatement insertLegStats, TimePoint now,
|
||||
TrackedLegOfCompetitor trackedLegOfCompetitor, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws SQLException {
|
||||
insertLegStats.setString(1, trackedLegOfCompetitor.getTrackedLeg().getTrackedRace().getRace().getName());
|
||||
insertLegStats.setString(2, trackedLegOfCompetitor.getTrackedLeg().getTrackedRace().getTrackedRegatta().getRegatta().getName());
|
||||
insertLegStats.setInt(3, trackedLegOfCompetitor.getTrackedLeg().getLeg().getZeroBasedIndexOfStartWaypoint());
|
||||
insertLegStats.setString(4, trackedLegOfCompetitor.getCompetitor().getId().toString());
|
||||
insertLegStats.setInt(5, trackedLegOfCompetitor.getRank(now));
|
||||
setDouble(insertLegStats, 6, metersOr0ForNull(trackedLegOfCompetitor.getDistanceTraveled(now)));
|
||||
setDouble(insertLegStats, 7, secondsOr0ForNull(trackedLegOfCompetitor.getTime(now)));
|
||||
setDouble(insertLegStats, 8, metersOr0ForNull(trackedLegOfCompetitor.getAverageSignedCrossTrackError(now, /* waitForLatest */ false)));
|
||||
setDouble(insertLegStats, 9, metersOr0ForNull(trackedLegOfCompetitor.getAverageAbsoluteCrossTrackError(now, /* waitForLatest */ false)));
|
||||
try {
|
||||
insertLegStats.setInt(10, intOr0ForNull(trackedLegOfCompetitor.getNumberOfTacks(now, /* waitForLatest */ false)));
|
||||
insertLegStats.setInt(11, intOr0ForNull(trackedLegOfCompetitor.getNumberOfJibes(now, /* waitForLatest */ false)));
|
||||
insertLegStats.setInt(12, intOr0ForNull(trackedLegOfCompetitor.getNumberOfPenaltyCircles(now, /* waitForLatest */ false)));
|
||||
} catch (NoWindException nwe) {
|
||||
insertLegStats.setInt(10, 0);
|
||||
insertLegStats.setInt(11, 0);
|
||||
insertLegStats.setInt(12, 0);
|
||||
}
|
||||
final Speed vmg = trackedLegOfCompetitor.getAverageVelocityMadeGood(now);
|
||||
setDouble(insertLegStats, 13, vmg==null?0:vmg.getKnots());
|
||||
setDouble(insertLegStats, 14, secondsOr0ForNull(trackedLegOfCompetitor.getGapToLeader(now, WindPositionMode.LEG_MIDDLE, rankingInfo, cache)));
|
||||
}
|
||||
|
||||
private int intOr0ForNull(Integer i) {
|
||||
return i==null?0:i;
|
||||
}
|
||||
|
||||
private void parameterizeInsertLegsStatement(PreparedStatement insertLegs, TimePoint now, Regatta regatta, TrackedRace trackedRace, TrackedLeg trackedLeg) throws SQLException {
|
||||
insertLegs.setString(1, trackedRace.getRace().getName());
|
||||
insertLegs.setString(2, trackedRace.getTrackedRegatta().getRegatta().getName());
|
||||
insertLegs.setInt(3, trackedLeg.getLeg().getZeroBasedIndexOfStartWaypoint());
|
||||
final LegType legType;
|
||||
try {
|
||||
legType = trackedLeg.getLegType(now);
|
||||
insertLegs.setString(4, legType.name());
|
||||
} catch (NoWindException nwe) {
|
||||
insertLegs.setString(4, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void parameterizeInsertRaceStats(PreparedStatement insertRaceStats, TimePoint now, Waypoint startWaypoint,
|
||||
Competitor competitor, TrackedRace trackedRace) throws SQLException {
|
||||
insertRaceStats.setString(1, trackedRace.getRace().getName());
|
||||
insertRaceStats.setString(2, trackedRace.getTrackedRegatta().getRegatta().getName());
|
||||
insertRaceStats.setString(3, competitor.getId().toString());
|
||||
insertRaceStats.setInt(4, trackedRace.getRank(competitor, now));
|
||||
setDouble(insertRaceStats, 5, metersOr0ForNull(trackedRace.getDistanceTraveled(competitor, now)));
|
||||
setDouble(insertRaceStats, 6, secondsOr0ForNull(trackedRace.getTimeSailedSinceRaceStart(competitor, now)));
|
||||
setDouble(insertRaceStats, 7, metersOr0ForNull(trackedRace.getAverageSignedCrossTrackError(competitor, now, /* waitForLatest */ false)));
|
||||
setDouble(insertRaceStats, 8, metersOr0ForNull(trackedRace.getAverageAbsoluteCrossTrackError(competitor, now, /* waitForLatest */ false)));
|
||||
final Iterable<Maneuver> maneuvers = trackedRace.getManeuvers(competitor, /* waitForLatest */ false);
|
||||
insertRaceStats.setInt(9, Util.size(Util.filter(maneuvers, m->m.getType() == ManeuverType.TACK)));
|
||||
insertRaceStats.setInt(10, Util.size(Util.filter(maneuvers, m->m.getType() == ManeuverType.JIBE)));
|
||||
insertRaceStats.setInt(11, Util.size(Util.filter(maneuvers, m->m.getType() == ManeuverType.PENALTY_CIRCLE)));
|
||||
final TimePoint startOfRace = trackedRace.getStartOfRace();
|
||||
final double startDelay;
|
||||
Tack startTack;
|
||||
if (startWaypoint != null && startOfRace != null) {
|
||||
NavigableSet<MarkPassing> competitorMarkPassings = trackedRace.getMarkPassings(competitor);
|
||||
trackedRace.lockForRead(competitorMarkPassings);
|
||||
try {
|
||||
if (!Util.isEmpty(competitorMarkPassings)) {
|
||||
final MarkPassing competitorStartMarkPassing = competitorMarkPassings.iterator().next();
|
||||
final TimePoint competitorStartTime = competitorStartMarkPassing.getTimePoint();
|
||||
startDelay = secondsOr0ForNull(startOfRace.until(competitorStartTime));
|
||||
try {
|
||||
startTack = trackedRace.getTack(competitor, competitorStartTime);
|
||||
} catch (NoWindException e) {
|
||||
startTack = null;
|
||||
}
|
||||
} else {
|
||||
startDelay = 0;
|
||||
startTack = null;
|
||||
}
|
||||
} finally {
|
||||
trackedRace.unlockAfterRead(competitorMarkPassings);
|
||||
}
|
||||
} else {
|
||||
startDelay = 0;
|
||||
startTack = null;
|
||||
}
|
||||
setDouble(insertRaceStats, 12, startDelay);
|
||||
if (startOfRace != null) {
|
||||
setDouble(insertRaceStats, 13, metersOr0ForNull(trackedRace.getDistanceToStartLine(competitor, startOfRace)));
|
||||
final Speed speedWhenCrossingStartLine = trackedRace.getSpeedWhenCrossingStartLine(competitor);
|
||||
setDouble(insertRaceStats, 14, speedWhenCrossingStartLine==null?0:speedWhenCrossingStartLine.getKnots());
|
||||
insertRaceStats.setString(15, startTack==null?null:startTack.name());
|
||||
} else {
|
||||
setDouble(insertRaceStats, 13, 0);
|
||||
setDouble(insertRaceStats, 14, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private double metersOr0ForNull(final Distance distance) {
|
||||
return distance == null ? 0 : distance.getMeters();
|
||||
}
|
||||
|
||||
private double secondsOr0ForNull(final Duration duration) {
|
||||
return duration == null ? 0 : duration.asSeconds();
|
||||
}
|
||||
|
||||
private void parameterizeInsertRaceResult(PreparedStatement insertRaceResults, TimePoint now,
|
||||
Competitor competitor, Leaderboard leaderboard, RaceColumn raceColumn, Regatta regatta) throws SQLException {
|
||||
insertRaceResults.setString(1, regatta.getName());
|
||||
insertRaceResults.setString(2, raceColumn.getName());
|
||||
insertRaceResults.setString(3, competitor.getId().toString());
|
||||
final Double totalPoints = leaderboard.getTotalPoints(competitor, raceColumn, now);
|
||||
setDouble(insertRaceResults, 4, totalPoints == null ? 0 : totalPoints);
|
||||
insertRaceResults.setBoolean(5, leaderboard.isDiscarded(competitor, raceColumn, now));
|
||||
final MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitor, raceColumn, now);
|
||||
insertRaceResults.setString(6, (maxPointsReason == null ? MaxPointsReason.NONE : maxPointsReason).name());
|
||||
}
|
||||
|
||||
private void parameterizeInsertRacesStatement(final PreparedStatement insertRaces, final Regatta regatta,
|
||||
final RaceColumn raceColumn, final Fleet fleet, final TrackedRace trackedRace) throws SQLException {
|
||||
insertRaces.setString(1, trackedRace.getRace().getName());
|
||||
assert trackedRace.getTrackedRegatta().getRegatta() == regatta;
|
||||
insertRaces.setString(2, trackedRace.getTrackedRegatta().getRegatta().getName());
|
||||
insertRaces.setString(3, raceColumn.getName());
|
||||
insertRaces.setString(4, fleet.getName());
|
||||
if (trackedRace.getStartOfTracking() != null) {
|
||||
insertRaces.setDate(5, new Date(trackedRace.getStartOfTracking().asMillis()));
|
||||
} else {
|
||||
insertRaces.setDate(5, null);
|
||||
}
|
||||
if (trackedRace.getStartOfRace() != null) {
|
||||
insertRaces.setDate(6, new Date(trackedRace.getStartOfRace().asMillis()));
|
||||
} else {
|
||||
insertRaces.setDate(6, null);
|
||||
}
|
||||
if (trackedRace.getEndOfTracking() != null) {
|
||||
insertRaces.setDate(7, new Date(trackedRace.getEndOfTracking().asMillis()));
|
||||
} else {
|
||||
insertRaces.setDate(7, null);
|
||||
}
|
||||
if (trackedRace.getEndOfRace() != null) {
|
||||
insertRaces.setDate(8, new Date(trackedRace.getEndOfRace().asMillis()));
|
||||
} else {
|
||||
insertRaces.setDate(8, null);
|
||||
}
|
||||
final SpeedWithConfidence<TimePoint> averageWind = trackedRace.getAverageWindSpeedWithConfidenceWithNumberOfSamples(/* number of samples */ 5);
|
||||
if (averageWind != null) {
|
||||
setDouble(insertRaces, 9, averageWind.getObject().getKnots());
|
||||
} else {
|
||||
setDouble(insertRaces, 9, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("createtables")
|
||||
public Response createTables(@QueryParam("drop") boolean drop) throws SQLException, IOException {
|
||||
public Response createTables(@QueryParam("drop") boolean drop,
|
||||
@FormParam("dbendpoint") String dbEndpoint,
|
||||
@FormParam("dbuser") String dbUser,
|
||||
@FormParam("dbpassword") String dbPassword) throws SQLException, IOException {
|
||||
SecurityUtils.getSubject().checkPermission(SecuredSecurityTypes.SERVER.getStringPermissionForTypeRelativeIdentifier(
|
||||
SecuredSecurityTypes.ServerActions.CAN_EXPORT_MASTERDATA,
|
||||
new TypeRelativeObjectIdentifier(ServerInfo.getName())));
|
||||
final Connection connection = HanaConnectionFactory.INSTANCE.getConnection();
|
||||
final Connection connection = HanaConnectionFactory.INSTANCE.getConnection(Optional.ofNullable(dbEndpoint),
|
||||
Optional.ofNullable(dbUser), Optional.ofNullable(dbPassword));
|
||||
if (drop) {
|
||||
logger.info("Dropping HANA Cloud SAILING DB tables on behalf of user "+SecurityUtils.getSubject().getPrincipal());
|
||||
tryExecutingQueriesFromSqlResource("/droptables.sql", connection);
|
||||
@@ -489,12 +308,4 @@ public class HanaCloudSacExportResource extends SharedAbstractSailingServerResou
|
||||
connection.createStatement().execute(statementAsString);
|
||||
}
|
||||
}
|
||||
|
||||
private void setDouble(PreparedStatement statement, int parameterIndex, double value) throws SQLException {
|
||||
if (Double.isNaN(value) || Double.isInfinite(value)) {
|
||||
setDouble(statement, parameterIndex, 0.0);
|
||||
} else {
|
||||
statement.setDouble(parameterIndex, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
|
||||
public class InsertBoatClassStatement extends AbstractPreparedInsertStatement<BoatClass> {
|
||||
protected InsertBoatClassStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"BoatClass\" (\"id\", \"description\", \"hullLengthInMeters\", \"hullBeamInMeters\", \"hullType\") VALUES (?, ?, ?, ?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(BoatClass boatClass) throws SQLException {
|
||||
if (boatClass.getName() == null) {
|
||||
getPreparedStatement().setString(1, "<null>");
|
||||
} else {
|
||||
getPreparedStatement().setString(1, boatClass.getName().substring(0, Math.min(boatClass.getName().length(), 255)));
|
||||
}
|
||||
getPreparedStatement().setString(2, "Type "+boatClass.getHullType().name()+", length "+
|
||||
boatClass.getHullLength().getMeters()+"m, beam "+boatClass.getHullBeam().getMeters()+"m");
|
||||
setDouble(3, boatClass.getHullLength().getMeters());
|
||||
setDouble(4, boatClass.getHullBeam().getMeters());
|
||||
getPreparedStatement().setString(5, boatClass.getHullType().name());
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorWithBoat;
|
||||
|
||||
public class InsertCompetitorStatement extends AbstractPreparedInsertStatement<Competitor> {
|
||||
protected InsertCompetitorStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Competitor\" (\"id\", \"name\", \"shortName\", \"nationality\", \"sailNumber\") VALUES (?, ?, ?, ?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(Competitor competitor) throws SQLException {
|
||||
getPreparedStatement().setString(1, competitor.getId().toString());
|
||||
getPreparedStatement().setString(2, competitor.getName());
|
||||
getPreparedStatement().setString(3, competitor.getShortName());
|
||||
getPreparedStatement().setString(4, competitor.getNationality() == null ? " " : competitor.getNationality().getThreeLetterIOCAcronym());
|
||||
getPreparedStatement().setString(5, competitor.hasBoat() ? ((CompetitorWithBoat) competitor).getBoat().getSailID() : null);
|
||||
}
|
||||
}
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.Date;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
|
||||
public class InsertEventStatement extends AbstractPreparedInsertStatement<Event> {
|
||||
protected InsertEventStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Event\" (\"id\", \"name\", \"startDate\", \"endDate\", \"venue\", \"isListed\", \"description\", \"location\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, NEW ST_POINT(?, 3857));"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(Event event) throws SQLException {
|
||||
getPreparedStatement().setString(1, event.getId().toString());
|
||||
getPreparedStatement().setString(2, event.getName());
|
||||
getPreparedStatement().setDate(3, event.getStartDate()==null?null:new Date(event.getStartDate().asMillis()));
|
||||
getPreparedStatement().setDate(4, event.getEndDate()==null?null:new Date(event.getEndDate().asMillis()));
|
||||
getPreparedStatement().setString(5, event.getVenue().getName());
|
||||
getPreparedStatement().setBoolean(6, event.isPublic());
|
||||
getPreparedStatement().setString(7, event.getDescription());
|
||||
final Position location = event.getLocation();
|
||||
getPreparedStatement().setString(8, location != null ? String.format("POINT(%1.8f %1.8f)", location.getLngDeg(), location.getLatDeg()) : null);
|
||||
}
|
||||
}
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
|
||||
public class InsertIrmStatement extends AbstractPreparedInsertStatement<MaxPointsReason> {
|
||||
protected InsertIrmStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"IRM\" (\"name\", \"discardable\", \"advanceCompetitorsTrackedWorse\", \"appliesAtStartOfRace\") VALUES (?, ?, ?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(MaxPointsReason irm) throws SQLException {
|
||||
getPreparedStatement().setString(1, irm.name());
|
||||
getPreparedStatement().setBoolean(2, irm.isDiscardable());
|
||||
getPreparedStatement().setBoolean(3, irm.isAdvanceCompetitorsTrackedWorse());
|
||||
getPreparedStatement().setBoolean(4, irm.isAppliesAtStartOfRace());
|
||||
}
|
||||
}
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.common.LegType;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.hanaexport.jaxrs.api.InsertLegStatement.TrackedLegAndNow;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class InsertLegStatement extends AbstractPreparedInsertStatement<TrackedLegAndNow> {
|
||||
static class TrackedLegAndNow {
|
||||
private final TimePoint now;
|
||||
private final TrackedLeg trackedLeg;
|
||||
public TrackedLegAndNow(TimePoint now, TrackedLeg trackedLeg) {
|
||||
super();
|
||||
this.now = now;
|
||||
this.trackedLeg = trackedLeg;
|
||||
}
|
||||
public TimePoint getNow() {
|
||||
return now;
|
||||
}
|
||||
public TrackedLeg getTrackedLeg() {
|
||||
return trackedLeg;
|
||||
}
|
||||
}
|
||||
|
||||
protected InsertLegStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Leg\" (\"race\", \"regatta\", \"number\", \"type\") "+
|
||||
"VALUES (?, ?, ?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(TrackedLegAndNow trackedLegAndNow) throws SQLException {
|
||||
getPreparedStatement().setString(1, trackedLegAndNow.getTrackedLeg().getTrackedRace().getRace().getName());
|
||||
getPreparedStatement().setString(2, trackedLegAndNow.getTrackedLeg().getTrackedRace().getTrackedRegatta().getRegatta().getName());
|
||||
getPreparedStatement().setInt(3, trackedLegAndNow.getTrackedLeg().getLeg().getZeroBasedIndexOfStartWaypoint());
|
||||
final LegType legType;
|
||||
try {
|
||||
legType = trackedLegAndNow.getTrackedLeg().getLegType(trackedLegAndNow.getNow());
|
||||
getPreparedStatement().setString(4, legType.name());
|
||||
} catch (NoWindException nwe) {
|
||||
getPreparedStatement().setString(4, null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
|
||||
import com.sap.sailing.domain.tracking.WindPositionMode;
|
||||
import com.sap.sailing.hanaexport.jaxrs.api.InsertLegStatsStatement.TrackedLegOfCompetitorRankingInfoCacheAndNow;
|
||||
import com.sap.sse.common.Speed;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class InsertLegStatsStatement extends AbstractPreparedInsertStatement<TrackedLegOfCompetitorRankingInfoCacheAndNow> {
|
||||
static class TrackedLegOfCompetitorRankingInfoCacheAndNow {
|
||||
private final TimePoint now;
|
||||
private final RankingInfo rankingInfo;
|
||||
private final WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache;
|
||||
private final TrackedLegOfCompetitor trackedLegOfCompetitor;
|
||||
public TrackedLegOfCompetitorRankingInfoCacheAndNow(TimePoint now, RankingInfo rankingInfo,
|
||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache,
|
||||
TrackedLegOfCompetitor trackedLegOfCompetitor) {
|
||||
super();
|
||||
this.now = now;
|
||||
this.rankingInfo = rankingInfo;
|
||||
this.cache = cache;
|
||||
this.trackedLegOfCompetitor = trackedLegOfCompetitor;
|
||||
}
|
||||
public TimePoint getNow() {
|
||||
return now;
|
||||
}
|
||||
public RankingInfo getRankingInfo() {
|
||||
return rankingInfo;
|
||||
}
|
||||
public WindLegTypeAndLegBearingAndORCPerformanceCurveCache getCache() {
|
||||
return cache;
|
||||
}
|
||||
public TrackedLegOfCompetitor getTrackedLegOfCompetitor() {
|
||||
return trackedLegOfCompetitor;
|
||||
}
|
||||
}
|
||||
|
||||
protected InsertLegStatsStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"LegStats\" (\"race\", \"regatta\", \"number\", \"competitorId\", \"rankOneBased\", \"distanceSailedInMeters\", \"elapsedTimeInSeconds\", "+
|
||||
"\"avgCrossTrackErrorInMeters\", \"absoluteAvgCrossTrackErrorInMeters\", \"numberOfTacks\", "+
|
||||
"\"numberOfGybes\", \"numberOfPenaltyCircles\", \"avgVelocityMadeGoodInKnots\", \"gapToLeaderInSeconds\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(TrackedLegOfCompetitorRankingInfoCacheAndNow trackedLegOfCompetitorAndNow) throws SQLException {
|
||||
getPreparedStatement().setString(1, trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getTrackedLeg().getTrackedRace().getRace().getName());
|
||||
getPreparedStatement().setString(2, trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getTrackedLeg().getTrackedRace().getTrackedRegatta().getRegatta().getName());
|
||||
getPreparedStatement().setInt(3, trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getTrackedLeg().getLeg().getZeroBasedIndexOfStartWaypoint());
|
||||
getPreparedStatement().setString(4, trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getCompetitor().getId().toString());
|
||||
getPreparedStatement().setInt(5, trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getRank(trackedLegOfCompetitorAndNow.getNow()));
|
||||
setDouble(6, metersOr0ForNull(trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getDistanceTraveled(trackedLegOfCompetitorAndNow.getNow())));
|
||||
setDouble(7, secondsOr0ForNull(trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getTime(trackedLegOfCompetitorAndNow.getNow())));
|
||||
setDouble(8, metersOr0ForNull(trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getAverageSignedCrossTrackError(trackedLegOfCompetitorAndNow.getNow(), /* waitForLatest */ false)));
|
||||
setDouble(9, metersOr0ForNull(trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getAverageAbsoluteCrossTrackError(trackedLegOfCompetitorAndNow.getNow(), /* waitForLatest */ false)));
|
||||
try {
|
||||
getPreparedStatement().setInt(10, intOr0ForNull(trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getNumberOfTacks(trackedLegOfCompetitorAndNow.getNow(), /* waitForLatest */ false)));
|
||||
getPreparedStatement().setInt(11, intOr0ForNull(trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getNumberOfJibes(trackedLegOfCompetitorAndNow.getNow(), /* waitForLatest */ false)));
|
||||
getPreparedStatement().setInt(12, intOr0ForNull(trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getNumberOfPenaltyCircles(trackedLegOfCompetitorAndNow.getNow(), /* waitForLatest */ false)));
|
||||
} catch (NoWindException nwe) {
|
||||
getPreparedStatement().setInt(10, 0);
|
||||
getPreparedStatement().setInt(11, 0);
|
||||
getPreparedStatement().setInt(12, 0);
|
||||
}
|
||||
final Speed vmg = trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getAverageVelocityMadeGood(trackedLegOfCompetitorAndNow.getNow());
|
||||
setDouble(13, vmg==null?0:vmg.getKnots());
|
||||
setDouble(14, secondsOr0ForNull(trackedLegOfCompetitorAndNow.getTrackedLegOfCompetitor().getGapToLeader(trackedLegOfCompetitorAndNow.getNow(), WindPositionMode.LEG_MIDDLE,
|
||||
trackedLegOfCompetitorAndNow.getRankingInfo(), trackedLegOfCompetitorAndNow.getCache())));
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.Date;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.hanaexport.jaxrs.api.InsertManeuverStatement.ManeuverTrackedRaceAndCompetitor;
|
||||
|
||||
public class InsertManeuverStatement extends AbstractPreparedInsertStatement<ManeuverTrackedRaceAndCompetitor> {
|
||||
static class ManeuverTrackedRaceAndCompetitor {
|
||||
private final Maneuver maneuver;
|
||||
private final TrackedRace trackedRace;
|
||||
private final Competitor competitor;
|
||||
public ManeuverTrackedRaceAndCompetitor(Maneuver maneuver, TrackedRace trackedRace, Competitor competitor) {
|
||||
super();
|
||||
this.maneuver = maneuver;
|
||||
this.trackedRace = trackedRace;
|
||||
this.competitor = competitor;
|
||||
}
|
||||
public Maneuver getManeuver() {
|
||||
return maneuver;
|
||||
}
|
||||
public TrackedRace getTrackedRace() {
|
||||
return trackedRace;
|
||||
}
|
||||
public Competitor getCompetitor() {
|
||||
return competitor;
|
||||
}
|
||||
}
|
||||
|
||||
protected InsertManeuverStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Maneuver\" (\"race\", \"regatta\", \"competitorId\", \"timepoint\", \"type\", \"newTack\", "+
|
||||
"\"lossInMeters\", \"speedBeforeInKnots\", \"speedAfterInKnots\", "+
|
||||
"\"courseBeforeInTrueDegrees\", \"courseAfterInTrueDegrees\", \"directionChangeInDegrees\", \"maximumTurningRateInDegreesPerSecond\", "+
|
||||
"\"lowestSpeedInKnots\", \"toSide\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(ManeuverTrackedRaceAndCompetitor maneuverTrackedRaceAndCompetitor) throws SQLException {
|
||||
getPreparedStatement().setString(1, maneuverTrackedRaceAndCompetitor.getTrackedRace().getRace().getName());
|
||||
getPreparedStatement().setString(2, maneuverTrackedRaceAndCompetitor.getTrackedRace().getTrackedRegatta().getRegatta().getName());
|
||||
getPreparedStatement().setString(3, maneuverTrackedRaceAndCompetitor.getCompetitor().getId().toString());
|
||||
getPreparedStatement().setDate(4, new Date(maneuverTrackedRaceAndCompetitor.getManeuver().getTimePoint().asMillis()));
|
||||
getPreparedStatement().setString(5, maneuverTrackedRaceAndCompetitor.getManeuver().getType().name());
|
||||
getPreparedStatement().setString(6, maneuverTrackedRaceAndCompetitor.getManeuver().getNewTack().name());
|
||||
if (maneuverTrackedRaceAndCompetitor.getManeuver().getManeuverLoss() != null) {
|
||||
setDouble(7,
|
||||
maneuverTrackedRaceAndCompetitor.getManeuver().getManeuverLoss().getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle().getMeters()
|
||||
-maneuverTrackedRaceAndCompetitor.getManeuver().getManeuverLoss().getDistanceSailedProjectedOnMiddleManeuverAngle().getMeters());
|
||||
} else {
|
||||
setDouble(7, 0);
|
||||
}
|
||||
setDouble(8, maneuverTrackedRaceAndCompetitor.getManeuver().getSpeedWithBearingBefore().getKnots());
|
||||
setDouble(9, maneuverTrackedRaceAndCompetitor.getManeuver().getSpeedWithBearingAfter().getKnots());
|
||||
setDouble(10, maneuverTrackedRaceAndCompetitor.getManeuver().getSpeedWithBearingBefore().getBearing().getDegrees());
|
||||
setDouble(11, maneuverTrackedRaceAndCompetitor.getManeuver().getSpeedWithBearingAfter().getBearing().getDegrees());
|
||||
setDouble(12, maneuverTrackedRaceAndCompetitor.getManeuver().getDirectionChangeInDegrees());
|
||||
setDouble(13, maneuverTrackedRaceAndCompetitor.getManeuver().getMaxTurningRateInDegreesPerSecond());
|
||||
setDouble(14, maneuverTrackedRaceAndCompetitor.getManeuver().getLowestSpeed().getKnots());
|
||||
getPreparedStatement().setString(15, maneuverTrackedRaceAndCompetitor.getManeuver().getToSide().name());
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.hanaexport.jaxrs.api.InsertRaceResultStatement.RaceResult;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class InsertRaceResultStatement extends AbstractPreparedInsertStatement<RaceResult> {
|
||||
static class RaceResult {
|
||||
private final Regatta regatta;
|
||||
private final Leaderboard leaderboard;
|
||||
private final Competitor competitor;
|
||||
private final RaceColumn raceColumn;
|
||||
private final TimePoint now;
|
||||
public RaceResult(Regatta regatta, Leaderboard leaderboard, Competitor competitor, RaceColumn raceColumn,
|
||||
TimePoint now) {
|
||||
super();
|
||||
this.regatta = regatta;
|
||||
this.leaderboard = leaderboard;
|
||||
this.competitor = competitor;
|
||||
this.raceColumn = raceColumn;
|
||||
this.now = now;
|
||||
}
|
||||
public Regatta getRegatta() {
|
||||
return regatta;
|
||||
}
|
||||
public Leaderboard getLeaderboard() {
|
||||
return leaderboard;
|
||||
}
|
||||
public Competitor getCompetitor() {
|
||||
return competitor;
|
||||
}
|
||||
public RaceColumn getRaceColumn() {
|
||||
return raceColumn;
|
||||
}
|
||||
public TimePoint getNow() {
|
||||
return now;
|
||||
}
|
||||
}
|
||||
|
||||
protected InsertRaceResultStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"RaceResult\" (\"regatta\", \"raceColumn\", \"competitorId\", \"points\", "+
|
||||
"\"discarded\", \"irm\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(RaceResult raceResult) throws SQLException {
|
||||
getPreparedStatement().setString(1, raceResult.getRegatta().getName());
|
||||
getPreparedStatement().setString(2, raceResult.getRaceColumn().getName());
|
||||
getPreparedStatement().setString(3, raceResult.getCompetitor().getId().toString());
|
||||
final Double totalPoints = raceResult.getLeaderboard().getTotalPoints(raceResult.getCompetitor(), raceResult.getRaceColumn(), raceResult.getNow());
|
||||
setDouble(4, totalPoints == null ? 0 : totalPoints);
|
||||
getPreparedStatement().setBoolean(5, raceResult.getLeaderboard().isDiscarded(raceResult.getCompetitor(), raceResult.getRaceColumn(), raceResult.getNow()));
|
||||
final MaxPointsReason maxPointsReason = raceResult.getLeaderboard().getMaxPointsReason(raceResult.getCompetitor(), raceResult.getRaceColumn(), raceResult.getNow());
|
||||
getPreparedStatement().setString(6, (maxPointsReason == null ? MaxPointsReason.NONE : maxPointsReason).name());
|
||||
}
|
||||
}
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.Date;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.SpeedWithConfidence;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.hanaexport.jaxrs.api.InsertRaceStatement.TrackedRaceWithRaceColumnAndFleet;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class InsertRaceStatement extends AbstractPreparedInsertStatement<TrackedRaceWithRaceColumnAndFleet> {
|
||||
static class TrackedRaceWithRaceColumnAndFleet {
|
||||
private final TrackedRace trackedRace;
|
||||
private final RaceColumn raceColumn;
|
||||
private final Fleet fleet;
|
||||
public TrackedRaceWithRaceColumnAndFleet(TrackedRace trackedRace, RaceColumn raceColumn, Fleet fleet) {
|
||||
super();
|
||||
this.trackedRace = trackedRace;
|
||||
this.raceColumn = raceColumn;
|
||||
this.fleet = fleet;
|
||||
}
|
||||
public TrackedRace getTrackedRace() {
|
||||
return trackedRace;
|
||||
}
|
||||
public RaceColumn getRaceColumn() {
|
||||
return raceColumn;
|
||||
}
|
||||
public Fleet getFleet() {
|
||||
return fleet;
|
||||
}
|
||||
}
|
||||
|
||||
protected InsertRaceStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Race\" (\"name\", \"regatta\", \"raceColumn\", \"fleet\", \"startOfTracking\", "+
|
||||
"\"startOfRace\", \"endOfTracking\", \"endOfRace\", \"avgWindSpeedInKnots\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(TrackedRaceWithRaceColumnAndFleet raceColumnFleetAndTrackedRace) throws SQLException {
|
||||
final TrackedRace trackedRace = raceColumnFleetAndTrackedRace.getTrackedRace();
|
||||
getPreparedStatement().setString(1, trackedRace.getRace().getName());
|
||||
getPreparedStatement().setString(2, trackedRace.getTrackedRegatta().getRegatta().getName());
|
||||
getPreparedStatement().setString(3, raceColumnFleetAndTrackedRace.getRaceColumn().getName());
|
||||
getPreparedStatement().setString(4, raceColumnFleetAndTrackedRace.getFleet().getName());
|
||||
if (trackedRace.getStartOfTracking() != null) {
|
||||
getPreparedStatement().setDate(5, new Date(trackedRace.getStartOfTracking().asMillis()));
|
||||
} else {
|
||||
getPreparedStatement().setDate(5, null);
|
||||
}
|
||||
if (trackedRace.getStartOfRace() != null) {
|
||||
getPreparedStatement().setDate(6, new Date(trackedRace.getStartOfRace().asMillis()));
|
||||
} else {
|
||||
getPreparedStatement().setDate(6, null);
|
||||
}
|
||||
if (trackedRace.getEndOfTracking() != null) {
|
||||
getPreparedStatement().setDate(7, new Date(trackedRace.getEndOfTracking().asMillis()));
|
||||
} else {
|
||||
getPreparedStatement().setDate(7, null);
|
||||
}
|
||||
if (trackedRace.getEndOfRace() != null) {
|
||||
getPreparedStatement().setDate(8, new Date(trackedRace.getEndOfRace().asMillis()));
|
||||
} else {
|
||||
getPreparedStatement().setDate(8, null);
|
||||
}
|
||||
final SpeedWithConfidence<TimePoint> averageWind = trackedRace.getAverageWindSpeedWithConfidenceWithNumberOfSamples(/* number of samples */ 5);
|
||||
if (averageWind != null) {
|
||||
setDouble(9, averageWind.getObject().getKnots());
|
||||
} else {
|
||||
setDouble(9, 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.NavigableSet;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.hanaexport.jaxrs.api.InsertRaceStatsStatement.TrackedRaceWithCompetitorAndStartWaypoint;
|
||||
import com.sap.sse.common.Speed;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class InsertRaceStatsStatement extends AbstractPreparedInsertStatement<TrackedRaceWithCompetitorAndStartWaypoint> {
|
||||
static class TrackedRaceWithCompetitorAndStartWaypoint {
|
||||
private final TimePoint now;
|
||||
private final Waypoint startWaypoint;
|
||||
private final Competitor competitor;
|
||||
private final TrackedRace trackedRace;
|
||||
public TrackedRaceWithCompetitorAndStartWaypoint(TimePoint now, Waypoint startWaypoint, Competitor competitor,
|
||||
TrackedRace trackedRace) {
|
||||
super();
|
||||
this.now = now;
|
||||
this.startWaypoint = startWaypoint;
|
||||
this.competitor = competitor;
|
||||
this.trackedRace = trackedRace;
|
||||
}
|
||||
public TimePoint getNow() {
|
||||
return now;
|
||||
}
|
||||
public Waypoint getStartWaypoint() {
|
||||
return startWaypoint;
|
||||
}
|
||||
public Competitor getCompetitor() {
|
||||
return competitor;
|
||||
}
|
||||
public TrackedRace getTrackedRace() {
|
||||
return trackedRace;
|
||||
}
|
||||
}
|
||||
|
||||
protected InsertRaceStatsStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"RaceStats\" (\"race\", \"regatta\", \"competitorId\", \"rankOneBased\", \"distanceSailedInMeters\", \"elapsedTimeInSeconds\", "+
|
||||
"\"avgCrossTrackErrorInMeters\", \"absoluteAvgCrossTrackErrorInMeters\", \"numberOfTacks\", "+
|
||||
"\"numberOfGybes\", \"numberOfPenaltyCircles\", \"startDelayInSeconds\", \"distanceFromStartLineInMetersAtStart\", "+
|
||||
"\"speedWhenCrossingStartLineInKnots\", \"startTack\") "+
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(TrackedRaceWithCompetitorAndStartWaypoint raceColumnFleetAndTrackedRace) throws SQLException {
|
||||
final TrackedRace trackedRace = raceColumnFleetAndTrackedRace.getTrackedRace();
|
||||
final Competitor competitor = raceColumnFleetAndTrackedRace.getCompetitor();
|
||||
final TimePoint now = raceColumnFleetAndTrackedRace.getNow();
|
||||
getPreparedStatement().setString(1, trackedRace.getRace().getName());
|
||||
getPreparedStatement().setString(2, trackedRace.getTrackedRegatta().getRegatta().getName());
|
||||
getPreparedStatement().setString(3, competitor.getId().toString());
|
||||
getPreparedStatement().setInt(4, trackedRace.getRank(competitor, now));
|
||||
setDouble(5, metersOr0ForNull(trackedRace.getDistanceTraveled(competitor, now)));
|
||||
setDouble(6, secondsOr0ForNull(trackedRace.getTimeSailedSinceRaceStart(competitor, now)));
|
||||
setDouble(7, metersOr0ForNull(trackedRace.getAverageSignedCrossTrackError(competitor, now, /* waitForLatest */ false)));
|
||||
setDouble(8, metersOr0ForNull(trackedRace.getAverageAbsoluteCrossTrackError(competitor, now, /* waitForLatest */ false)));
|
||||
final Iterable<Maneuver> maneuvers = trackedRace.getManeuvers(competitor, /* waitForLatest */ false);
|
||||
getPreparedStatement().setInt(9, Util.size(Util.filter(maneuvers, m->m.getType() == ManeuverType.TACK)));
|
||||
getPreparedStatement().setInt(10, Util.size(Util.filter(maneuvers, m->m.getType() == ManeuverType.JIBE)));
|
||||
getPreparedStatement().setInt(11, Util.size(Util.filter(maneuvers, m->m.getType() == ManeuverType.PENALTY_CIRCLE)));
|
||||
final TimePoint startOfRace = trackedRace.getStartOfRace();
|
||||
final double startDelay;
|
||||
Tack startTack;
|
||||
if (raceColumnFleetAndTrackedRace.getStartWaypoint() != null && startOfRace != null) {
|
||||
NavigableSet<MarkPassing> competitorMarkPassings = trackedRace.getMarkPassings(competitor);
|
||||
trackedRace.lockForRead(competitorMarkPassings);
|
||||
try {
|
||||
if (!Util.isEmpty(competitorMarkPassings)) {
|
||||
final MarkPassing competitorStartMarkPassing = competitorMarkPassings.iterator().next();
|
||||
final TimePoint competitorStartTime = competitorStartMarkPassing.getTimePoint();
|
||||
startDelay = secondsOr0ForNull(startOfRace.until(competitorStartTime));
|
||||
try {
|
||||
startTack = trackedRace.getTack(competitor, competitorStartTime);
|
||||
} catch (NoWindException e) {
|
||||
startTack = null;
|
||||
}
|
||||
} else {
|
||||
startDelay = 0;
|
||||
startTack = null;
|
||||
}
|
||||
} finally {
|
||||
trackedRace.unlockAfterRead(competitorMarkPassings);
|
||||
}
|
||||
} else {
|
||||
startDelay = 0;
|
||||
startTack = null;
|
||||
}
|
||||
setDouble(12, startDelay);
|
||||
if (startOfRace != null) {
|
||||
setDouble(13, metersOr0ForNull(trackedRace.getDistanceToStartLine(competitor, startOfRace)));
|
||||
final Speed speedWhenCrossingStartLine = trackedRace.getSpeedWhenCrossingStartLine(competitor);
|
||||
setDouble(14, speedWhenCrossingStartLine==null?0:speedWhenCrossingStartLine.getKnots());
|
||||
getPreparedStatement().setString(15, startTack==null?null:startTack.name());
|
||||
} else {
|
||||
setDouble(13, 0);
|
||||
setDouble(14, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
java/com.sap.sailing.hanaexport/src/com/sap/sailing/hanaexport/jaxrs/api/InsertRegattaStatement.java
Executable
+43
@@ -0,0 +1,43 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.hanaexport.jaxrs.api.InsertRegattaStatement.RegattaAndEvent;
|
||||
|
||||
public class InsertRegattaStatement extends AbstractPreparedInsertStatement<RegattaAndEvent> {
|
||||
static class RegattaAndEvent {
|
||||
private final Regatta regatta;
|
||||
private final Event event;
|
||||
public RegattaAndEvent(Regatta regatta, Event event) {
|
||||
super();
|
||||
this.regatta = regatta;
|
||||
this.event = event;
|
||||
}
|
||||
public Regatta getRegatta() {
|
||||
return regatta;
|
||||
}
|
||||
public Event getEvent() {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
protected InsertRegattaStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"Regatta\" (\"name\", \"boatClass\", \"scoringScheme\", \"rankingMetric\", \"eventId\") "+
|
||||
"VALUES (?, ?, ?, ?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(RegattaAndEvent regattaAndEvent) throws SQLException {
|
||||
final Regatta regatta = regattaAndEvent.getRegatta();
|
||||
final Event event = regattaAndEvent.getEvent();
|
||||
getPreparedStatement().setString(1, regatta.getName());
|
||||
getPreparedStatement().setString(2, regatta.getBoatClass().getName());
|
||||
getPreparedStatement().setString(3, regatta.getScoringScheme().getType().name());
|
||||
getPreparedStatement().setString(4, regatta.getRankingMetricType().name());
|
||||
getPreparedStatement().setString(5, event == null ? null : event.getId().toString());
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
|
||||
public class InsertScoringSchemeStatement extends AbstractPreparedInsertStatement<ScoringScheme> {
|
||||
protected InsertScoringSchemeStatement(Connection connection) throws SQLException {
|
||||
super(connection.prepareStatement(
|
||||
"INSERT INTO SAILING.\"ScoringScheme\" (\"id\", \"higherIsBetter\") VALUES (?, ?);"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameterizeStatement(ScoringScheme scoringScheme) throws SQLException {
|
||||
getPreparedStatement().setString(1, scoringScheme.getType().name());
|
||||
getPreparedStatement().setBoolean(2, scoringScheme.isHigherBetter());
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.sap.sailing.hanaexport.jaxrs.api;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Can insert objects of type {@code T} using a prepared statement, in batch mode.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public interface PreparedInsertStatement<T> {
|
||||
PreparedStatement getPreparedStatement();
|
||||
|
||||
void parameterizeStatement(T objectToInsert) throws SQLException;
|
||||
|
||||
default void insert(T objectToInsert) throws SQLException {
|
||||
parameterizeStatement(objectToInsert);
|
||||
getPreparedStatement().execute();
|
||||
}
|
||||
|
||||
default void insertBatch(Iterable<T> objectsToInsert) throws SQLException {
|
||||
for (final T objectToInsert : objectsToInsert) {
|
||||
insertBatch(objectToInsert);
|
||||
}
|
||||
}
|
||||
|
||||
default void insertBatch(final T objectToInsert) throws SQLException {
|
||||
parameterizeStatement(objectToInsert);
|
||||
getPreparedStatement().addBatch();
|
||||
}
|
||||
|
||||
default int[] executeBatch() throws SQLException {
|
||||
return getPreparedStatement().executeBatch();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -141,7 +141,7 @@ public class LandscapeManagementWriteServiceImpl extends ResultCachingProxiedRem
|
||||
/**
|
||||
* The timeout for a host to come up
|
||||
*/
|
||||
private static final Optional<Duration> WAIT_FOR_HOST_TIMEOUT = Optional.of(Duration.ONE_MINUTE.times(10));
|
||||
private static final Optional<Duration> WAIT_FOR_HOST_TIMEOUT = Optional.of(Duration.ONE_MINUTE.times(30));
|
||||
|
||||
private static final String SAILING_TARGET_GROUP_NAME_PREFIX = "S-";
|
||||
|
||||
|
||||
+12
@@ -8,6 +8,8 @@ import com.sap.sse.landscape.DefaultProcessConfigurationVariables;
|
||||
import com.sap.sse.landscape.InboundReplicationConfiguration;
|
||||
import com.sap.sse.landscape.OutboundReplicationConfiguration;
|
||||
import com.sap.sse.landscape.ProcessConfigurationVariable;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
import com.sap.sse.landscape.mongodb.MongoEndpoint;
|
||||
|
||||
public class SailingAnalyticsReplicaConfiguration<ShardingKey>
|
||||
extends SailingAnalyticsApplicationConfiguration<ShardingKey> {
|
||||
@@ -24,6 +26,8 @@ extends SailingAnalyticsApplicationConfiguration<ShardingKey> {
|
||||
* {@code "live-replica-server"}.</li>
|
||||
* <li>If no {@link #setDatabaseName(String) database name is set} explicitly, it defaults to the
|
||||
* {@link #getServerName() server name} with the suffix {@code -replica} appended to it.</li>
|
||||
* <li>If no {@link #setDatabaseConfiguration(Database) database configuration is set} explicitly, it defaults
|
||||
* to the "replica" replica set on "localhost:27017" on the replica node.</li>
|
||||
* </ul>
|
||||
*
|
||||
* TODO we could default the set of replicables to replicate, competing with the live-replica-server environment
|
||||
@@ -40,6 +44,8 @@ extends SailingAnalyticsApplicationConfiguration<ShardingKey> {
|
||||
protected static class BuilderImpl<BuilderT extends Builder<BuilderT, ShardingKey>, ShardingKey>
|
||||
extends SailingAnalyticsApplicationConfiguration.BuilderImpl<BuilderT, SailingAnalyticsReplicaConfiguration<ShardingKey>, ShardingKey>
|
||||
implements Builder<BuilderT, ShardingKey> {
|
||||
private static final String DEFAULT_MONGO_REPLICA_SET_NAME_FOR_REPLICA = "replica";
|
||||
|
||||
@Override
|
||||
public OutboundReplicationConfiguration getOutboundReplicationConfiguration() {
|
||||
final OutboundReplicationConfiguration.Builder resultBuilder;
|
||||
@@ -56,6 +62,12 @@ extends SailingAnalyticsApplicationConfiguration<ShardingKey> {
|
||||
}
|
||||
return resultBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Database getDatabaseConfiguration() {
|
||||
return isDatabaseConfigurationSet() ? super.getDatabaseConfiguration() :
|
||||
Database.of(MongoEndpoint.of("localhost", 27017, DEFAULT_MONGO_REPLICA_SET_NAME_FOR_REPLICA), getDatabaseName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<InboundReplicationConfiguration> getInboundReplicationConfiguration() {
|
||||
|
||||
@@ -3,6 +3,7 @@ source.. = src/,\
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
./.well-known/,\
|
||||
WEB-INF/web.xml,\
|
||||
index.html,\
|
||||
release_notes.css,\
|
||||
|
||||
+5
-1
@@ -190,7 +190,11 @@ implements UserDataProvider {
|
||||
}
|
||||
|
||||
protected Database getDatabaseConfiguration() {
|
||||
return databaseConfiguration == null ? getLandscape().getDatabase(getRegion(), getDatabaseName()) : databaseConfiguration;
|
||||
return isDatabaseConfigurationSet() ? databaseConfiguration : getLandscape().getDatabase(getRegion(), getDatabaseName());
|
||||
}
|
||||
|
||||
protected boolean isDatabaseConfigurationSet() {
|
||||
return databaseConfiguration != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,14 +5,18 @@ import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.sap.sse.common.Named;
|
||||
import com.sap.sse.landscape.DefaultProcessConfigurationVariables;
|
||||
import com.sap.sse.landscape.ProcessConfigurationVariable;
|
||||
import com.sap.sse.landscape.UserDataProvider;
|
||||
import com.sap.sse.landscape.mongodb.impl.DatabaseImpl;
|
||||
|
||||
public interface Database extends UserDataProvider, Named {
|
||||
static final Logger logger = Logger.getLogger(Database.class.getName());
|
||||
|
||||
/**
|
||||
* Obtains the database-specific connection URI that clients can use to connect to the replica set hosting this
|
||||
* database. See also {@link MongoReplicaSet#getConnectionURI()}.
|
||||
@@ -48,5 +52,12 @@ public interface Database extends UserDataProvider, Named {
|
||||
/**
|
||||
* Drops the database.
|
||||
*/
|
||||
void drop() throws URISyntaxException;
|
||||
default void drop() throws URISyntaxException {
|
||||
logger.info("Dropping database "+this);
|
||||
getMongoDatabase().drop();
|
||||
}
|
||||
|
||||
static Database of(MongoEndpoint mongoEndpoint, String databaseName) {
|
||||
return new DatabaseImpl(mongoEndpoint, databaseName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.mongodb.MongoClientURI;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.session.ClientSession;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.landscape.mongodb.impl.SimpleMongoEndpointImpl;
|
||||
|
||||
/**
|
||||
* A MongoDB endpoint that an application can connect to. It can produce a {@link URI} the client can use to connect to,
|
||||
@@ -19,6 +20,14 @@ import com.sap.sse.common.Duration;
|
||||
*
|
||||
*/
|
||||
public interface MongoEndpoint {
|
||||
static MongoEndpoint of(String hostname, int port) {
|
||||
return new SimpleMongoEndpointImpl(hostname, port);
|
||||
}
|
||||
|
||||
static MongoEndpoint of(String hostname, int port, String replicaSetName) {
|
||||
return new SimpleMongoEndpointImpl(hostname, port, replicaSetName);
|
||||
}
|
||||
|
||||
/**
|
||||
* When invoked on a {@link MongoProcess} that is not currently equipped with a public IP address, a
|
||||
* {@link NullPointerException} will result. Consider using {@link #getURI(Optional, Optional)} to wait for
|
||||
@@ -28,6 +37,24 @@ public interface MongoEndpoint {
|
||||
|
||||
URI getURI(Optional<Database> optionalDb, Optional<Duration> timeoutEmptyMeaningForever) throws URISyntaxException;
|
||||
|
||||
default URI getURI(Optional<Database> optionalDb, String hostname, int port, Optional<String> replicaSetName) throws URISyntaxException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("mongodb://");
|
||||
sb.append(hostname);
|
||||
sb.append(":");
|
||||
sb.append(port);
|
||||
sb.append("/");
|
||||
optionalDb.ifPresent(db->sb.append(db.getName()));
|
||||
replicaSetName.ifPresent(rsName->appendReplicaSetParametersToURI(rsName, sb));
|
||||
return new URI(sb.toString());
|
||||
}
|
||||
|
||||
default void appendReplicaSetParametersToURI(String replicaSetName, StringBuilder uriStringBuilder) {
|
||||
uriStringBuilder.append("?replicaSet=");
|
||||
uriStringBuilder.append(replicaSetName);
|
||||
uriStringBuilder.append("&retryWrites=true&readPreference=nearest");
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all MongoDB databases available in this end point
|
||||
*/
|
||||
|
||||
@@ -11,25 +11,14 @@ import com.sap.sse.landscape.RotatingFileBasedLog;
|
||||
public interface MongoProcess extends Process<RotatingFileBasedLog, MongoMetrics>, MongoEndpoint {
|
||||
@Override
|
||||
default URI getURI(Optional<Database> optionalDb) throws URISyntaxException {
|
||||
return getURI(optionalDb, getHostname());
|
||||
return getURI(optionalDb, getHostname(), getPort(), /* no replica set name */ Optional.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
default URI getURI(Optional<Database> optionalDb, Optional<Duration> timeoutEmptyMeaningForever) throws URISyntaxException {
|
||||
return getURI(optionalDb, getHostname(timeoutEmptyMeaningForever));
|
||||
return getURI(optionalDb, getHostname(timeoutEmptyMeaningForever), getPort(), /* no replica set name */ Optional.empty());
|
||||
}
|
||||
|
||||
default URI getURI(Optional<Database> optionalDb, String hostname) throws URISyntaxException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("mongodb://");
|
||||
sb.append(hostname);
|
||||
sb.append(":");
|
||||
sb.append(getPort());
|
||||
sb.append("/");
|
||||
optionalDb.ifPresent(db->sb.append(db.getName()));
|
||||
return new URI(sb.toString());
|
||||
}
|
||||
|
||||
boolean isInReplicaSet() throws URISyntaxException;
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,9 +49,7 @@ public interface MongoReplicaSet extends Named, MongoEndpoint {
|
||||
result.append(String.join(",", hostSpecs));
|
||||
result.append("/");
|
||||
optionalDb.ifPresent(db->result.append(db.getName()));
|
||||
result.append("?replicaSet=");
|
||||
result.append(getName());
|
||||
result.append("&retryWrites=true&readPreference=nearest");
|
||||
appendReplicaSetParametersToURI(getName(), result);
|
||||
return new URI(result.toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
package com.sap.sse.landscape.mongodb.impl;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sse.common.impl.NamedImpl;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
import com.sap.sse.landscape.mongodb.MongoEndpoint;
|
||||
|
||||
public class DatabaseImpl extends NamedImpl implements Database {
|
||||
private static final Logger logger = Logger.getLogger(DatabaseImpl.class.getName());
|
||||
private static final long serialVersionUID = -3816220771822620058L;
|
||||
private final MongoEndpoint endpoint;
|
||||
|
||||
@@ -22,12 +18,6 @@ public class DatabaseImpl extends NamedImpl implements Database {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drop() throws URISyntaxException {
|
||||
logger.info("Dropping database "+this);
|
||||
getMongoDatabase().drop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DatabaseImpl [endpoint=" + endpoint + "]";
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
package com.sap.sse.landscape.mongodb.impl;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
|
||||
public class SimpleMongoEndpointImpl extends MongoEndpointImpl {
|
||||
private final String hostname;
|
||||
private final int port;
|
||||
private final Optional<String> replicaSetName;
|
||||
|
||||
public SimpleMongoEndpointImpl(String hostname, int port) {
|
||||
this(hostname, port, /* no replica set name */ null);
|
||||
}
|
||||
|
||||
public SimpleMongoEndpointImpl(String hostname, int port, String replicaSetName) {
|
||||
super();
|
||||
this.hostname = hostname;
|
||||
this.port = port;
|
||||
this.replicaSetName = Optional.ofNullable(replicaSetName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getURI(Optional<Database> optionalDb) throws URISyntaxException {
|
||||
return getURI(optionalDb, hostname, port, replicaSetName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getURI(Optional<Database> optionalDb, Optional<Duration> timeoutEmptyMeaningForever) throws URISyntaxException {
|
||||
return getURI(optionalDb);
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -26,6 +26,7 @@ import com.google.gwt.user.cellview.client.TextColumn;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.util.NaturalComparator;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.celltable.AbstractSortableTextColumn;
|
||||
@@ -200,7 +201,7 @@ extends TableWrapper<UserDTO, S, StringMessages, TR> {
|
||||
string.add(t.getFullName());
|
||||
string.add(t.getEmail());
|
||||
string.add(t.getCompany());
|
||||
string.add(t.getUserGroups().toString());
|
||||
Util.addAll(Util.map(t.getUserGroups(), StrippedUserGroupDTO::getName), string);
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -536,7 +536,7 @@
|
||||
<!-- GWT version detected from dependencyManagement -->
|
||||
<execution>
|
||||
<configuration>
|
||||
<extraJvmArgs>-Dgwt.persistentunitcache=false -Xmx2560m -Djava.io.tmpdir=${env.TMP} -Dgwt.watchFileChanges=false</extraJvmArgs>
|
||||
<extraJvmArgs>-Dgwt.persistentunitcache=false -Xmx4g -Djava.io.tmpdir=${env.TMP} -Dgwt.watchFileChanges=false</extraJvmArgs>
|
||||
<fragmentCount>4</fragmentCount>
|
||||
<!--
|
||||
<userAgents>chrome</userAgents>
|
||||
|
||||
Reference in New Issue
Block a user