Merge commit '066074eadef60849f26de3536857cce3741f38ed' into highcharts_version_update

This commit is contained in:
fmittag committed 2012-05-23 15:22:25 +02:00
commit e60640108d
51 files changed
+444 -141

No files matched your search

@@ -290,8 +290,9 @@ public class EndToEndListeningStoreAndFowardTest {
private void setUpUsingScript(String[] racesToTrack, String... scriptNames) throws Exception {
for (String raceToTrack : racesToTrack) {
RacesHandle raceHandle = racingEventService.addSwissTimingRace(raceToTrack, "localhost", CLIENT_PORT, /* canSendRequests */
false, emptyWindStore, -1);
RacesHandle raceHandle = racingEventService.addSwissTimingRace(/* regattaToAddTo */ null /* use a default regatta */,
raceToTrack, "localhost", /* canSendRequests */
CLIENT_PORT, false, emptyWindStore, -1);
raceHandles.add(raceHandle);
if (connector == null) {
connector = racingEventService.getSwissTimingFactory().getOrCreateSailMasterConnector("localhost",
@@ -20,7 +20,7 @@ import difflib.PatchFailedException;
public interface DomainFactory {
final static DomainFactory INSTANCE = new DomainFactoryImpl(com.sap.sailing.domain.base.DomainFactory.INSTANCE);
Regatta getOrCreateEvent(String raceID);
Regatta getOrCreateRegatta(String raceID);
Nationality getOrCreateNationality(String nationalityName);
@@ -4,8 +4,10 @@ import java.io.IOException;
import java.net.UnknownHostException;
import java.text.ParseException;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.swisstimingadapter.impl.SwissTimingFactoryImpl;
import com.sap.sailing.domain.tracking.RaceTracker;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
import com.sap.sailing.domain.tracking.WindStore;
@@ -51,7 +53,13 @@ public interface SwissTimingFactory {
SwissTimingRaceTracker createRaceTracker(String raceID, String hostname, int port, boolean canSendRequests, WindStore windStore, RaceSpecificMessageLoader messageLoader, DomainFactory domainFactory, TrackedRegattaRegistry trackedRegattaRegistry) throws InterruptedException, UnknownHostException, IOException, ParseException;
RaceTracker createRaceTracker(Regatta regatta, String raceID, String hostname, int port, boolean canSendRequests,
WindStore windStore, RaceSpecificMessageLoader messageLoader, DomainFactory domainFactory,
TrackedRegattaRegistry trackedRegattaRegistry) throws UnknownHostException, InterruptedException,
IOException, ParseException;
Race createRace(String raceId, String description, TimePoint startTime);
SailMasterMessage createMessage(String message, Long sequenceNumber);
}
@@ -7,24 +7,25 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.Person;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util;
@@ -54,6 +55,7 @@ import difflib.PatchFailedException;
*
*/
public class DomainFactoryImpl implements DomainFactory {
private final static Logger logger = Logger.getLogger(DomainFactoryImpl.class.getName());
private final Map<String, Regatta> raceIDToEventCache;
private final Map<Iterable<String>, ControlPoint> controlPointCache;
private final Map<String, BoatClass> olympicClassesByID;
@@ -89,10 +91,11 @@ public class DomainFactoryImpl implements DomainFactory {
}
@Override
public Regatta getOrCreateEvent(String raceID) {
public Regatta getOrCreateRegatta(String raceID) {
Regatta result = raceIDToEventCache.get(raceID);
if (result == null) {
result = new RegattaImpl(raceID, null);
logger.info("Created regatta "+result.getName()+" ("+result.hashCode()+")");
raceIDToEventCache.put(raceID, result);
}
return result;
@@ -124,6 +127,7 @@ public class DomainFactoryImpl implements DomainFactory {
com.sap.sailing.domain.base.Course domainCourse = createCourse(race.getDescription(), course);
BoatClass boatClass = getOrCreateBoatClassFromRaceID(race.getRaceID());
Iterable<Competitor> competitors = createCompetitorList(startList, boatClass);
logger.info("Creating RaceDefinitionImpl for race "+race.getRaceID());
RaceDefinition result = new RaceDefinitionImpl(race.getRaceID(), domainCourse,
boatClass, competitors);
regatta.addRace(result);
@@ -228,7 +232,7 @@ public class DomainFactoryImpl implements DomainFactory {
@Override
public void removeRace(String raceID) {
Regatta regatta = getOrCreateEvent(raceID);
Regatta regatta = getOrCreateRegatta(raceID);
Set<RaceDefinition> toRemove = new HashSet<RaceDefinition>();
if (regatta != null) {
for (RaceDefinition race : regatta.getAllRaces()) {
@@ -6,6 +6,7 @@ import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
@@ -18,6 +19,7 @@ import com.sap.sailing.domain.swisstimingadapter.SwissTimingConfiguration;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingMessageParser;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingRaceTracker;
import com.sap.sailing.domain.tracking.RaceTracker;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
import com.sap.sailing.domain.tracking.WindStore;
@@ -83,6 +85,15 @@ public class SwissTimingFactoryImpl implements SwissTimingFactory {
trackedRegattaRegistry, canSendRequests);
}
@Override
public RaceTracker createRaceTracker(Regatta regatta, String raceID, String hostname, int port,
boolean canSendRequests, WindStore windStore, RaceSpecificMessageLoader messageLoader,
DomainFactory domainFactory, TrackedRegattaRegistry trackedRegattaRegistry) throws UnknownHostException,
InterruptedException, IOException, ParseException {
return new SwissTimingRaceTrackerImpl(regatta, raceID, hostname, port, windStore, domainFactory, this,
messageLoader, trackedRegattaRegistry, canSendRequests);
}
@Override
public SailMasterTransceiver createSailMasterTransceiver() {
return new SailMasterTransceiverImpl();
@@ -64,6 +64,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl implemen
private Course course;
private StartList startList;
private DynamicTrackedRace trackedRace;
private final DynamicTrackedRegatta trackedRegatta;
private boolean loggedIgnore;
@@ -71,7 +72,16 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl implemen
DomainFactory domainFactory, SwissTimingFactory factory, RaceSpecificMessageLoader messageLoader,
TrackedRegattaRegistry trackedRegattaRegistry, boolean canSendRequests) throws InterruptedException,
UnknownHostException, IOException, ParseException {
this(domainFactory.getOrCreateRegatta(raceID), raceID, hostname, port, windStore, domainFactory, factory,
messageLoader, trackedRegattaRegistry, canSendRequests);
}
protected SwissTimingRaceTrackerImpl(Regatta regatta, String raceID, String hostname, int port, WindStore windStore,
DomainFactory domainFactory, SwissTimingFactory factory, RaceSpecificMessageLoader messageLoader,
TrackedRegattaRegistry trackedRegattaRegistry, boolean canSendRequests) throws InterruptedException,
UnknownHostException, IOException, ParseException {
super();
this.regatta = regatta;
this.connector = factory.getOrCreateSailMasterConnector(hostname, port, messageLoader, canSendRequests);
this.domainFactory = domainFactory;
this.raceID = raceID;
@@ -79,11 +89,15 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl implemen
this.windStore = windStore;
this.id = createID(raceID, hostname, port);
connector.addSailMasterListener(raceID, this);
regatta = domainFactory.getOrCreateEvent(raceID);
setTrackedRegatta(trackedRegattaRegistry.getOrCreateTrackedRegatta(regatta));
trackedRegatta = trackedRegattaRegistry.getOrCreateTrackedRegatta(regatta);
connector.trackRace(raceID);
}
@Override
public DynamicTrackedRegatta getTrackedRegatta() {
return trackedRegatta;
}
static Triple<String, String, Integer> createID(String raceID, String hostname, int port) {
return new Triple<String, String, Integer>(raceID, hostname, port);
}
@@ -1,5 +1,6 @@
package com.sap.sailing.domain.swisstimingadapter.impl;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
import com.sap.sailing.domain.swisstimingadapter.RaceSpecificMessageLoader;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
@@ -38,6 +39,13 @@ public class SwissTimingTrackingConnectivityParameters implements RaceTrackingCo
domainFactory, trackedRegattaRegistry);
}
@Override
public RaceTracker createRaceTracker(Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry)
throws Exception {
return swissTimingFactory.createRaceTracker(regatta, raceID, hostname, port, canSendRequests, windStore, messageLoader,
domainFactory, trackedRegattaRegistry);
}
@Override
public Object getTrackerID() {
return SwissTimingRaceTrackerImpl.createID(raceID, hostname, port);
@@ -67,7 +67,7 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest {
public void setUp() throws MalformedURLException, IOException, InterruptedException, URISyntaxException {
super.setUp();
domainFactory = new DomainFactoryImpl(new com.sap.sailing.domain.base.impl.DomainFactoryImpl());
domainRegatta = domainFactory.getOrCreateEvent(getTracTracEvent());
domainRegatta = domainFactory.getOrCreateRegatta(getTracTracEvent());
trackedRegatta = new DynamicTrackedRegattaImpl(domainRegatta);
ArrayList<Receiver> receivers = new ArrayList<Receiver>();
receivers.add(new RaceCourseReceiver(domainFactory, trackedRegatta, getTracTracEvent(), /* millisecondsOverWhichToAverageWind */
@@ -131,7 +131,7 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest {
if (domainFactory == null) {
domainFactory = new DomainFactoryImpl(new com.sap.sailing.domain.base.impl.DomainFactoryImpl());
}
domainEvent = domainFactory.getOrCreateEvent(getTracTracEvent());
domainEvent = domainFactory.getOrCreateRegatta(getTracTracEvent());
trackedRegatta = new DynamicTrackedRegattaImpl(domainEvent);
}
@@ -93,7 +93,7 @@ public class ReceiveMarkPassingDataTest extends AbstractTracTracLiveTest {
List<Receiver> receivers = new ArrayList<Receiver>();
receivers.add(receiver);
for (Receiver r : DomainFactory.INSTANCE.getUpdateReceivers(
new DynamicTrackedRegattaImpl(DomainFactory.INSTANCE.getOrCreateEvent(getTracTracEvent())),
new DynamicTrackedRegattaImpl(DomainFactory.INSTANCE.getOrCreateRegatta(getTracTracEvent())),
getTracTracEvent(), EmptyWindStore.INSTANCE, /* startOfTracking */ null, /* endOfTracking */ null,
new DynamicRaceDefinitionSet() {
@Override
@@ -65,7 +65,7 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest {
}
};
List<TypeController> listeners = new ArrayList<TypeController>();
Regatta regatta = domainFactory.getOrCreateEvent(getTracTracEvent());
Regatta regatta = domainFactory.getOrCreateRegatta(getTracTracEvent());
DynamicTrackedRegatta trackedRegatta = new DynamicTrackedRegattaImpl(regatta);
trackedRegatta.addRaceListener(new RaceListener() {
@Override
@@ -16,6 +16,7 @@ import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.Person;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.TimePoint;
@@ -24,6 +25,7 @@ import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceTracker;
import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
@@ -85,7 +87,7 @@ public interface DomainFactory {
* an equal name with a boat class with an equal name as the <code>event</code>'s
* boat class exists yet.
*/
com.sap.sailing.domain.base.Regatta getOrCreateEvent(Event event);
com.sap.sailing.domain.base.Regatta getOrCreateRegatta(Event event);
/**
* Creates a race tracked for the specified URL/URIs and starts receiving all available existing and future push
@@ -121,6 +123,14 @@ public interface DomainFactory {
TimePoint endOfTracking, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry)
throws MalformedURLException, FileNotFoundException, URISyntaxException;
/**
* Same as {@link #createRaceTracker(URL, URI, URI, TimePoint, TimePoint, WindStore, TrackedRegattaRegistry)}, only that
* a predefined {@link Regatta} is used to hold the resulting races.
*/
RaceTracker createRaceTracker(Regatta regatta, URL paramURL, URI liveURI, URI storedURI, TimePoint startOfTracking,
TimePoint endOfTracking, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry)
throws MalformedURLException, FileNotFoundException, URISyntaxException;
BoatClass getOrCreateBoatClass(CompetitorClass competitorClass);
/**
@@ -222,11 +232,11 @@ public interface DomainFactory {
* Removes all knowledge about <code>tractracRace</code> which includes removing it from the race cache, from the
* {@link com.sap.sailing.domain.base.Regatta} and, if a {@link TrackedRace} for the corresponding
* {@link RaceDefinition} exists, from the {@link TrackedRegatta}. If removing the race from the event, the event is
* removed from the event cache such that {@link #getOrCreateEvent(Event)} will have to create a new one. Similarly,
* removed from the event cache such that {@link #getOrCreateRegatta(Event)} will have to create a new one. Similarly,
* if the {@link TrackedRace} that was removed from the {@link TrackedRegatta} was the last one, the
* {@link TrackedRegatta} is removed such that {@link #getOrCreateTrackedRegatta(com.sap.sailing.domain.base.Regatta)}
* will have to create a new one.
*/
void removeRace(Event tractracEvent, Race tractracRace, TrackedRegattaRegistry trackedRegattaRegistry);
}
@@ -140,7 +140,7 @@ public abstract class AbstractReceiverWithQueue<A, B, C> implements Runnable, Re
protected DynamicTrackedRace getTrackedRace(Race race) {
DynamicTrackedRace result = null;
RaceDefinition raceDefinition = getDomainFactory().getAndWaitForRaceDefinition(race);
com.sap.sailing.domain.base.Regatta domainEvent = getDomainFactory().getOrCreateEvent(getTracTracEvent());
com.sap.sailing.domain.base.Regatta domainEvent = getDomainFactory().getOrCreateRegatta(getTracTracEvent());
if (domainEvent.getRaceByName(raceDefinition.getName()) != null) {
result = trackedRegatta.getTrackedRace(raceDefinition);
}
@@ -47,6 +47,7 @@ import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceTracker;
import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
@@ -94,7 +95,7 @@ public class DomainFactoryImpl implements DomainFactory {
* class needs to be determined for an regatta. Synchronization for additions / removals is tied to the
* synchronization for {@link #regattaCache}.
*/
private final WeakIdentityHashMap<com.tractrac.clientmodule.Event, Regatta> weakEventCache = new WeakIdentityHashMap<>();
private final WeakIdentityHashMap<com.tractrac.clientmodule.Event, Regatta> weakRegattaCache = new WeakIdentityHashMap<>();
private final Map<Race, RaceDefinition> raceCache = new HashMap<Race, RaceDefinition>();
@@ -243,7 +244,7 @@ public class DomainFactoryImpl implements DomainFactory {
}
@Override
public Regatta getOrCreateEvent(com.tractrac.clientmodule.Event event) {
public Regatta getOrCreateRegatta(com.tractrac.clientmodule.Event event) {
synchronized (regattaCache) {
// FIXME Dialog with Lasse by Skype on 2011-06-17:
// [6:20:04 PM] Axel Uhl: Lasse, can Event.getCompetitorClassList() ever produce more than one result?
@@ -258,7 +259,7 @@ public class DomainFactoryImpl implements DomainFactory {
// try a quick look-up in the weak cache using the TracTrac event as key; only if that delivers no result,
// compute the dominant boat class which requires a lot more effort
Regatta result = weakEventCache.get(event);
Regatta result = weakRegattaCache.get(event);
if (result == null) {
Collection<CompetitorClass> competitorClassList = new ArrayList<CompetitorClass>();
for (com.tractrac.clientmodule.Competitor c : event.getCompetitorList()) {
@@ -271,7 +272,8 @@ public class DomainFactoryImpl implements DomainFactory {
if (result == null) {
result = new RegattaImpl(event.getName(), boatClass);
regattaCache.put(key, result);
weakEventCache.put(event, result);
weakRegattaCache.put(event, result);
logger.info("Created regatta "+result.getName()+" ("+result.hashCode()+") because none found for key "+key);
}
}
return result;
@@ -326,6 +328,7 @@ public class DomainFactoryImpl implements DomainFactory {
raceDefinition = getExistingRaceDefinitionForRace(tractracRace);
if (raceDefinition != null) { // otherwise, this domain factory doesn't seem to know about the race
raceCache.remove(tractracRace);
logger.info("Removed race "+raceDefinition.getName()+" from TracTrac DomainFactoryImpl");
}
}
if (raceDefinition != null) {
@@ -346,8 +349,9 @@ public class DomainFactoryImpl implements DomainFactory {
int oldSize = Util.size(regatta.getAllRaces());
regatta.removeRace(raceDefinition);
if (oldSize > 0 && Util.size(regatta.getAllRaces()) == 0) {
logger.info("Removing regatta "+regatta.getName()+" ("+regatta.hashCode()+") from TracTrac DomainFactoryImpl");
regattaCache.remove(key);
weakEventCache.remove(tractracEvent);
weakRegattaCache.remove(tractracEvent);
}
TrackedRegatta trackedRegatta = trackedRegattaRegistry.getTrackedRegatta(regatta);
if (trackedRegatta != null) {
@@ -371,6 +375,7 @@ public class DomainFactoryImpl implements DomainFactory {
RaceDefinition raceDefinition = raceCache.get(race);
if (raceDefinition == null) {
Pair<List<Competitor>, BoatClass> competitorsAndDominantBoatClass = getCompetitorsAndDominantBoatClass(race);
logger.info("Creating RaceDefinitionImpl for race "+race.getName());
raceDefinition = new RaceDefinitionImpl(race.getName(), course, competitorsAndDominantBoatClass.getB(),
competitorsAndDominantBoatClass.getA());
// add to domain Event only if boat class matches
@@ -469,6 +474,14 @@ public class DomainFactoryImpl implements DomainFactory {
windStore, trackedRegattaRegistry);
}
@Override
public RaceTracker createRaceTracker(Regatta regatta, URL paramURL, URI liveURI, URI storedURI,
TimePoint startOfTracking, TimePoint endOfTracking, WindStore windStore,
TrackedRegattaRegistry trackedRegattaRegistry) throws MalformedURLException, FileNotFoundException, URISyntaxException {
return new TracTracRaceTrackerImpl(regatta, this, paramURL, liveURI, storedURI, startOfTracking, endOfTracking,
windStore, trackedRegattaRegistry);
}
@Override
public JSONService parseJSONURL(URL jsonURL) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
return new JSONServiceImpl(jsonURL);
@@ -26,7 +26,7 @@ public class RaceHandleImpl implements RacesHandle {
@Override
public com.sap.sailing.domain.base.Regatta getRegatta() {
return domainFactory.getOrCreateEvent(tractracEvent);
return trackedRegatta.getRegatta();
}
@Override
@@ -6,6 +6,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.tracking.RaceTracker;
@@ -43,6 +44,14 @@ public class RaceTrackingConnectivityParametersImpl implements RaceTrackingConne
return tracker;
}
@Override
public RaceTracker createRaceTracker(Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry)
throws Exception {
RaceTracker tracker = domainFactory.createRaceTracker(regatta, paramURL, liveURI, storedURI, startOfTracking,
endOfTracking, windStore, trackedRegattaRegistry);
return tracker;
}
@Override
public Util.Triple<URL, URI, URI> getTrackerID() {
return TracTracRaceTrackerImpl.createID(paramURL, liveURI, storedURI);
@@ -19,6 +19,7 @@ import com.maptrack.client.io.TypeController;
import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.DegreePosition;
@@ -27,11 +28,12 @@ import com.sap.sailing.domain.tracking.AbstractRaceTrackerImpl;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.WindStore;
import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
@@ -56,14 +58,15 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private final Event tractracEvent;
private final com.sap.sailing.domain.base.Regatta domainEvent;
private final com.sap.sailing.domain.base.Regatta regatta;
private final Thread ioThread;
private final DataController controller;
private final Set<Receiver> receivers;
private final DomainFactory domainFactory;
private final WindStore windStore;
private final Set<RaceDefinition> races;
private final DynamicTrackedRegatta trackedRegatta;
/**
* paramURL, liveURI and storedURI for TracTrac connection
*/
@@ -107,13 +110,48 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
TimePoint startOfTracking, TimePoint endOfTracking, WindStore windStore,
TrackedRegattaRegistry trackedRegattaRegistry) throws URISyntaxException, MalformedURLException,
FileNotFoundException {
this(KeyValue.setup(paramURL), domainFactory, paramURL, liveURI, storedURI, startOfTracking, endOfTracking, windStore,
trackedRegattaRegistry);
}
private TracTracRaceTrackerImpl(Event tractracEvent, DomainFactory domainFactory, URL paramURL, URI liveURI, URI storedURI,
TimePoint startOfTracking, TimePoint endOfTracking, WindStore windStore,
TrackedRegattaRegistry trackedRegattaRegistry) throws URISyntaxException, MalformedURLException,
FileNotFoundException {
this(tractracEvent, null, domainFactory, paramURL, liveURI, storedURI,
startOfTracking, endOfTracking, windStore, trackedRegattaRegistry);
}
/**
* Use this constructor if the {@link Regatta} in which to arrange the {@link RaceDefinition}s created by this
* tracker is already known up-front, particularly if it has a specific configuration to use. Other constructors
* may create a default {@link Regatta} with only a single default {@link Series} and {@link Fleet} which may not
* always be what you want.
*/
protected TracTracRaceTrackerImpl(Regatta regatta, DomainFactory domainFactory, URL paramURL, URI liveURI, URI storedURI,
TimePoint startOfTracking, TimePoint endOfTracking, WindStore windStore,
TrackedRegattaRegistry trackedRegattaRegistry) throws URISyntaxException, MalformedURLException,
FileNotFoundException {
this(KeyValue.setup(paramURL), regatta, domainFactory, paramURL, liveURI, storedURI, startOfTracking,
endOfTracking, windStore, trackedRegattaRegistry);
}
/**
*
* @param regatta if <code>null</code>, then <code>domainFactory.getOrCreateRegatta(tractracEvent)</code> will be used to
* obtain a default regatta
*/
private TracTracRaceTrackerImpl(Event tractracEvent, Regatta regatta, DomainFactory domainFactory, URL paramURL, URI liveURI, URI storedURI,
TimePoint startOfTracking, TimePoint endOfTracking, WindStore windStore,
TrackedRegattaRegistry trackedRegattaRegistry) throws URISyntaxException, MalformedURLException,
FileNotFoundException {
super();
this.tractracEvent = tractracEvent;
urls = createID(paramURL, liveURI, storedURI);
this.races = new HashSet<RaceDefinition>();
this.windStore = windStore;
this.domainFactory = domainFactory;
// Read event data from configuration file
tractracEvent = KeyValue.setup(paramURL);
controlPointPositionPoller = scheduleControlPointPositionPoller(paramURL);
// can happen that TracTrac event is null (occurs when there is no Internet connection)
// so lets raise some meaningful exception
@@ -126,13 +164,13 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
// Start live and stored data streams
ioThread = new Thread(controller, "I/O for event "+tractracEvent.getName()+", race URL "+paramURL);
for (Race tractracRace : tractracEvent.getRaceList()) {
// removeRace may detach the domain event from the domain factory if that
// removeRace may detach the domain regatta from the domain factory if that
// removed the last race; therefore, it's important to getOrCreate the
// domainEvent *after* calling removeRace
// domain regatta *after* calling removeRace
domainFactory.removeRace(tractracEvent, tractracRace, trackedRegattaRegistry);
}
domainEvent = domainFactory.getOrCreateEvent(tractracEvent);
setTrackedRegatta(trackedRegattaRegistry.getOrCreateTrackedRegatta(domainEvent));
this.regatta = regatta == null ? domainFactory.getOrCreateRegatta(tractracEvent) : regatta;
trackedRegatta = trackedRegattaRegistry.getOrCreateTrackedRegatta(this.regatta);
receivers = new HashSet<Receiver>();
Set<TypeController> typeControllers = new HashSet<TypeController>();
for (Receiver receiver : domainFactory.getUpdateReceivers(getTrackedRegatta(), tractracEvent, startOfTracking,
@@ -145,6 +183,11 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
addListenersForStoredDataAndStartController(typeControllers);
}
@Override
public DynamicTrackedRegatta getTrackedRegatta() {
return trackedRegatta;
}
static Triple<URL, URI, URI> createID(URL paramURL, URI liveURI, URI storedURI) {
return new Triple<URL, URI, URI>(paramURL, liveURI, storedURI);
}
@@ -219,7 +262,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
@Override
public com.sap.sailing.domain.base.Regatta getRegatta() {
return domainEvent;
return regatta;
}
/**
@@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
@@ -18,6 +19,7 @@ import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.impl.NamedImpl;
public class RegattaImpl extends NamedImpl implements Regatta {
private static final Logger logger = Logger.getLogger(RegattaImpl.class.getName());
private static final long serialVersionUID = 6509564189552478869L;
private final Set<RaceDefinition> races;
private final BoatClass boatClass;
@@ -85,6 +87,7 @@ public class RegattaImpl extends NamedImpl implements Regatta {
@Override
public void addRace(RaceDefinition race) {
logger.info("Adding race "+race.getName()+" to regatta "+getName()+" ("+hashCode()+")");
if (getBoatClass() != null && race.getBoatClass() != getBoatClass()) {
throw new IllegalArgumentException("Boat class "+race.getBoatClass()+" doesn't match regatta's boat class "+getBoatClass());
}
@@ -101,6 +104,7 @@ public class RegattaImpl extends NamedImpl implements Regatta {
@Override
public void removeRace(RaceDefinition race) {
synchronized (races) {
logger.info("Removing race "+race.getName()+" from regatta "+getName()+" ("+hashCode()+")");
races.remove(race);
}
synchronized (regattaListeners) {
@@ -20,17 +20,6 @@ public abstract class AbstractRaceTrackerImpl implements RaceTracker {
return result;
}
private DynamicTrackedRegatta trackedRegatta;
public AbstractRaceTrackerImpl() {
}
@Override
public DynamicTrackedRegatta getTrackedRegatta() {
return trackedRegatta;
}
protected void setTrackedRegatta(DynamicTrackedRegatta trackedRegatta) {
this.trackedRegatta = trackedRegatta;
}
public abstract DynamicTrackedRegatta getTrackedRegatta();
}
@@ -1,5 +1,9 @@
package com.sap.sailing.domain.tracking;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
@@ -18,6 +22,14 @@ public interface RaceTrackingConnectivityParameters {
*/
RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry) throws Exception;
/**
* Starts a {@link RaceTracker}, associating the resulting races with the {@link Regatta} passed as argument
* instead of using the tracker's domain factory to obtain a default {@link Regatta} object for the tracking
* parameters. This is particularly useful if a predefined regatta with {@link Series} and {@link Fleet}s
* is to be used.
*/
RaceTracker createRaceTracker(Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry) throws Exception;
/**
* Deliver an ID object equal to that of the {@link RaceTracker#getID()} delivered by the {@link RaceTracker}
* that will be created from these parameters by calling {@link #createRaceTracker(TrackedRegattaRegistry)}.
@@ -60,6 +60,8 @@ public class TrackedRegattaImpl implements TrackedRegatta {
@Override
public void addTrackedRace(TrackedRace trackedRace) {
synchronized (trackedRaces) {
logger.info("adding tracked race for "+trackedRace.getRace()+" to tracked regatta "+getRegatta().getName()+
" with regatta hash code "+getRegatta().hashCode());
trackedRaces.put(trackedRace.getRace(), trackedRace);
Collection<TrackedRace> coll = trackedRacesByBoatClass.get(trackedRace.getRace().getBoatClass());
if (coll == null) {
@@ -46,6 +46,7 @@
<property name="osgi.noShutdown" value="true" />
<property name="replication.brokerURL" value="tcp://localhost:61616" />
<property name="replication.persistenceDir" value="." />
<property name="replication.useJMX" value="false" />
</configurations>
</product>
-7
View File
@@ -77,13 +77,6 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al
version="0.0.0"
unpack="false"/>
<plugin
id="com.tractrac.resultapi"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.mongodb.driver"
download-size="0"
@@ -80,8 +80,11 @@ public class GwtTestCaseColumnToggling extends GWTTestCase {
}
private void trackRace(){
service.track(rrDao, tractracTunnel ? "tcp://"+tractracTunnelHost+":"+TracTracConnectionConstants.PORT_TUNNEL_LIVE : "tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_LIVE,
tractracTunnel ? "tcp://"+tractracTunnelHost+":"+TracTracConnectionConstants.PORT_TUNNEL_STORED : "tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_STORED, false, false, new AsyncCallback<Void>() {
service.trackWithTracTrac(/* regattaToAddTo */null, rrDao, tractracTunnel ? "tcp://" + tractracTunnelHost + ":"
+ TracTracConnectionConstants.PORT_TUNNEL_LIVE : "tcp://" + TracTracConnectionConstants.HOST_NAME + ":"
+ TracTracConnectionConstants.PORT_LIVE, tractracTunnel ? "tcp://" + tractracTunnelHost + ":"
+ TracTracConnectionConstants.PORT_TUNNEL_STORED : "tcp://" + TracTracConnectionConstants.HOST_NAME
+ ":" + TracTracConnectionConstants.PORT_STORED, false, false, new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
@@ -128,6 +128,16 @@
width: 12px;
}
.gwt-SplitLayoutPanel-HDragger {
background: #e7e7e7 url(images/thumb_vertical.png) center center no-repeat;
cursor: col-resize;
}
.gwt-SplitLayoutPanel-VDragger {
background: #e7e7e7 url(images/thumb_horz.png) center center no-repeat;
cursor: row-resize;
}
.gwt-ToggleButton-up-hovering, .gwt-ToggleButton-down-hovering {
background: url(images/btn-cta-orangeleft-down.png) center top repeat-x;
color: #fff;
Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

@@ -342,7 +342,8 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
int port = portIntegerbox.getValue();
for (final SwissTimingRaceRecordDTO rr : raceList.getList()) {
if (raceTable.getSelectionModel().isSelected(rr)) {
sailingService.trackWithSwissTiming(rr, hostname, port, /* canSendRequests */false,
sailingService.trackWithSwissTiming(/* regattaToAddTo */ null, // TODO allow user to select a pre-defined regatta
rr, hostname, port, /* canSendRequests */false,
trackWind, correctWindByDeclination, new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
@@ -455,7 +455,8 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
String storedURI = storedURIBox.getValue();
for (final TracTracRaceRecordDTO rr : raceList.getList()) {
if (raceTable.getSelectionModel().isSelected(rr)) {
sailingService.track(rr, liveURI, storedURI, trackWind, correctWindByDeclination, new AsyncCallback<Void>() {
sailingService.trackWithTracTrac(/* regattaToAddTo */ null, // TODO allow user to optionally select a pre-defined regatta
rr, liveURI, storedURI, trackWind, correctWindByDeclination, new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error trying to register race " + rr.name + " for tracking: "
@@ -113,7 +113,7 @@ public class TrackedRacesListComposite extends FormPanel implements RegattaDispl
public TrackedRacesListComposite(final SailingServiceAsync sailingService, final ErrorReporter errorReporter,
final RegattaRefresher regattaRefresher, RaceSelectionProvider raceSelectionProvider,
StringMessages stringConstants, boolean hasMultiSelection) {
StringMessages stringMessages, boolean hasMultiSelection) {
if (regattaRefresher == null) {
throw new IllegalArgumentException("regattaRefresher must not be null");
}
@@ -130,7 +130,7 @@ public class TrackedRacesListComposite extends FormPanel implements RegattaDispl
setWidget(panel);
HorizontalPanel filterPanel = new HorizontalPanel();
panel.add(filterPanel);
Label lblFilterEvents = new Label(stringConstants.filterRacesByName() + ":");
Label lblFilterEvents = new Label(stringMessages.filterRacesByName() + ":");
lblFilterEvents.setWordWrap(false);
filterPanel.setSpacing(5);
filterPanel.add(lblFilterEvents);
@@ -144,7 +144,7 @@ public class TrackedRacesListComposite extends FormPanel implements RegattaDispl
});
filterPanel.add(filterRacesTextbox);
noTrackedRacesLabel = new Label(stringConstants.noRacesYet());
noTrackedRacesLabel = new Label(stringMessages.noRacesYet());
noTrackedRacesLabel.setWordWrap(false);
panel.add(noTrackedRacesLabel);
@@ -181,16 +181,16 @@ public class TrackedRacesListComposite extends FormPanel implements RegattaDispl
}
});
TextColumn<RaceDTO> deprecatedRegattaNameColumn = new TextColumn<RaceDTO>() {
TextColumn<RaceDTO> boatClassNameColumn = new TextColumn<RaceDTO>() {
@Override
public String getValue(RaceDTO raceDTO) {
final BoatClassDTO boatClass = raceDTO.getRegatta().boatClass;
return boatClass == null ? "" : boatClass.name;
}
};
deprecatedRegattaNameColumn.setSortable(true);
boatClassNameColumn.setSortable(true);
columnSortHandler.setComparator(deprecatedRegattaNameColumn, new Comparator<RaceDTO>() {
columnSortHandler.setComparator(boatClassNameColumn, new Comparator<RaceDTO>() {
@Override
public int compare(RaceDTO t1, RaceDTO t2) {
RegattaDTO regattaOne = t1.getRegatta();
@@ -290,11 +290,11 @@ public class TrackedRacesListComposite extends FormPanel implements RegattaDispl
}
};
raceTable.addColumn(regattaNameColumn, stringConstants.event());
raceTable.addColumn(deprecatedRegattaNameColumn, stringConstants.regatta());
raceTable.addColumn(raceNameColumn, stringConstants.race());
raceTable.addColumn(raceStartColumn, stringConstants.startTime());
raceTable.addColumn(raceTrackedColumn, stringConstants.tracked());
raceTable.addColumn(regattaNameColumn, stringMessages.regatta());
raceTable.addColumn(boatClassNameColumn, stringMessages.boatClass());
raceTable.addColumn(raceNameColumn, stringMessages.race());
raceTable.addColumn(raceStartColumn, stringMessages.startTime());
raceTable.addColumn(raceTrackedColumn, stringMessages.tracked());
raceTable.setWidth("300px");
raceTable.setSelectionModel(selectionModel);
raceTable.setVisible(false);
@@ -326,7 +326,7 @@ public class TrackedRacesListComposite extends FormPanel implements RegattaDispl
HorizontalPanel trackedRacesButtonPanel = new HorizontalPanel();
trackedRacesButtonPanel.setSpacing(10);
panel.add(trackedRacesButtonPanel);
btnRemoveRace = new Button(stringConstants.remove());
btnRemoveRace = new Button(stringMessages.remove());
btnRemoveRace.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
@@ -337,7 +337,7 @@ public class TrackedRacesListComposite extends FormPanel implements RegattaDispl
});
btnRemoveRace.setEnabled(false);
trackedRacesButtonPanel.add(btnRemoveRace);
btnUntrack = new Button(stringConstants.stopTracking());
btnUntrack = new Button(stringMessages.stopTracking());
btnUntrack.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent click) {
@@ -351,7 +351,7 @@ public class TrackedRacesListComposite extends FormPanel implements RegattaDispl
btnUntrack.setEnabled(false);
trackedRacesButtonPanel.add(btnUntrack);
btnRefresh = new Button(stringConstants.refresh());
btnRefresh = new Button(stringMessages.refresh());
btnRefresh.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
@@ -48,8 +48,11 @@ public interface SailingService extends RemoteService {
Pair<String, List<TracTracRaceRecordDTO>> listTracTracRacesInEvent(String eventJsonURL) throws Exception;
void track(TracTracRaceRecordDTO rr, String liveURI, String storedURI, boolean trackWind, boolean correctWindByDeclination) throws Exception;
void trackWithTracTrac(RegattaIdentifier regattaToAddTo, TracTracRaceRecordDTO rr, String liveURI, String storedURI, boolean trackWind, boolean correctWindByDeclination) throws Exception;
void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, SwissTimingRaceRecordDTO rr, String hostname, int port,
boolean canSendRequests, boolean trackWind, boolean correctWindByDeclination) throws Exception;
void storeTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI) throws Exception;
void stopTrackingEvent(RegattaIdentifier eventIdentifier) throws Exception;
@@ -144,9 +147,6 @@ public interface SailingService extends RemoteService {
void storeSwissTimingConfiguration(String configName, String hostname, int port, boolean canSendRequests);
void trackWithSwissTiming(SwissTimingRaceRecordDTO rr, String hostname, int port, boolean canSendRequests,
boolean trackWind, boolean correctWindByDeclination) throws Exception;
void sendSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage) throws IllegalArgumentException;
void stressTestLeaderboardByName(String leaderboardName, int times) throws Exception;
@@ -49,12 +49,21 @@ public interface SailingServiceAsync {
void listTracTracRacesInEvent(String eventJsonURL, AsyncCallback<Pair<String, List<TracTracRaceRecordDTO>>> callback);
/**
* @param liveURI may be <code>null</code> or the empty string in which case the server will
* use the {@link TracTracRaceRecordDTO#liveURI} from the <code>rr</code> race record.
* @param storedURImay be <code>null</code> or the empty string in which case the server will
* use the {@link TracTracRaceRecordDTO#storedURI} from the <code>rr</code> race record.
* @param regattaToAddTo
* if <code>null</code>, an existing regatta by the name of the TracTrac event with the boat class name
* appended in parentheses will be looked up; if not found, a default regatta with that name will be
* created, with a single default series and a single default fleet. If a valid {@link RegattaIdentifier}
* is specified, a regatta lookup is performed with that identifier; if the regatta is found, it is used
* to add the races to. Otherwise, a default regatta as described above will be created and used.
* @param liveURI
* may be <code>null</code> or the empty string in which case the server will use the
* {@link TracTracRaceRecordDTO#liveURI} from the <code>rr</code> race record.
* @param storedURImay
* be <code>null</code> or the empty string in which case the server will use the
* {@link TracTracRaceRecordDTO#storedURI} from the <code>rr</code> race record.
*/
void track(TracTracRaceRecordDTO rr, String liveURI, String storedURI, boolean trackWind, boolean correctWindByDeclination,
void trackWithTracTrac(RegattaIdentifier regattaToAddTo,
TracTracRaceRecordDTO rr, String liveURI, String storedURI, boolean trackWind, boolean correctWindByDeclination,
AsyncCallback<Void> callback);
void getPreviousTracTracConfigurations(AsyncCallback<List<TracTracConfigurationDTO>> callback);
@@ -235,8 +244,17 @@ public interface SailingServiceAsync {
void storeSwissTimingConfiguration(String configName, String hostname, int port, boolean canSendRequests, AsyncCallback<Void> asyncCallback);
void trackWithSwissTiming(SwissTimingRaceRecordDTO rr, String hostname, int port, boolean canSendRequests,
boolean trackWind, boolean correctWindByDeclination, AsyncCallback<Void> asyncCallback);
/**
* @param regattaToAddTo
* if <code>null</code>, an existing regatta by the name of the TracTrac event with the boat class name
* appended in parentheses will be looked up; if not found, a default regatta with that name will be
* created, with a single default series and a single default fleet. If a valid {@link RegattaIdentifier}
* is specified, a regatta lookup is performed with that identifier; if the regatta is found, it is used
* to add the races to. Otherwise, a default regatta as described above will be created and used.
*/
void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, SwissTimingRaceRecordDTO rr, String hostname, int port,
boolean canSendRequests, boolean trackWind, boolean correctWindByDeclination,
AsyncCallback<Void> asyncCallback);
void sendSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage, AsyncCallback<Void> callback);
@@ -302,4 +302,5 @@ public interface StringMessages extends Messages {
String showWindSpeedSeries();
String showWindDirectionSeries();
String fleet();
String boatClass();
}
@@ -299,4 +299,5 @@ registeredAt=Registered at {0}
replicatingFromMaster=Replicating from master {0}, JMS port {1}, servlet port {2}
showWindSpeedSeries=Show wind speed data
showWindDirectionSeries=Show wind directions data
fleet=Fleet
fleet=Fleet
boatClass=Boat Class
@@ -300,4 +300,5 @@ registeredAt=Registriert {0}
replicatingFromMaster=Repliziert von master {0}, JMS Port {1}, Servlet Port {2}
showWindSpeedSeries=Daten für Windgeschwindigkeit zeigen
showWindDirectionSeries=Daten für Windrichtung zeigen
fleet=Flotte
fleet=Flotte
boatClass=Bootsklasse
@@ -495,16 +495,17 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
@Override
public void track(TracTracRaceRecordDTO rr, String liveURI, String storedURI, boolean trackWind, final boolean correctWindByDeclination) throws Exception {
public void trackWithTracTrac(RegattaIdentifier regattaToAddTo, TracTracRaceRecordDTO rr, String liveURI, String storedURI,
boolean trackWind, final boolean correctWindByDeclination) throws Exception {
if (liveURI == null || liveURI.trim().length() == 0) {
liveURI = rr.liveURI;
}
if (storedURI == null || storedURI.trim().length() == 0) {
storedURI = rr.storedURI;
}
final RacesHandle raceHandle = getService().addTracTracRace(new URL(rr.paramURL), new URI(liveURI), new URI(storedURI),
new MillisecondsTimePoint(rr.trackingStartTime), new MillisecondsTimePoint(rr.trackingEndTime),
MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory), TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
final RacesHandle raceHandle = getService().addTracTracRace(regattaToAddTo, new URL(rr.paramURL), new URI(liveURI),
new URI(storedURI), new MillisecondsTimePoint(rr.trackingStartTime),
new MillisecondsTimePoint(rr.trackingEndTime), MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory), TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
if (trackWind) {
new Thread("Wind tracking starter for race "+rr.regattaName+"/"+rr.name) {
public void run() {
@@ -1440,11 +1441,11 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
@Override
public void trackWithSwissTiming(SwissTimingRaceRecordDTO rr, String hostname, int port, boolean canSendRequests,
boolean trackWind, final boolean correctWindByDeclination) throws Exception {
final RacesHandle raceHandle = getService().addSwissTimingRace(rr.ID, hostname, port, canSendRequests,
MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory),
TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
public void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, SwissTimingRaceRecordDTO rr, String hostname, int port,
boolean canSendRequests, boolean trackWind, final boolean correctWindByDeclination) throws Exception {
final RacesHandle raceHandle = getService().addSwissTimingRace(regattaToAddTo, rr.ID, hostname, port,
canSendRequests,
MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory), TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
if (trackWind) {
new Thread("Wind tracking starter for race "+rr.ID+"/"+rr.description) {
public void run() {
@@ -12,6 +12,7 @@ public class RegattaDTO extends NamedDTO implements IsSerializable {
public BoatClassDTO boatClass;
public List<RaceDTO> races;
public List<CompetitorDTO> competitors;
public List<SeriesDTO> series;
public RegattaDTO() {
}
@@ -0,0 +1,38 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.List;
import com.google.gwt.user.client.rpc.IsSerializable;
public class SeriesDTO extends NamedDTO implements IsSerializable {
private List<String> fleetNames;
private List<String> raceColumnNames;
private boolean isFleetsOrdered;
private boolean isMedal;
SeriesDTO() {} // for serializability
public SeriesDTO(String name, List<String> fleetNames, List<String> raceColumnNames, boolean isFleetsOrdered, boolean isMedal) {
super(name);
this.fleetNames = fleetNames;
this.raceColumnNames = raceColumnNames;
this.isFleetsOrdered = isFleetsOrdered;
}
public Iterable<String> getFleetNames() {
return fleetNames;
}
public Iterable<String> getRaceColumnNames() {
return raceColumnNames;
}
public boolean isFleetsOrdered() {
return isFleetsOrdered;
}
public boolean isMedal() {
return isMedal;
}
}
@@ -3,6 +3,8 @@ package com.sap.sailing.mongodb.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
@@ -26,6 +28,8 @@ import com.sap.sailing.domain.base.impl.RaceColumnInSeries;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.SeriesImpl;
import com.sap.sailing.domain.base.impl.VenueImpl;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
@@ -123,6 +127,30 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest
}
}
@Test
public void testStorageOfRaceIdentifiersOnRaceColumnInSeries() {
final int numberOfQualifyingRaces = 5;
final int numberOfFinalRaces = 7;
final String regattaBaseName = "Kieler Woche";
BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true);
Regatta regatta = createRegatta(numberOfQualifyingRaces, numberOfFinalRaces, regattaBaseName, boatClass);
Series qualifyingSeries = regatta.getSeries().iterator().next();
RaceColumn q2 = qualifyingSeries.getRaceColumnByName("Q2");
final RegattaNameAndRaceName q2TrackedRaceIdentifier = new RegattaNameAndRaceName(regatta.getName(), "Q2 TracTrac");
q2.setRaceIdentifier(qualifyingSeries.getFleetByName("Yellow"), q2TrackedRaceIdentifier);
MongoObjectFactory mof = MongoFactory.INSTANCE.getMongoObjectFactory(getMongoService());
mof.storeRegatta(regatta);
DomainObjectFactory dof = MongoFactory.INSTANCE.getDomainObjectFactory(getMongoService());
Regatta loadedRegatta = dof.loadRegatta(regatta.getName());
Series loadedQualifyingSeries = loadedRegatta.getSeries().iterator().next();
RaceColumn loadedQ2 = loadedQualifyingSeries.getRaceColumnByName("Q2");
RaceIdentifier loadedQ2TrackedRaceIdentifier = loadedQ2.getRaceIdentifier(loadedQualifyingSeries.getFleetByName("Yellow"));
assertEquals(q2TrackedRaceIdentifier, loadedQ2TrackedRaceIdentifier);
assertNotSame(q2TrackedRaceIdentifier, loadedQ2TrackedRaceIdentifier);
assertNull(loadedQualifyingSeries.getRaceColumnByName("Q1").getRaceIdentifier(loadedQualifyingSeries.getFleetByName("Yellow")));
assertNull(loadedQualifyingSeries.getRaceColumnByName("Q2").getRaceIdentifier(loadedQualifyingSeries.getFleetByName("Blue")));
}
private Regatta createRegatta(final int numberOfQualifyingRaces, final int numberOfFinalRaces,
final String regattaBaseName, BoatClass boatClass) {
@@ -70,7 +70,7 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive
@Test
public void testStoreAFewWindEntries() throws UnknownHostException, MongoException, InterruptedException {
DomainFactory domainFactory = DomainFactory.INSTANCE;
Regatta domainEvent = domainFactory.getOrCreateEvent(getTracTracEvent());
Regatta domainEvent = domainFactory.getOrCreateRegatta(getTracTracEvent());
DynamicTrackedRegatta trackedRegatta = new RacingEventServiceImpl().getOrCreateTrackedRegatta(domainEvent);
Iterable<Receiver> typeControllers = domainFactory.getUpdateReceivers(trackedRegatta, getTracTracEvent(),
EmptyWindStore.INSTANCE, /* startOfTracking */ null, /* endOfTracking */ null, new DynamicRaceDefinitionSet() {
@@ -18,8 +18,7 @@ public class MongoDBConfiguration {
private int port;
private String databaseName;
public static MongoDBConfiguration getDefaultConfiguration()
{
public static MongoDBConfiguration getDefaultConfiguration() {
String defaultHostName = System.getProperty(MONGO_HOSTNAME, "127.0.0.1");
int defaultPort = Integer.valueOf(System.getProperty(MONGO_PORT, "27017"));
String defaultDatabaseName = System.getProperty(MONGO_DB_NAME, DEFAULT_DB_NAME);
@@ -27,8 +26,7 @@ public class MongoDBConfiguration {
return new MongoDBConfiguration(defaultHostName, defaultPort, defaultDatabaseName);
}
public static MongoDBConfiguration getDefaultTestConfiguration()
{
public static MongoDBConfiguration getDefaultTestConfiguration() {
String defaultHostName = System.getProperty(MONGO_HOSTNAME, "127.0.0.1");
int defaultPort = Integer.valueOf(System.getProperty(MONGO_PORT, "27017"));
String defaultDatabaseName = System.getProperty(MONGO_DB_NAME, DEFAULT_TEST_DB_NAME);
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sailing.server.replication.test"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=com.sap.sailing.server.replication.test"/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.server.replication.test"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -XX:+UseParallelGC -Dtractrac.tunnel=true -Dtractrac.tunnel.host=10.18.206.73 -ea -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties"/>
</launchConfiguration>
@@ -42,6 +42,8 @@ public abstract class AbstractServerReplicationTest {
protected RacingEventServiceImpl master;
private MessageBrokerManager brokerMgr;
private File brokerPersistenceDir;
private ReplicaDescriptor replicaDescriptor;
private ReplicationServiceImpl masterReplicator;
/**
* Sets up master and replica, starts the JMS message broker and registers the replica with the master.
@@ -54,7 +56,7 @@ public abstract class AbstractServerReplicationTest {
master = new RacingEventServiceImpl(mongoDBService);
replica = new RacingEventServiceImpl(mongoDBService);
ReplicationInstancesManager rim = new ReplicationInstancesManager();
final String IN_VM_BROKER_URL = "vm://localhost-jms-connection";
final String IN_VM_BROKER_URL = "vm://localhost-jms-connection?broker.useJmx=false";
final String activeMQPersistenceParentDir = System.getProperty("java.io.tmpdir");
final String brokerName = "local_in-VM_test_broker";
brokerPersistenceDir = new File(activeMQPersistenceParentDir, brokerName);
@@ -63,8 +65,8 @@ public abstract class AbstractServerReplicationTest {
IN_VM_BROKER_URL, activeMQPersistenceParentDir));
brokerMgr.startMessageBroker(/* useJmx */ false);
brokerMgr.createAndStartConnection();
ReplicationService masterReplicator = new ReplicationServiceImpl(rim, brokerMgr, master);
ReplicaDescriptor replicaDescriptor = new ReplicaDescriptor(InetAddress.getLocalHost());
masterReplicator = new ReplicationServiceImpl(rim, brokerMgr, master);
replicaDescriptor = new ReplicaDescriptor(InetAddress.getLocalHost());
masterReplicator.registerReplica(replicaDescriptor);
ReplicationMasterDescriptor masterDescriptor = new ReplicationMasterDescriptor() {
@Override
@@ -106,6 +108,7 @@ public abstract class AbstractServerReplicationTest {
@After
public void tearDown() throws Exception {
masterReplicator.unregisterReplica(replicaDescriptor);
brokerMgr.closeSessions();
brokerMgr.closeConnections();
brokerMgr.stopMessageBroker();
@@ -84,7 +84,7 @@ public class TrackRaceReplicationTest extends AbstractServerReplicationTest {
}
private void startTrackingOnMaster() throws Exception {
racesHandle = master.addRace(trackingParams, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
racesHandle = master.addRace(/* regattaToAddTo */ null, trackingParams, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
}
private void waitForTrackRaceReplicationTrigger() throws InterruptedException {
@@ -66,7 +66,7 @@ public class ReplicationServiceImpl implements ReplicationService, OperationExec
private final Map<ReplicationMasterDescriptor, String> replicaUUIDs;
public ReplicationServiceImpl(final ReplicationInstancesManager replicationInstancesManager,
final MessageBrokerManager messageBrokerManager) {
final MessageBrokerManager messageBrokerManager) throws Exception {
this.replicationInstancesManager = replicationInstancesManager;
replicaUUIDs = new HashMap<ReplicationMasterDescriptor, String>();
this.messageBrokerManager = messageBrokerManager;
@@ -35,7 +35,7 @@ public class ReplicationServlet extends Servlet {
private ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker;
public ReplicationServlet() {
public ReplicationServlet() throws Exception {
BundleContext context = Activator.getDefaultContext();
replicationServiceTracker = new ServiceTracker<ReplicationService, ReplicationService>(context, ReplicationService.class.getName(), null);
replicationServiceTracker.open();
@@ -135,6 +135,7 @@ public class RaceTrackerStartStopTest {
assertSame(raceTracker1, currentTracker);
}
}
/**
* This test methods checks if the {@link RacingEventService#removeRace(Regatta, RaceDefinition) removeRace} method works correctly
*/
@@ -4,6 +4,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.MalformedURLException;
@@ -11,21 +12,24 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Set;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.tracking.RaceListener;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.domain.tractracadapter.TracTracConnectionConstants;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
public class RaceTrackerTest {
private static final Logger logger = Logger.getLogger(RaceTrackerTest.class.getName());
protected static final boolean tractracTunnel = Boolean.valueOf(System.getProperty("tractrac.tunnel", "false"));
protected static final String tractracTunnelHost = System.getProperty("tractrac.tunnel.host", "localhost");
private final URL paramUrl;
@@ -55,13 +59,20 @@ public class RaceTrackerTest {
@Before
public void setUp() throws Exception {
service = new RacingEventServiceImpl();
logger.info("Calling service.addTracTracRace");
raceHandle = service.addTracTracRace(paramUrl, liveUri, storedUri, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
raceHandle.getRaces(); // wait for RaceDefinition to be completely wired in Event
logger.info("Calling raceHandle.getRaces()");
Set<RaceDefinition> races = raceHandle.getRaces(); // wait for RaceDefinition to be completely wired in Regatta
logger.info("Obtained races: "+races);
assertTrue(!races.isEmpty());
// TODO the following assertion fails; this suggests that the race obtained above hasn't properly been entered into the regatta. Why???
assertTrue(!Util.isEmpty(raceHandle.getRegatta().getAllRaces()));
}
@After
public void tearDown() throws MalformedURLException, IOException, InterruptedException {
service.stopTracking(raceHandle.getRegatta());
logger.info("calling stopTrackingAndRemove("+raceHandle.getRegatta().getName()+" ("+raceHandle.getRegatta().hashCode()+"))");
service.stopTrackingAndRemove(raceHandle.getRegatta());
}
private TrackedRace getTrackedRace(TrackedRegatta trackedRegatta) throws InterruptedException {
@@ -88,22 +99,27 @@ public class RaceTrackerTest {
@Test
public void testInitialization() throws InterruptedException {
logger.entering(getClass().getName(), "testInitialization");
Set<RaceDefinition> races = raceHandle.getRaces();
assertNotNull(races);
assertFalse(races.isEmpty());
assertNotNull(getTrackedRace(raceHandle.getTrackedRegatta()));
logger.exiting(getClass().getName(), "testInitialization");
}
@Test
public void testStopTracking() throws Exception {
TrackedRegatta oldTrackedEvent = raceHandle.getTrackedRegatta();
TrackedRace oldTrackedRace = getTrackedRace(oldTrackedEvent);
logger.entering(getClass().getName(), "testStopTracking");
assertTrue(!Util.isEmpty(raceHandle.getRegatta().getAllRaces()));
TrackedRegatta oldTrackedRegatta = raceHandle.getTrackedRegatta();
TrackedRace oldTrackedRace = getTrackedRace(oldTrackedRegatta);
RaceDefinition oldRaceDefinition = oldTrackedRace.getRace();
service.removeEvent(raceHandle.getRegatta());
assertTrue(!Util.isEmpty(raceHandle.getRegatta().getAllRaces()));
service.removeRegatta(raceHandle.getRegatta());
RacesHandle myRaceHandle = service.addTracTracRace(paramUrl, liveUri, storedUri, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
TrackedRegatta newTrackedEvent = myRaceHandle.getTrackedRegatta();
assertNotSame(oldTrackedEvent, newTrackedEvent);
TrackedRace newTrackedRace = getTrackedRace(newTrackedEvent);
TrackedRegatta newTrackedRegatta = myRaceHandle.getTrackedRegatta();
assertNotSame(oldTrackedRegatta, newTrackedRegatta);
TrackedRace newTrackedRace = getTrackedRace(newTrackedRegatta);
// expecting a new tracked race to be created when starting over with tracking
try {
assertNotSame(oldTrackedRace, newTrackedRace);
@@ -111,6 +127,7 @@ public class RaceTrackerTest {
} finally {
service.stopTracking(myRaceHandle.getRegatta());
}
logger.exiting(getClass().getName(), "testStopTracking");
}
/**
@@ -120,6 +137,7 @@ public class RaceTrackerTest {
*/
@Test
public void testTrackingSameRaceWithoutStopping() throws Exception {
logger.entering(getClass().getName(), "testTrackingSameRaceWithoutStopping");
TrackedRegatta oldTrackedRegatta = raceHandle.getTrackedRegatta();
TrackedRace oldTrackedRace = getTrackedRace(oldTrackedRegatta);
RacesHandle myRaceHandle = service.addTracTracRace(paramUrl, liveUri, storedUri, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
@@ -132,5 +150,6 @@ public class RaceTrackerTest {
} finally {
service.stopTracking(myRaceHandle.getRegatta());
}
logger.exiting(getClass().getName(), "testStopTracking");
}
}
@@ -143,9 +143,16 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
* Same as {@link #addTracTracRace(URL, URI, URI, WindStore, long)}, only that start and end of tracking are
* specified which may help reducing the amount of stored data (particularly mark positions) that needs to be
* loaded.
*
* @param regattaToAddTo
* if <code>null</code>, an existing regatta by the name of the TracTrac event with the boat class name
* appended in parentheses will be looked up; if not found, a default regatta with that name will be
* created, with a single default series and a single default fleet. If a valid {@link RegattaIdentifier}
* is specified, a regatta lookup is performed with that identifier; if the regatta is found, it is used
* to add the races to. Otherwise, a default regatta as described above will be created and used.
*/
RacesHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, TimePoint trackingStartTime,
TimePoint trackingEndTime, WindStore windStore, long timeoutForReceivingRaceDefinitionInMilliseconds)
RacesHandle addTracTracRace(RegattaIdentifier regattaToAddTo, URL paramURL, URI liveURI, URI storedURI,
TimePoint trackingStartTime, TimePoint trackingEndTime, WindStore windStore, long timeoutForReceivingRaceDefinitionInMilliseconds)
throws MalformedURLException, FileNotFoundException, URISyntaxException, Exception;
/**
@@ -259,8 +266,16 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
*/
void updateStoredLeaderboard(Leaderboard leaderboard);
RacesHandle addSwissTimingRace(String raceID, String hostname, int port, boolean canSendRequests,
WindStore windStore, long timeoutInMilliseconds) throws InterruptedException, UnknownHostException,
/**
* @param regattaToAddTo
* if <code>null</code>, an existing regatta by the name of the TracTrac event with the boat class name
* appended in parentheses will be looked up; if not found, a default regatta with that name will be
* created, with a single default series and a single default fleet. If a valid {@link RegattaIdentifier}
* is specified, a regatta lookup is performed with that identifier; if the regatta is found, it is used
* to add the races to. Otherwise, a default regatta as described above will be created and used.
*/
RacesHandle addSwissTimingRace(RegattaIdentifier regattaToAddTo, String raceID, String hostname, int port,
boolean canSendRequests, WindStore windStore, long timeoutInMilliseconds) throws InterruptedException, UnknownHostException,
IOException, ParseException, Exception;
SwissTimingFactory getSwissTimingFactory();
@@ -269,7 +284,7 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
void stopTrackingAndRemove(Regatta regatta) throws MalformedURLException, IOException, InterruptedException;
void removeEvent(Regatta regatta) throws MalformedURLException, IOException, InterruptedException;
void removeRegatta(Regatta regatta) throws MalformedURLException, IOException, InterruptedException;
TrackedRace getExistingTrackedRace(RaceIdentifier raceIdentifier);
@@ -325,9 +340,16 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
void removeExpeditionListener(ExpeditionListener listener);
/**
* @param windStore must not be <code>null</code>, but can, e.g., be an {@link EmptyWindStore}
* @param regattaToAddTo
* if <code>null</code>, an existing regatta by the name of the TracTrac event with the boat class name
* appended in parentheses will be looked up; if not found, a default regatta with that name will be
* created, with a single default series and a single default fleet. If a valid {@link RegattaIdentifier}
* is specified, a regatta lookup is performed with that identifier; if the regatta is found, it is used
* to add the races to. Otherwise, a default regatta as described above will be created and used.
* @param windStore
* must not be <code>null</code>, but can, e.g., be an {@link EmptyWindStore}
*/
RacesHandle addRace(RaceTrackingConnectivityParameters params, WindStore windStore, long timeoutInMilliseconds)
RacesHandle addRace(RegattaIdentifier regattaToAddTo, RaceTrackingConnectivityParameters params, WindStore windStore, long timeoutInMilliseconds)
throws MalformedURLException, FileNotFoundException, URISyntaxException, Exception;
TrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore,
@@ -30,16 +30,16 @@ import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.RegattaListener;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.common.DefaultLeaderboardName;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.impl.Util;
@@ -49,8 +49,8 @@ import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl;
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl;
import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl;
import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
@@ -70,8 +70,8 @@ import com.sap.sailing.domain.tracking.RaceListener;
import com.sap.sailing.domain.tracking.RaceTracker;
import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.domain.tracking.WindStore;
import com.sap.sailing.domain.tracking.WindTracker;
@@ -88,8 +88,8 @@ import com.sap.sailing.operationaltransformation.Operation;
import com.sap.sailing.server.OperationExecutionListener;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
import com.sap.sailing.server.operationaltransformation.AddRegatta;
import com.sap.sailing.server.operationaltransformation.AddRaceDefinition;
import com.sap.sailing.server.operationaltransformation.AddRegatta;
import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn;
import com.sap.sailing.server.operationaltransformation.CreateTrackedRace;
import com.sap.sailing.server.operationaltransformation.RecordBuoyGPSFix;
@@ -418,6 +418,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
Regatta result = regattasByName.get(regatta.getName());
if (result == null) {
result = regatta;
logger.info("Created regatta "+result.getName()+" ("+hashCode()+")");
cacheAndReplicateRegatta(result);
}
return result;
@@ -448,19 +449,22 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
}
@Override
public synchronized RacesHandle addSwissTimingRace(String raceID, String hostname, int port,
boolean canSendRequests, WindStore windStore, long timeoutInMilliseconds) throws Exception {
public synchronized RacesHandle addSwissTimingRace(RegattaIdentifier regattaToAddTo, String raceID, String hostname,
int port, boolean canSendRequests, WindStore windStore, long timeoutInMilliseconds) throws Exception {
return addRace(
regattaToAddTo,
swissTimingDomainFactory.createTrackingConnectivityParameters(hostname, port, raceID, canSendRequests,
swissTimingFactory, swissTimingDomainFactory, windStore, swissTimingAdapterPersistence),
windStore, timeoutInMilliseconds);
swissTimingFactory, swissTimingDomainFactory, windStore, swissTimingAdapterPersistence), windStore, timeoutInMilliseconds);
}
@Override
public synchronized RacesHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore,
long timeoutInMilliseconds) throws Exception {
return addRace(getDomainFactory().createTrackingConnectivityParameters(paramURL, liveURI, storedURI, /* startOfTracking */ null,
/* endOfTracking */ null, windStore), windStore, timeoutInMilliseconds);
return addRace(
/* regattaToAddTo */ null,
getDomainFactory().createTrackingConnectivityParameters(paramURL, liveURI, storedURI,
/* startOfTracking */ null,
/* endOfTracking */null, windStore), windStore, timeoutInMilliseconds);
}
@Override
@@ -483,11 +487,19 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
}
@Override
public synchronized RacesHandle addRace(RaceTrackingConnectivityParameters params, WindStore windStore,
long timeoutInMilliseconds) throws Exception {
public synchronized RacesHandle addRace(RegattaIdentifier regattaToAddTo, RaceTrackingConnectivityParameters params,
WindStore windStore, long timeoutInMilliseconds) throws Exception {
RaceTracker tracker = raceTrackersByID.get(params.getTrackerID());
if (tracker == null) {
tracker = params.createRaceTracker(this);
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);
} else {
// use the regatta selected by the RaceIdentifier regattaToAddTo
tracker = params.createRaceTracker(regatta, this);
assert tracker.getRegatta() == regatta;
}
raceTrackersByID.put(params.getTrackerID(), tracker);
Set<RaceTracker> trackers = raceTrackersByRegatta.get(tracker.getRegatta());
if (trackers == null) {
@@ -552,11 +564,11 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
}
@Override
public synchronized RacesHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI,
TimePoint startOfTracking, TimePoint endOfTracking, WindStore windStore,
long timeoutInMilliseconds) throws Exception {
return addRace(getDomainFactory().createTrackingConnectivityParameters(paramURL, liveURI, storedURI, startOfTracking,
endOfTracking, windStore), windStore, timeoutInMilliseconds);
public synchronized RacesHandle addTracTracRace(RegattaIdentifier regattaToAddTo, URL paramURL, URI liveURI,
URI storedURI, TimePoint startOfTracking, TimePoint endOfTracking,
WindStore windStore, long timeoutInMilliseconds) throws Exception {
return addRace(regattaToAddTo, getDomainFactory().createTrackingConnectivityParameters(paramURL, liveURI, storedURI, startOfTracking,
endOfTracking, windStore), windStore, timeoutInMilliseconds);
}
private void ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(DynamicTrackedRegatta trackedRegatta) {
@@ -715,7 +727,9 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
stopTracking(regatta);
if (regatta != null) {
if (regatta.getName() != null) {
logger.info("Removing regatta "+regatta.getName()+" ("+regatta.hashCode()+") from RacingEventServiceImpl");
regattasByName.remove(regatta.getName());
regattaTrackingCache.remove(regatta);
regatta.removeRegattaListener(this);
}
for (RaceDefinition race : regatta.getAllRaces()) {
@@ -790,7 +804,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
}
@Override
public synchronized void removeEvent(Regatta regatta) throws MalformedURLException, IOException, InterruptedException {
public synchronized void removeRegatta(Regatta regatta) throws MalformedURLException, IOException, InterruptedException {
for (RaceDefinition race : regatta.getAllRaces()) {
removeRace(regatta, race);
}
@@ -799,7 +813,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
@Override
public synchronized void removeRace(Regatta regatta, RaceDefinition race) throws MalformedURLException,
IOException, InterruptedException {
logger.info("Removing the race + " + race + "...");
logger.info("Removing the race " + race + "...");
stopAllTrackersForWhichRaceIsLastReachable(regatta, race);
stopTrackingWind(regatta, race);
TrackedRace trackedRace = getExistingTrackedRace(regatta, race);
@@ -829,6 +843,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
// remove the race from the regatta
regatta.removeRace(race);
if (Util.isEmpty(regatta.getAllRaces())) {
logger.info("Removing regatta "+regatta.getName()+" from service "+this);
regattasByName.remove(regatta.getName());
regatta.removeRegattaListener(this);
}
@@ -914,6 +929,8 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
synchronized (regattaTrackingCache) {
DynamicTrackedRegatta result = regattaTrackingCache.get(regatta);
if (result == null) {
logger.info("Creating DynamicTrackedRegattaImpl for regatta "+regatta.getName()+
" with hashCode "+regatta.hashCode());
result = new DynamicTrackedRegattaImpl(regatta);
replicate(new TrackRegatta(regatta.getRegattaIdentifier()));
regattaTrackingCache.put(regatta, result);
@@ -930,6 +947,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
@Override
public void removeTrackedRegatta(Regatta regatta) {
logger.info("Removing regatta "+regatta.getName()+" from regattaTrackingCache");
regattaTrackingCache.remove(regatta);
}
@@ -1123,7 +1141,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
<T> void replicate(RacingEventServiceOperation<T> operation) {
for (OperationExecutionListener listener : operationExecutionListeners) {
listener.executed(operation);
listener.executed(operation); // TODO consider exception handling
}
}
+1 -1
View File
@@ -149,7 +149,7 @@
<argLine>-Dfile.encoding=cp1252 -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y -Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -Dmongo.dbName=winddbTest -Dreplication.brokerURL=tcp://localhost:61615 -Xmx1024m -XX:PermSize=256m -XX:-UseGCOverheadLimit -XX:+UseParallelGC</argLine>
-->
<!-- debug, no proxy
<!-- debug, no proxy
<argLine>-Dfile.encoding=cp1252 -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y -Dmongo.dbName=winddbTest -Dreplication.brokerURL=tcp://localhost:61615 -Xmx1024m -XX:PermSize=256m -XX:-UseGCOverheadLimit -XX:+UseParallelGC</argLine>
-->