Merge branch 'master' into bug2775

Conflicts:
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
	java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java
This commit is contained in:
Steffen Schaefer committed 2016-07-11 11:18:46 +02:00
commit 793c2c0341
215 files changed
+11209 -6198

No files matched your search

@@ -19,7 +19,7 @@
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console -clean"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Djetty.port=8889 -Dreplication.exchangeName=sapsailinganalytics-replica -Declipse.ignoreApp=true -Dosgi.noShutdown=true&#13;&#10;-Dexpedition.udp.port=2011 -Xmx6000m -XX:+UseG1GC -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -XX:+UseMembar -Dmongo.dbName=replica -Dreplicate.on.start=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl -Dreplicate.master.queue.host=52.16.112.6 -Dreplicate.master.queue.port=5672 -Dreplicate.master.servlet.port=8888 -Dreplicate.master.servlet.host=54.154.72.33 -Dreplicate.master.exchange.name=sapsailinganalytics-dev"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Djetty.port=8889 -Dreplication.exchangeName=sapsailinganalytics-replica -Declipse.ignoreApp=true -Dosgi.noShutdown=true&#13;&#10;-Dexpedition.udp.port=2011 -Xmx6000m -XX:+UseG1GC -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -XX:+UseMembar -Dmongo.dbName=replica -Dreplicate.on.start=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.RegattaLogSensorDataTrackerTrackedRegattaListener -Dreplicate.master.queue.host=52.16.112.6 -Dreplicate.master.queue.port=5672 -Dreplicate.master.servlet.port=8888 -Dreplicate.master.servlet.host=54.154.72.33 -Dreplicate.master.exchange.name=sapsailinganalytics-dev"/>
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc}"/>
<stringAttribute key="pde.version" value="3.3"/>
<booleanAttribute key="show_selected_only" value="false"/>
@@ -21,7 +21,7 @@
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console -clean"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Djetty.port=8889 -Dreplication.exchangeName=sapsailinganalytics-replica -Declipse.ignoreApp=true -Dosgi.noShutdown=true&#13;&#10;-Dexpedition.udp.port=2011 -Xmx6000m -XX:+UseG1GC -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -XX:+UseMembar -Dmongo.dbName=replica -Dreplicate.on.start=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl -Dreplicate.master.queue.host=127.0.0.1 -Dreplicate.master.queue.port=5672 -Dreplicate.master.servlet.port=8888 -Dreplicate.master.servlet.host=127.0.0.1 -Dreplicate.master.exchange.name=sapsailinganalytics"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Djetty.port=8889 -Dreplication.exchangeName=sapsailinganalytics-replica -Declipse.ignoreApp=true -Dosgi.noShutdown=true&#13;&#10;-Dexpedition.udp.port=2011 -Xmx6000m -XX:+UseG1GC -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -XX:+UseMembar -Dmongo.dbName=replica -Dreplicate.on.start=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.RegattaLogSensorDataTrackerTrackedRegattaListener -Dreplicate.master.queue.host=127.0.0.1 -Dreplicate.master.queue.port=5672 -Dreplicate.master.servlet.port=8888 -Dreplicate.master.servlet.host=127.0.0.1 -Dreplicate.master.exchange.name=sapsailinganalytics"/>
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc}"/>
<stringAttribute key="pde.version" value="3.3"/>
<booleanAttribute key="show_selected_only" value="false"/>
@@ -12,6 +12,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
@@ -61,7 +62,7 @@ import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.polars.PolarDataService;
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
import com.sap.sailing.domain.ranking.RankingMetricConstructor;
import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
@@ -303,7 +304,7 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
*/
void updateStoredLeaderboardGroup(LeaderboardGroup leaderboardGroup);
DynamicTrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore, GPSFixStore gpsFixStore,
DynamicTrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore,
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, boolean useMarkPassingCalculator);
Regatta getOrCreateDefaultRegatta(String name, String boatClassName, Serializable id);
@@ -531,8 +532,8 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
PolarDataService getPolarDataService();
SimulationService getSimulationService();
GPSFixStore getGPSFixStore();
SensorFixStore getSensorFixStore();
RaceTracker getRaceTrackerById(Object id);
@@ -617,4 +618,11 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
ClassLoader getCombinedMasterDataClassLoader();
Iterable<Competitor> getCompetitorInOrderOfWindwardDistanceTraveledFarthestFirst(TrackedRace trackedRace, TimePoint timePoint);
/**
* Gets the {@link RaceTracker} associated with a given {@link RegattaAndRaceIdentifier}. If the {@link RaceTracker}
* isn't available yet, the given callback will be informed asynchronously on registration of the RaceTracker in
* question.
*/
void getRaceTrackerByRegattaAndRaceIdentifier(RegattaAndRaceIdentifier raceIdentifier, Consumer<RaceTracker> callback);
}
@@ -21,9 +21,11 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl;
import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl;
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
import com.sap.sailing.domain.persistence.racelog.tracking.GPSFixMongoHandler;
import com.sap.sailing.domain.persistence.racelog.tracking.FixMongoHandler;
import com.sap.sailing.domain.persistence.racelog.tracking.impl.DoubleVectorFixMongoHandlerImpl;
import com.sap.sailing.domain.persistence.racelog.tracking.impl.GPSFixMongoHandlerImpl;
import com.sap.sailing.domain.persistence.racelog.tracking.impl.GPSFixMovingMongoHandlerImpl;
import com.sap.sailing.domain.polars.PolarDataService;
@@ -60,6 +62,8 @@ public class Activator implements BundleActivator {
private ServiceTracker<MasterDataImportClassLoaderService, MasterDataImportClassLoaderService> masterDataImportClassLoaderServiceTracker;
private ServiceTracker<PolarDataService, PolarDataService> polarDataServiceTracker;
private OSGiBasedTrackedRegattaListener trackedRegattaListener;
public Activator() {
clearPersistentCompetitors = Boolean.valueOf(System.getProperty(CLEAR_PERSISTENT_COMPETITORS_PROPERTY_NAME, ""+false));
@@ -71,12 +75,14 @@ public class Activator implements BundleActivator {
extenderBundleTracker = new ExtenderBundleTracker(context);
extenderBundleTracker.open();
trackedRegattaListener = new OSGiBasedTrackedRegattaListener(context);
// At this point the OSGi resolver is used as device type service finder.
// In the case that we are not in an OSGi context (e.g. running a JUnit test instead),
// this code block is not run, and the test case can inject some other type of finder
// instead.
serviceFinderFactory = new CachedOsgiTypeBasedServiceFinderFactory(context);
racingEventService = new RacingEventServiceImpl(clearPersistentCompetitors, serviceFinderFactory);
racingEventService = new RacingEventServiceImpl(clearPersistentCompetitors, serviceFinderFactory, trackedRegattaListener);
masterDataImportClassLoaderServiceTracker = new ServiceTracker<MasterDataImportClassLoaderService, MasterDataImportClassLoaderService>(
context, MasterDataImportClassLoaderService.class,
@@ -98,19 +104,23 @@ public class Activator implements BundleActivator {
final GPSFixMongoHandlerImpl gpsFixMongoHandler = new GPSFixMongoHandlerImpl(racingEventService.getMongoObjectFactory(),
racingEventService.getDomainObjectFactory());
properties.put(TypeBasedServiceFinder.TYPE, GPSFixImpl.class.getName());
registrations.add(context.registerService(GPSFixMongoHandler.class,
registrations.add(context.registerService(FixMongoHandler.class,
gpsFixMongoHandler, properties));
// legacy type name; some DBs may still contain fixes marked with this old package name:
properties.put(TypeBasedServiceFinder.TYPE, "com.sap.sailing.domain.tracking.impl.GPSFixImpl");
registrations.add(context.registerService(GPSFixMongoHandler.class,
registrations.add(context.registerService(FixMongoHandler.class,
gpsFixMongoHandler, properties));
final GPSFixMovingMongoHandlerImpl gpsFixMovingMongoHandler = new GPSFixMovingMongoHandlerImpl(racingEventService.getMongoObjectFactory(),
racingEventService.getDomainObjectFactory());
properties.put(TypeBasedServiceFinder.TYPE, GPSFixMovingImpl.class.getName());
registrations.add(context.registerService(GPSFixMongoHandler.class, gpsFixMovingMongoHandler, properties));
registrations.add(context.registerService(FixMongoHandler.class, gpsFixMovingMongoHandler, properties));
// legacy type name; some DBs may still contain fixes marked with this old package name:
properties.put(TypeBasedServiceFinder.TYPE, "com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl");
registrations.add(context.registerService(GPSFixMongoHandler.class, gpsFixMovingMongoHandler, properties));
registrations.add(context.registerService(FixMongoHandler.class, gpsFixMovingMongoHandler, properties));
properties.put(TypeBasedServiceFinder.TYPE, DoubleVectorFixImpl.class.getName());
registrations.add(context.registerService(FixMongoHandler.class, new DoubleVectorFixMongoHandlerImpl(racingEventService.getMongoObjectFactory(),
racingEventService.getDomainObjectFactory()), properties));
registerPreferenceConvertersWhenUserStoreIsAvailable(context);
@@ -165,6 +175,7 @@ public class Activator implements BundleActivator {
for (ServiceRegistration<?> reg : registrations) {
reg.unregister();
}
trackedRegattaListener.close();
registrations.clear();
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
mbs.unregisterMBean(mBeanName);
@@ -0,0 +1,44 @@
package com.sap.sailing.server.impl;
import java.util.function.Consumer;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaListener;
import com.sap.sse.util.ServiceTrackerFactory;
public class OSGiBasedTrackedRegattaListener implements TrackedRegattaListener {
private ServiceTracker<TrackedRegattaListener, TrackedRegattaListener> serviceTracker;
public OSGiBasedTrackedRegattaListener(BundleContext context) {
serviceTracker = ServiceTrackerFactory.createAndOpen(context, TrackedRegattaListener.class);
serviceTracker.open(true);
}
public void close() {
serviceTracker.close();
}
private void forEachListener(Consumer<TrackedRegattaListener> consumer) {
for(ServiceReference<TrackedRegattaListener> serviceReference : serviceTracker.getServiceReferences()) {
TrackedRegattaListener listener = serviceTracker.getService(serviceReference);
if(listener != null) {
consumer.accept(listener);
}
}
}
@Override
public void regattaAdded(TrackedRegatta trackedRegatta) {
forEachListener((listener) -> listener.regattaAdded(trackedRegatta));
}
@Override
public void regattaRemoved(TrackedRegatta trackedRegatta) {
forEachListener((listener) -> listener.regattaRemoved(trackedRegatta));
}
}
@@ -35,6 +35,7 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -58,6 +59,7 @@ import com.sap.sailing.domain.abstractlog.race.state.RaceState;
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl;
import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.CompetitorStore.CompetitorUpdateListener;
@@ -110,6 +112,7 @@ import com.sap.sailing.domain.common.media.MediaTrack;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.domain.common.tracking.GPSFix;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.common.tracking.SensorFix;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.FlexibleRaceColumn;
import com.sap.sailing.domain.leaderboard.Leaderboard;
@@ -131,11 +134,11 @@ import com.sap.sailing.domain.persistence.MongoWindStoreFactory;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sailing.domain.persistence.media.MediaDB;
import com.sap.sailing.domain.persistence.media.MediaDBFactory;
import com.sap.sailing.domain.persistence.racelog.tracking.MongoGPSFixStoreFactory;
import com.sap.sailing.domain.persistence.racelog.tracking.MongoSensorFixStoreFactory;
import com.sap.sailing.domain.polars.PolarDataService;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
import com.sap.sailing.domain.ranking.RankingMetric.CompetitorRankingInfo;
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
@@ -144,8 +147,10 @@ import com.sap.sailing.domain.regattalike.HasRegattaLike;
import com.sap.sailing.domain.regattalike.IsRegattaLike;
import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike;
import com.sap.sailing.domain.regattalog.RegattaLogStore;
import com.sap.sailing.domain.tracking.DynamicSensorFixTrack;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
import com.sap.sailing.domain.tracking.EmptyTrackedRegattaListener;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceChangeListener;
@@ -156,6 +161,7 @@ import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRaceStatus;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaListener;
import com.sap.sailing.domain.tracking.WindStore;
import com.sap.sailing.domain.tracking.WindTracker;
import com.sap.sailing.domain.tracking.WindTrackerFactory;
@@ -183,6 +189,8 @@ import com.sap.sailing.server.operationaltransformation.CreateOrUpdateDeviceConf
import com.sap.sailing.server.operationaltransformation.CreateTrackedRace;
import com.sap.sailing.server.operationaltransformation.DataImportFailed;
import com.sap.sailing.server.operationaltransformation.RecordCompetitorGPSFix;
import com.sap.sailing.server.operationaltransformation.RecordCompetitorSensorFix;
import com.sap.sailing.server.operationaltransformation.RecordCompetitorSensorFixTrack;
import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFix;
import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFixForExistingTrack;
import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFixForNewMarkTrack;
@@ -295,6 +303,15 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
*/
private final ConcurrentHashMap<Object, NamedReentrantReadWriteLock> raceTrackersByIDLocks;
/**
* Using {@link #getRaceTrackerByRegattaAndRaceIdentifier(RegattaAndRaceIdentifier, Consumer)}, one can request a
* {@link RaceTracker} for a specific race. It can be that the requested {@link RaceTracker} isn't registered in
* {@link #raceTrackersByRegatta}. To not need a Thread to wait for the RaceTracker to get available, a callback
* will be registered that fires on registration of the RaceTracker. If the {@link RaceTracker} will not be
* registered, the callback only leads to a minor leak.
*/
private volatile transient ConcurrentHashMap<RegattaAndRaceIdentifier, Set<Consumer<RaceTracker>>> raceTrackerCallbacks;
/**
* Leaderboards managed by this racing event service
*/
@@ -361,7 +378,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
protected final DeviceConfigurationMapImpl configurationMap;
private final WindStore windStore;
private final GPSFixStore gpsFixStore;
private final SensorFixStore sensorFixStore;
/**
* This author should be used for server generated race log events
@@ -404,6 +421,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
private SailingServerConfiguration sailingServerConfiguration;
private final TrackedRegattaListener trackedRegattaListener;
/**
* Providing the constructor parameters for a new {@link RacingEventServiceImpl} instance is a bit tricky
* in some cases because containment and initialization order of some types is fairly tightly coupled.
@@ -432,15 +451,19 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
this(true, null);
}
public RacingEventServiceImpl(WindStore windStore, GPSFixStore gpsFixStore,
public RacingEventServiceImpl(WindStore windStore, SensorFixStore sensorFixStore,
TypeBasedServiceFinderFactory serviceFinderFactory) {
this(true, windStore, gpsFixStore, serviceFinderFactory);
this(true, windStore, sensorFixStore, serviceFinderFactory);
}
void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory) {
this(clearPersistentCompetitorStore, serviceFinderFactory, null);
}
/**
* Like {@link #RacingEventServiceImpl()}, but allows callers to specify that the persistent competitor collection
* be cleared before the service starts.
@@ -450,7 +473,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
* database collection cleared as well. Use with caution! When used with <code>false</code>, competitors
* created and stored during previous service executions will initially be loaded.
*/
public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory) {
public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListener trackedRegattaListener) {
this((final RaceLogResolver raceLogResolver)-> {
return new ConstructorParameters() {
private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory);
@@ -463,11 +486,11 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
@Override public DomainFactory getBaseDomainFactory() { return competitorStore.getBaseDomainFactory(); }
@Override public CompetitorStore getCompetitorStore() { return competitorStore; }
};
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory);
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory ,trackedRegattaListener);
}
private RacingEventServiceImpl(final boolean clearPersistentCompetitorStore, WindStore windStore,
GPSFixStore gpsFixStore, final TypeBasedServiceFinderFactory serviceFinderFactory) {
SensorFixStore sensorFixStore, final TypeBasedServiceFinderFactory serviceFinderFactory) {
this((final RaceLogResolver raceLogResolver)-> {
return new ConstructorParameters() {
private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory);
@@ -480,7 +503,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
@Override public DomainFactory getBaseDomainFactory() { return competitorStore.getBaseDomainFactory(); }
@Override public CompetitorStore getCompetitorStore() { return competitorStore; }
};
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, gpsFixStore, serviceFinderFactory);
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, sensorFixStore, serviceFinderFactory, null);
}
/**
@@ -490,7 +513,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
* persistence.
*/
public RacingEventServiceImpl(Function<RaceLogResolver, DomainObjectFactory> domainObjectFactoryProvider,
final MongoObjectFactory mongoObjectFactory, MediaDB mediaDB, WindStore windStore, GPSFixStore gpsFixStore) {
final MongoObjectFactory mongoObjectFactory, MediaDB mediaDB, WindStore windStore, SensorFixStore sensorFixStore) {
this((final RaceLogResolver raceLogResolver)-> {
return new ConstructorParameters() {
private final DomainObjectFactory domainObjectFactory = domainObjectFactoryProvider.apply(raceLogResolver);
@@ -500,11 +523,11 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
@Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); }
@Override public CompetitorStore getCompetitorStore() { return getBaseDomainFactory().getCompetitorStore(); }
};
}, mediaDB, windStore, gpsFixStore, null);
}, mediaDB, windStore, sensorFixStore, null, null);
}
public RacingEventServiceImpl(final DomainObjectFactory domainObjectFactory, MongoObjectFactory mongoObjectFactory,
MediaDB mediaDB, WindStore windStore, GPSFixStore gpsFixStore) {
MediaDB mediaDB, WindStore windStore, SensorFixStore sensorFixStore) {
this((final RaceLogResolver raceLogResolver)-> {
return new ConstructorParameters() {
@Override public DomainObjectFactory getDomainObjectFactory() { return domainObjectFactory; }
@@ -512,7 +535,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
@Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); }
@Override public CompetitorStore getCompetitorStore() { return getBaseDomainFactory().getCompetitorStore(); }
};
}, mediaDB, windStore, gpsFixStore, null);
}, mediaDB, windStore, sensorFixStore, null, null);
}
/**
@@ -525,7 +548,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
* associations per race tracked.
*/
public RacingEventServiceImpl(Function<RaceLogResolver, ConstructorParameters> constructorParametersProvider, MediaDB mediaDb,
WindStore windStore, GPSFixStore gpsFixStore, TypeBasedServiceFinderFactory serviceFinderFactory) {
final WindStore windStore, final SensorFixStore sensorFixStore, TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListener trackedRegattaListener) {
logger.info("Created " + this);
final ConstructorParameters constructorParameters = constructorParametersProvider.apply(this);
this.domainObjectFactory = constructorParameters.getDomainObjectFactory();
@@ -536,12 +559,11 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
this.mongoObjectFactory = constructorParameters.getMongoObjectFactory();
this.mediaDB = mediaDb;
this.competitorStore = constructorParameters.getCompetitorStore();
if (windStore == null) {
try {
windStore = MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory);
} catch (Exception e) {
throw new RuntimeException(e);
}
try {
this.windStore = windStore == null ? MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory,
domainObjectFactory) : windStore;
} catch (Exception e) {
throw new RuntimeException(e);
}
this.competitorStore.addCompetitorUpdateListener(new CompetitorUpdateListener() {
@Override
@@ -553,7 +575,6 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
competitor.getSearchTag()));
}
});
this.windStore = windStore;
this.dataImportLock = new DataImportLockWithProgress();
remoteSailingServerSet = new RemoteSailingServerSet(scheduler);
@@ -567,6 +588,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
false);
raceTrackersByID = new ConcurrentHashMap<>();
raceTrackersByIDLocks = new ConcurrentHashMap<>();
raceTrackerCallbacks = new ConcurrentHashMap<>();
leaderboardGroupsByName = new ConcurrentHashMap<>();
leaderboardGroupsByID = new ConcurrentHashMap<>();
leaderboardGroupsByNameLock = new NamedReentrantReadWriteLock("leaderboardGroupsByName for " + this, /* fair */
@@ -588,19 +610,19 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
this.regattaLogReplicator = new RegattaLogReplicator(this);
this.raceLogScoringReplicator = new RaceLogScoringReplicator(this);
this.mediaLibrary = new MediaLibrary();
if (gpsFixStore == null) {
try {
gpsFixStore = MongoGPSFixStoreFactory.INSTANCE.getMongoGPSFixStore(mongoObjectFactory,
domainObjectFactory, serviceFinderFactory);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
try {
this.sensorFixStore = sensorFixStore == null ? MongoSensorFixStoreFactory.INSTANCE.getMongoGPSFixStore(
mongoObjectFactory, domainObjectFactory, serviceFinderFactory) : sensorFixStore;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
this.gpsFixStore = gpsFixStore;
this.configurationMap = new DeviceConfigurationMapImpl();
this.serviceFinderFactory = serviceFinderFactory;
this.trackedRegattaListener = trackedRegattaListener == null ? EmptyTrackedRegattaListener.INSTANCE : trackedRegattaListener;
sailingServerConfiguration = domainObjectFactory.loadServerConfiguration();
final Iterable<Pair<Event, Boolean>> loadedEventsWithRequireStoreFlag = loadStoredEvents();
loadStoredRegattas();
@@ -1353,10 +1375,10 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
Regatta regatta = regattaToAddTo == null ? null : getRegatta(regattaToAddTo);
if (regatta == null) {
// create tracker and use an existing or create a default regatta
tracker = params.createRaceTracker(this, windStore, gpsFixStore, /* raceLogResolver */ this);
tracker = params.createRaceTracker(this, windStore, /* raceLogResolver */ this);
} else {
// use the regatta selected by the RaceIdentifier regattaToAddTo
tracker = params.createRaceTracker(regatta, this, windStore, gpsFixStore, /* raceLogResolver */ this);
tracker = params.createRaceTracker(regatta, this, windStore, /* raceLogResolver */ this);
assert tracker.getRegatta() == regatta;
}
LockUtil.lockForWrite(raceTrackersByRegattaLock);
@@ -1368,6 +1390,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
raceTrackersByRegatta.put(tracker.getRegatta(), trackers);
}
trackers.add(tracker);
notifyListenersForNewRaceTracker(tracker);
} finally {
LockUtil.unlockAfterWrite(raceTrackersByRegattaLock);
}
@@ -1403,11 +1426,6 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
logger.warning("Wind store mismatch. Requested wind store: " + windStore
+ ". Wind store in use by existing tracker: " + existingTrackersWindStore);
}
GPSFixStore existingTrackersGPSFixStore = tracker.getGPSFixStore();
if (!existingTrackersGPSFixStore.equals(gpsFixStore)) {
logger.warning("GPSFix store mismatch. Requested GPSFix store: " + gpsFixStore
+ ". GPSFix store in use by existing tracker: " + existingTrackersGPSFixStore);
}
}
if (timeoutInMilliseconds != -1) {
scheduleAbortTrackerAfterInitialTimeout(tracker, timeoutInMilliseconds);
@@ -1494,11 +1512,11 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
@Override
public DynamicTrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore,
GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
long millisecondsOverWhichToAverageSpeed, boolean useMarkPassingCalculator) {
DynamicTrackedRegatta trackedRegatta = getOrCreateTrackedRegatta(getRegatta(raceIdentifier));
RaceDefinition race = getRace(raceIdentifier);
return trackedRegatta.createTrackedRace(race, Collections.<Sideline> emptyList(), windStore, gpsFixStore,
return trackedRegatta.createTrackedRace(race, Collections.<Sideline> emptyList(), windStore,
delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
/* raceDefinitionSetToUpdate */null, useMarkPassingCalculator, /* raceLogResolver */ this);
}
@@ -1556,8 +1574,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
public void raceAdded(TrackedRace trackedRace) {
// replicate the addition of the tracked race:
CreateTrackedRace op = new CreateTrackedRace(trackedRace.getRaceIdentifier(), trackedRace.getWindStore(),
trackedRace.getGPSFixStore(), trackedRace.getDelayToLiveInMillis(),
trackedRace.getMillisecondsOverWhichToAverageWind(),
trackedRace.getDelayToLiveInMillis(), trackedRace.getMillisecondsOverWhichToAverageWind(),
trackedRace.getMillisecondsOverWhichToAverageSpeed());
replicate(op);
linkRaceToConfiguredLeaderboardColumns(trackedRace);
@@ -1615,13 +1632,13 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
}
@Override
public void startOfTrackingChanged(TimePoint startOfTracking) {
replicate(new UpdateStartOfTracking(getRaceIdentifier(), startOfTracking));
public void startOfTrackingChanged(TimePoint oldStartOfTracking, TimePoint newStartOfTracking) {
replicate(new UpdateStartOfTracking(getRaceIdentifier(), newStartOfTracking));
}
@Override
public void endOfTrackingChanged(TimePoint endOfTracking) {
replicate(new UpdateEndOfTracking(getRaceIdentifier(), endOfTracking));
public void endOfTrackingChanged(TimePoint oldEndOfTracking, TimePoint newEndOfTracking) {
replicate(new UpdateEndOfTracking(getRaceIdentifier(), newEndOfTracking));
}
@Override
@@ -1702,11 +1719,35 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
public void speedAveragingChanged(long oldMillisecondsOverWhichToAverage, long newMillisecondsOverWhichToAverage) {
replicate(new UpdateWindAveragingTime(getRaceIdentifier(), newMillisecondsOverWhichToAverage));
}
@Override
public void competitorSensorTrackAdded(DynamicSensorFixTrack<Competitor, ?> track) {
replicate(new RecordCompetitorSensorFixTrack(getRaceIdentifier(), track));
}
@Override
public void competitorSensorFixAdded(Competitor competitor, String trackName, SensorFix fix) {
replicate(new RecordCompetitorSensorFix(getRaceIdentifier(), competitor, trackName, fix));
}
private RegattaAndRaceIdentifier getRaceIdentifier() {
return trackedRace.getRaceIdentifier();
}
@Override
public void regattaLogAttached(RegattaLog regattaLog) {
// no action required
}
@Override
public void raceLogAttached(RaceLog regattaLog) {
// no action required
}
@Override
public void raceLogDetached(RaceLog raceLog) {
// no action required
}
}
/**
@@ -2116,6 +2157,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
replicate(new TrackRegatta(regatta.getRegattaIdentifier()));
regattaTrackingCache.put(regatta, result);
ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(result);
trackedRegattaListener.regattaAdded(result);
}
return result;
} finally {
@@ -2139,6 +2182,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
LockUtil.unlockAfterWrite(regattaTrackingCacheLock);
}
stopObservingRegattaForRedaultLeaderboardAndAutoLeaderboardLinking(trackedRegatta);
trackedRegattaListener.regattaRemoved(trackedRegatta);
}
@Override
@@ -3026,8 +3070,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
}
@Override
public GPSFixStore getGPSFixStore() {
return gpsFixStore;
public SensorFixStore getSensorFixStore() {
return sensorFixStore;
}
@Override
@@ -3310,4 +3354,55 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
}
return result;
}
@Override
public void getRaceTrackerByRegattaAndRaceIdentifier(RegattaAndRaceIdentifier raceIdentifier,
Consumer<RaceTracker> callback) {
LockUtil.lockForRead(regattasByNameLock);
Regatta regatta = regattasByName.get(raceIdentifier.getRegattaName());
LockUtil.unlockAfterRead(regattasByNameLock);
if (regatta != null) {
LockUtil.lockForRead(raceTrackersByRegattaLock);
try {
Set<RaceTracker> raceTrackersForRegatta = raceTrackersByRegatta.get(regatta);
if(raceTrackersForRegatta != null) {
for (RaceTracker raceTracker : raceTrackersForRegatta) {
if (raceTracker.getRaceIdentifiers().contains(raceIdentifier)) {
callback.accept(raceTracker);
return;
}
}
}
Util.addToValueSet(getRaceTrackerCallbacks(), raceIdentifier, callback);
} finally {
LockUtil.unlockAfterRead(raceTrackersByRegattaLock);
}
}
}
private ConcurrentHashMap<RegattaAndRaceIdentifier, Set<Consumer<RaceTracker>>> getRaceTrackerCallbacks() {
if (raceTrackerCallbacks == null) {
synchronized (this) {
if (raceTrackerCallbacks == null) {
raceTrackerCallbacks = new ConcurrentHashMap<>();
}
}
}
return raceTrackerCallbacks;
}
private void notifyListenersForNewRaceTracker(RaceTracker tracker) {
LockUtil.lockForRead(raceTrackersByRegattaLock);
try {
tracker.getRaceIdentifiers().forEach((raceIdentifier) -> {
Set<Consumer<RaceTracker>> callbacks = getRaceTrackerCallbacks().remove(raceIdentifier);
if (callbacks != null) {
callbacks.forEach((callback) -> callback.accept(tracker));
}
});
} finally {
LockUtil.unlockAfterRead(raceTrackersByRegattaLock);
}
}
}
@@ -31,9 +31,9 @@ import com.sap.sailing.domain.common.Wind;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.tracking.GPSFix;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.common.tracking.SensorFix;
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
import com.sap.sailing.domain.polars.PolarDataService;
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
import com.sap.sailing.domain.ranking.RankingMetric;
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
import com.sap.sailing.domain.tracking.CourseDesignChangedListener;
@@ -44,6 +44,7 @@ import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceAbortedListener;
import com.sap.sailing.domain.tracking.RaceChangeListener;
import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider;
import com.sap.sailing.domain.tracking.SensorFixTrack;
import com.sap.sailing.domain.tracking.StartTimeChangedListener;
import com.sap.sailing.domain.tracking.TrackedLeg;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
@@ -535,11 +536,6 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
return null;
}
@Override
public GPSFixStore getGPSFixStore() {
return null;
}
@Override
public void addRaceAbortedListener(RaceAbortedListener listener) {
}
@@ -554,7 +550,7 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
}
@Override
public void waitForLoadingFromGPSFixStoreToFinishRunning(RegattaLog fromRegattaLog) throws InterruptedException {
public void waitForLoadingToFinish() throws InterruptedException {
}
@Override
@@ -639,4 +635,20 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
@Override
public void updateStartAndEndOfTracking(boolean waitForGPSFixesToLoad) {
}
@Override
public <FixT extends SensorFix, TrackT extends SensorFixTrack<Competitor, FixT>> TrackT getSensorTrack(
Competitor competitor, String trackName) {
return null;
}
@Override
public Iterable<RegattaLog> getAttachedRegattaLogs() {
return Collections.emptySet();
}
@Override
public Iterable<RaceLog> getAttachedRaceLogs() {
return Collections.emptySet();
}
}
@@ -4,8 +4,6 @@ import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore;
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
@@ -36,26 +34,15 @@ public class CreateTrackedRace extends AbstractRaceOperation<DynamicTrackedRace>
*/
private transient final WindStore windStore;
/**
* If a {@link GPSFixStore} is provided to this command, it will be used for the construction of the tracked race.
* However, after de-serialization, the store will always be <code>null</code>, causing the use of an
* {@link EmptyGPSFixStore}.
*/
private transient final GPSFixStore gpsFixStore;
/**
* @param windStore
* if <code>null</code>, an {@link EmptyWindStore} will be used. Note that the {@link #windStore} field
* won't be serialized. A receiver of this operation will therefore always use an {@link EmptyWindStore}.
* @param gpsFixStore
* if <code>null</code>, an {@link EmptyGPSFixStore} will be used. Note that the {@link #gpsFixStore} field
* won't be serialized. A receiver of this operation will therefore always use an {@link EmptyWindStore}.
*/
public CreateTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore, GPSFixStore gpsFixStore,
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed) {
public CreateTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore, long delayToLiveInMillis,
long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed) {
super(raceIdentifier);
this.windStore = windStore;
this.gpsFixStore = gpsFixStore;
this.delayToLiveInMillis = delayToLiveInMillis;
this.millisecondsOverWhichToAverageWind = millisecondsOverWhichToAverageWind;
this.millisecondsOverWhichToAverageSpeed = millisecondsOverWhichToAverageSpeed;
@@ -75,10 +62,10 @@ public class CreateTrackedRace extends AbstractRaceOperation<DynamicTrackedRace>
@Override
public DynamicTrackedRace internalApplyTo(RacingEventService toState) {
return toState.createTrackedRace(getRaceIdentifier(), windStore == null ? EmptyWindStore.INSTANCE : windStore,
gpsFixStore == null ? EmptyGPSFixStore.INSTANCE : gpsFixStore,
delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
/* useMarkPassingCalculator */ false); // no separate mark passing calculations in replica;
return toState.createTrackedRace(getRaceIdentifier(), windStore == null ? EmptyWindStore.INSTANCE : windStore,
delayToLiveInMillis, millisecondsOverWhichToAverageWind,
millisecondsOverWhichToAverageSpeed, /* useMarkPassingCalculator */ false);
// no separate mark passing calculations in replica;
// Mark passings are computed on master and are replicated separately.
// See UpdateMarkPassings
}
@@ -31,8 +31,6 @@ import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.Wind;
import com.sap.sailing.domain.common.impl.MasterDataImportObjectCreationCountImpl;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.common.tracking.GPSFix;
import com.sap.sailing.domain.common.tracking.impl.CompactGPSFixImpl;
import com.sap.sailing.domain.common.tracking.impl.CompactGPSFixMovingImpl;
import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl;
@@ -49,7 +47,7 @@ import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory;
import com.sap.sailing.domain.persistence.MongoRegattaLogStoreFactory;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
import com.sap.sailing.domain.regattalike.HasRegattaLike;
import com.sap.sailing.domain.regattalike.IsRegattaLike;
@@ -64,6 +62,7 @@ import com.sap.sailing.server.RacingEventServiceOperation;
import com.sap.sailing.server.masterdata.DataImportLockWithProgress;
import com.sap.sailing.server.masterdata.DummyTrackedRace;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
import com.sap.sse.common.Timed;
import com.sap.sse.common.Util;
import com.sap.sse.concurrent.LockUtil;
@@ -402,21 +401,23 @@ public class ImportMasterDataOperation extends
private void importRaceLogTrackingGPSFixes(RacingEventService toState) {
Map<DeviceIdentifier, Set<GPSFix>> raceLogTrackingFixes = masterData.getRaceLogTrackingFixes();
Map<DeviceIdentifier, Set<Timed>> raceLogTrackingFixes = masterData.getRaceLogTrackingFixes();
if (raceLogTrackingFixes != null) {
GPSFixStore store = toState.getGPSFixStore();
for (Entry<DeviceIdentifier, Set<GPSFix>> entry : raceLogTrackingFixes.entrySet()) {
SensorFixStore store = toState.getSensorFixStore();
for (Entry<DeviceIdentifier, Set<Timed>> entry : raceLogTrackingFixes.entrySet()) {
DeviceIdentifier device = entry.getKey();
for (GPSFix fixToAdd : entry.getValue()) {
for (Timed fixToAdd : entry.getValue()) {
try {
if (fixToAdd instanceof CompactGPSFixMovingImpl) {
fixToAdd = new GPSFixMovingImpl(fixToAdd.getPosition(), fixToAdd.getTimePoint(),
CompactGPSFixMovingImpl gpsFix = (CompactGPSFixMovingImpl) fixToAdd;
fixToAdd = new GPSFixMovingImpl(gpsFix.getPosition(), fixToAdd.getTimePoint(),
((CompactGPSFixMovingImpl) fixToAdd).getSpeed());
} else if (fixToAdd instanceof CompactGPSFixImpl) {
fixToAdd = new GPSFixImpl(fixToAdd.getPosition(), fixToAdd.getTimePoint());
CompactGPSFixImpl gpsFix = (CompactGPSFixImpl) fixToAdd;
fixToAdd = new GPSFixImpl(gpsFix.getPosition(), fixToAdd.getTimePoint());
}
store.storeFix(device, fixToAdd);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
} catch (NoCorrespondingServiceRegisteredException e) {
logger.severe("Failed to store race log tracking fix while importing.");
e.printStackTrace();
}
@@ -0,0 +1,53 @@
package com.sap.sailing.server.operationaltransformation;
import java.io.Serializable;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.tracking.SensorFix;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class RecordCompetitorSensorFix extends AbstractRaceOperation<Void> {
private static final long serialVersionUID = -7092704633177037511L;
private final Serializable competitorID;
private final SensorFix fix;
private final String trackName;
public RecordCompetitorSensorFix(RegattaAndRaceIdentifier raceIdentifier, Competitor competitor, String trackName, SensorFix fix) {
super(raceIdentifier);
this.trackName = trackName;
this.competitorID = competitor.getId();
this.fix = fix;
}
/**
* Operations of this type can be run in parallel to other operations; subsequent operations do not have to wait
* for this operation's completion.
*/
@Override
public boolean requiresSynchronousExecution() {
return false;
}
@Override
public Void internalApplyTo(RacingEventService toState) throws Exception {
DynamicTrackedRace trackedRace = (DynamicTrackedRace) toState.getTrackedRace(getRaceIdentifier());
Competitor competitor = trackedRace.getRace().getCompetitorById(competitorID);
trackedRace.recordSensorFix(competitor, trackName, fix, /* onlyWhenInTrackingTimeInterval */ false); // record the fix in any case
return null;
}
@Override
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
// TODO Auto-generated method stub
return null;
}
}
@@ -0,0 +1,46 @@
package com.sap.sailing.server.operationaltransformation;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.tracking.DynamicSensorFixTrack;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class RecordCompetitorSensorFixTrack extends AbstractRaceOperation<Void> {
private static final long serialVersionUID = -7092704633177037511L;
private DynamicSensorFixTrack<Competitor, ?> track;
public RecordCompetitorSensorFixTrack(RegattaAndRaceIdentifier raceIdentifier, DynamicSensorFixTrack<Competitor, ?> track) {
super(raceIdentifier);
this.track = track;
}
/**
* Operations of this type can be run in parallel to other operations; subsequent operations do not have to wait
* for this operation's completion.
*/
@Override
public boolean requiresSynchronousExecution() {
return false;
}
@Override
public Void internalApplyTo(RacingEventService toState) throws Exception {
DynamicTrackedRace trackedRace = (DynamicTrackedRace) toState.getTrackedRace(getRaceIdentifier());
trackedRace.addSensorTrack(track.getTrackedItem(), track.getTrackName(), track);
return null;
}
@Override
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
// TODO Auto-generated method stub
return null;
}
}
@@ -3,10 +3,11 @@ package com.sap.sailing.server.operationaltransformation;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.TrackedRaceStatus;
import com.sap.sailing.domain.tracking.TrackingDataLoader;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class UpdateTrackedRaceStatus extends AbstractRaceOperation<Void> {
public class UpdateTrackedRaceStatus extends AbstractRaceOperation<Void> implements TrackingDataLoader {
private static final long serialVersionUID = 5847067037829132465L;
private final TrackedRaceStatus newStatus;
@@ -18,7 +19,7 @@ public class UpdateTrackedRaceStatus extends AbstractRaceOperation<Void> {
@Override
public Void internalApplyTo(RacingEventService toState) throws Exception {
DynamicTrackedRace trackedRace = (DynamicTrackedRace) toState.getTrackedRace(getRaceIdentifier());
trackedRace.setStatus(newStatus);
trackedRace.onStatusChanged(this, newStatus);
return null;
}
@@ -189,12 +189,12 @@ public class SimulationServiceImpl implements SimulationService {
}
@Override
public void startOfTrackingChanged(TimePoint startOfTracking) {
public void startOfTrackingChanged(TimePoint oldStartOfTracking, TimePoint newStartOfTracking) {
// irrelevant for simulation
}
@Override
public void endOfTrackingChanged(TimePoint endOfTracking) {
public void endOfTrackingChanged(TimePoint oldEndOfTracking, TimePoint newEndOfTracking) {
// irrelevant for simulation
}