added competitor persistence; a first attempt to cherry-pick and merge this feature from the cmd-android-tracking branch

Conflicts:

	java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java
	java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java
	java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorDeserializer.java
	java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java
	java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/BoatJsonSerializer.java
	java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/tracking/impl/CreateCompetitorPostServlet.java
	java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java
This commit is contained in:
Fredrik Teschke authored and Axel Uhl committed 2013-10-23 10:01:12 +02:00
1 parent 125bd67529
commit f7a3f5c8df
31 files changed
+379 -80

No files matched your search

@@ -10,9 +10,11 @@ Require-Bundle: com.sap.sailing.mongodb,
com.sap.sailing.domain,
com.mongodb.driver;bundle-version="2.6.2",
com.sap.sailing.domain.common,
com.sap.sailing.domain.shared.android
com.sap.sailing.domain.shared.android,
com.sap.sailing.server.gateway.serialization;bundle-version="1.0.0"
Export-Package: com.sap.sailing.domain.persistence,
com.sap.sailing.domain.persistence.impl;x-friends:="com.sap.sailing.mongodb.test,com.sap.sailing.domain.swisstimingadapter.test,com.sap.sailing.domain.persistence.test",
com.sap.sailing.domain.persistence.media
Bundle-ActivationPolicy: lazy
Import-Package: org.osgi.framework;version="1.6.0"
Import-Package: org.json.simple,
org.osgi.framework;version="1.6.0"
@@ -1,8 +1,10 @@
package com.sap.sailing.domain.persistence;
import java.util.Collection;
import java.util.Map;
import com.mongodb.DBObject;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
@@ -86,4 +88,10 @@ public interface DomainObjectFactory {
Map<String, Regatta> loadRaceIDToRegattaAssociations(RegattaRegistry regattaRegistry);
RaceLog loadRaceLog(RaceLogIdentifier identifier);
/**
* Loads all competitors, and resolves them via the domain factory.
* @return
*/
Collection<Competitor> loadAllCompetitors();
}
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.persistence;
import java.io.Serializable;
import com.mongodb.DBObject;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
@@ -86,4 +87,11 @@ public interface MongoObjectFactory {
void removeRegattaForRaceID(String raceIDAsString, Regatta regatta);
/**
* Stores a competitor, including the team and boat. This should not be done for competitors for which
* the master data is supplied by other systems, such as TracTrac, but rather for smartphone tracking,
* where this data is otherwise not recoverable.
* @param competitor
*/
void storeCompetitor(Competitor competitor);
}
@@ -51,5 +51,10 @@ public enum CollectionNames {
/**
* Stores the race log events for a tracked race.
*/
RACE_LOGS;
RACE_LOGS,
/**
* Stores competitors for smartphone tracking.
*/
COMPETITORS,
}
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.persistence.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -12,6 +13,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.bson.types.ObjectId;
import org.json.simple.JSONObject;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
@@ -20,6 +22,7 @@ import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
@@ -110,9 +113,12 @@ import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.impl.WindImpl;
import com.sap.sailing.domain.tracking.impl.WindTrackImpl;
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
public class DomainObjectFactoryImpl implements DomainObjectFactory {
private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName());
private final CompetitorJsonDeserializer competitorDeserializer = CompetitorJsonDeserializer.create();
private final DB database;
@@ -1255,4 +1261,23 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
Mark mark = DomainFactory.INSTANCE.getOrCreateMark(markId, markName, markType, markColor, markShape, markPattern);
return mark;
}
@Override
public Collection<Competitor> loadAllCompetitors() {
ArrayList<Competitor> result = new ArrayList<Competitor>();
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
try {
for (DBObject o : collection.find()) {
JSONObject json = Helpers.toJSONObjectSafe(JSON.serialize(o));
Competitor c = competitorDeserializer.deserialize(json);
result.add(c);
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load competitors.");
logger.log(Level.SEVERE, "loadCompetitors", e);
}
return result;
}
}
@@ -6,12 +6,14 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.bson.types.ObjectId;
import org.json.simple.JSONObject;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.CourseArea;
@@ -66,10 +68,12 @@ 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.WindTrack;
import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer;
public class MongoObjectFactoryImpl implements MongoObjectFactory {
private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName());
private final DB database;
private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create();
public MongoObjectFactoryImpl(DB database) {
super();
@@ -858,4 +862,15 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
return passing;
}
@Override
public void storeCompetitor(Competitor competitor) {
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
JSONObject json = competitorSerializer.serialize(competitor);
BasicDBObject query = new BasicDBObject(FieldNames.COMPETITOR_ID.name(), competitor.getId());
DBObject entry = (DBObject) JSON.parse(json.toString());
collection.update(query, entry, /* upsrt */ true, /* multi */ false);
}
}
@@ -82,5 +82,4 @@ public interface SharedDomainFactory {
CourseArea getExistingCourseAreaById(Serializable courseAreaId);
}
@@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.common.MarkType;
@@ -32,7 +32,7 @@ import com.sap.sailing.server.gateway.deserialization.coursedata.impl.CourseBase
import com.sap.sailing.server.gateway.deserialization.coursedata.impl.GateDeserializer;
import com.sap.sailing.server.gateway.deserialization.coursedata.impl.MarkDeserializer;
import com.sap.sailing.server.gateway.deserialization.coursedata.impl.WaypointDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogCourseDesignChangedEventDeserializer;
import com.sap.sailing.server.gateway.serialization.coursedata.impl.ControlPointJsonSerializer;
import com.sap.sailing.server.gateway.serialization.coursedata.impl.CourseBaseJsonSerializer;
@@ -40,9 +40,6 @@ import com.sap.sailing.server.gateway.serialization.coursedata.impl.GateJsonSeri
import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer;
import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.PersonJsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.TeamJsonSerializer;
import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogCourseDesignChangedEventSerializer;
public class RaceLogCourseDesignChangedEventSerializerTest {
@@ -55,12 +52,10 @@ public class RaceLogCourseDesignChangedEventSerializerTest {
@Before
public void setUp() {
SharedDomainFactory factory = DomainFactory.INSTANCE;
NationalityJsonSerializer nationalityJsonSerializer = new NationalityJsonSerializer();
serializer = new RaceLogCourseDesignChangedEventSerializer(new CompetitorJsonSerializer(new TeamJsonSerializer(
new PersonJsonSerializer(nationalityJsonSerializer))),
serializer = new RaceLogCourseDesignChangedEventSerializer(CompetitorJsonSerializer.create(),
new CourseBaseJsonSerializer(new WaypointJsonSerializer(new ControlPointJsonSerializer(
new MarkJsonSerializer(), new GateJsonSerializer(new MarkJsonSerializer())))));
deserializer = new RaceLogCourseDesignChangedEventDeserializer(new CompetitorDeserializer(factory),
deserializer = new RaceLogCourseDesignChangedEventDeserializer(CompetitorJsonDeserializer.create(),
new CourseBaseDeserializer(new WaypointDeserializer(new ControlPointDeserializer(new MarkDeserializer(
factory), new GateDeserializer(factory, new MarkDeserializer(factory))))));
now = MillisecondsTimePoint.now();
@@ -23,7 +23,7 @@ import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.racelog.RaceLogEventFactory;
import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogFinishPositioningConfirmedEventDeserializer;
import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer;
@@ -43,8 +43,8 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest {
public void setUp() {
SharedDomainFactory factory = DomainFactory.INSTANCE;
serializer = new RaceLogFinishPositioningConfirmedEventSerializer(new CompetitorJsonSerializer(
new TeamJsonSerializer(new PersonJsonSerializer(new NationalityJsonSerializer()))));
deserializer = new RaceLogFinishPositioningConfirmedEventDeserializer(new CompetitorDeserializer(factory));
new TeamJsonSerializer(new PersonJsonSerializer(new NationalityJsonSerializer())), null));
deserializer = new RaceLogFinishPositioningConfirmedEventDeserializer(new CompetitorJsonDeserializer(factory, null));
now = MillisecondsTimePoint.now();
positioningList = new ArrayList<Triple<Serializable, String, MaxPointsReason>>();
@@ -23,7 +23,7 @@ import com.sap.sailing.domain.racelog.RaceLogWindFixEvent;
import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.domain.tracking.impl.WindImpl;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.PositionJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.WindJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogWindFixEventDeserializer;
@@ -46,9 +46,9 @@ public class RaceLogWindFixEventSerializerTest {
public void setUp() {
SharedDomainFactory factory = DomainFactory.INSTANCE;
serializer = new RaceLogWindFixEventSerializer(new CompetitorJsonSerializer(new TeamJsonSerializer(
new PersonJsonSerializer(new NationalityJsonSerializer()))), new WindJsonSerializer(
new PersonJsonSerializer(new NationalityJsonSerializer())), null), new WindJsonSerializer(
new PositionJsonSerializer()));
deserializer = new RaceLogWindFixEventDeserializer(new CompetitorDeserializer(factory),
deserializer = new RaceLogWindFixEventDeserializer(new CompetitorJsonDeserializer(factory, null),
new WindJsonDeserializer(new PositionJsonDeserializer()));
now = MillisecondsTimePoint.now();
@@ -18,6 +18,12 @@ public class BoatClassJsonDeserializer implements JsonDeserializer<BoatClass> {
public BoatClass deserialize(JSONObject object) throws JsonDeserializationException {
String name = object.get(BoatClassJsonSerializer.FIELD_NAME).toString();
if (object.containsKey(BoatClassJsonSerializer.FIELD_TYPICALLY_STARTS_UPWIND)) {
boolean typicallyStartsUpwind = Boolean.parseBoolean(object.get(BoatClassJsonSerializer.FIELD_TYPICALLY_STARTS_UPWIND).toString());
return domainFactory.getOrCreateBoatClass(name, typicallyStartsUpwind);
}
return domainFactory.getOrCreateBoatClass(name);
}
@@ -1,30 +0,0 @@
package com.sap.sailing.server.gateway.deserialization.impl;
import java.io.Serializable;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer;
public class CompetitorDeserializer implements JsonDeserializer<Competitor> {
protected SharedDomainFactory factory;
public CompetitorDeserializer(SharedDomainFactory factory) {
this.factory = factory;
}
@Override
public Competitor deserialize(JSONObject object) throws JsonDeserializationException {
Serializable competitorId = (Serializable) object.get(CompetitorJsonSerializer.FIELD_ID);
competitorId = Helpers.tryUuidConversion(competitorId);
String name = (String) object.get(CompetitorJsonSerializer.FIELD_NAME);
Competitor competitor = factory.getOrCreateCompetitor(competitorId, name, null, null);
return competitor;
}
}
@@ -0,0 +1,59 @@
package com.sap.sailing.server.gateway.deserialization.impl;
import java.io.Serializable;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer;
public class CompetitorJsonDeserializer implements JsonDeserializer<Competitor> {
protected final SharedDomainFactory factory;
protected final JsonDeserializer<Team> teamJsonDeserializer;
public static CompetitorJsonDeserializer create() {
return new CompetitorJsonDeserializer(DomainFactory.INSTANCE,
new TeamJsonDeserializer(
new PersonJsonDeserializer(
new NationalityJsonDeserializer(
DomainFactory.INSTANCE))));
}
public CompetitorJsonDeserializer(SharedDomainFactory factory) {
this(factory, null);
}
public CompetitorJsonDeserializer(SharedDomainFactory factory,
JsonDeserializer<Team> teamJsonDeserializer) {
this.factory = factory;
this.teamJsonDeserializer = teamJsonDeserializer;
}
@Override
public Competitor deserialize(JSONObject object)
throws JsonDeserializationException {
Serializable competitorId = (Serializable) object
.get(CompetitorJsonSerializer.FIELD_ID);
competitorId = Helpers.tryUuidConversion(competitorId);
String name = (String) object.get(CompetitorJsonSerializer.FIELD_NAME);
Team team = null;
Boat boat = null;
if (teamJsonDeserializer != null) {
team = teamJsonDeserializer.deserialize(Helpers
.getNestedObjectSafe(object,
CompetitorJsonSerializer.FIELD_TEAM));
}
Competitor competitor = factory.getOrCreateCompetitor(competitorId,
name, team, boat);
return competitor;
}
}
@@ -3,14 +3,20 @@ package com.sap.sailing.server.gateway.deserialization.impl;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer;
public class NationalityJsonDeserialzer implements JsonDeserializer<Nationality> {
public class NationalityJsonDeserializer implements JsonDeserializer<Nationality> {
private final SharedDomainFactory domainFactory;
@Override
public NationalityJsonDeserializer(SharedDomainFactory domainFactory) {
this.domainFactory = domainFactory;
}
@Override
public Nationality deserialize(JSONObject object) throws JsonDeserializationException {
final Nationality result;
if (object == null) {
@@ -20,7 +26,7 @@ public class NationalityJsonDeserialzer implements JsonDeserializer<Nationality>
if (threeLetterIOCAcronym == null) {
result = null;
} else {
result = new NationalityImpl(threeLetterIOCAcronym);
result = (Nationality) new NationalityImpl(threeLetterIOCAcronym).resolve(domainFactory);
}
}
return result;
@@ -6,6 +6,7 @@ import java.util.Set;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Person;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.impl.TeamImpl;
@@ -15,25 +16,32 @@ import com.sap.sailing.server.gateway.serialization.impl.TeamJsonSerializer;
public class TeamJsonDeserializer implements JsonDeserializer<Team> {
private final JsonDeserializer<Person> personDeserializer;
private final JsonDeserializer<Person> personDeserializer;
public TeamJsonDeserializer(JsonDeserializer<Person> personDeserializer) {
this.personDeserializer = personDeserializer;
}
public static TeamJsonDeserializer create() {
return new TeamJsonDeserializer(new PersonJsonDeserializer(
new NationalityJsonDeserializer(DomainFactory.INSTANCE)));
}
public TeamJsonDeserializer(JsonDeserializer<Person> personDeserializer) {
this.personDeserializer = personDeserializer;
}
@Override
public Team deserialize(JSONObject object)
throws JsonDeserializationException {
String name = (String) object.get(TeamJsonSerializer.FIELD_NAME);
Person coach = personDeserializer.deserialize((JSONObject) object
.get(TeamJsonSerializer.FIELD_COACH));
Set<Person> sailors = new HashSet<Person>();
@Override
public Team deserialize(JSONObject object) throws JsonDeserializationException {
String name = (String) object.get(TeamJsonSerializer.FIELD_NAME);
Person coach = personDeserializer.deserialize((JSONObject) object.get(TeamJsonSerializer.FIELD_COACH));
Set<Person> sailors = new HashSet<Person>();
JSONArray sailorsJson = (JSONArray) object.get(TeamJsonSerializer.FIELD_SAILORS);
for (Object sailorObject : sailorsJson) {
sailors.add(personDeserializer.deserialize((JSONObject) sailorObject));
}
return new TeamImpl(name, sailors, coach);
}
JSONArray sailorsJson = (JSONArray) object
.get(TeamJsonSerializer.FIELD_SAILORS);
for (Object sailorObject : sailorsJson) {
sailors.add(personDeserializer
.deserialize((JSONObject) sailorObject));
}
return new TeamImpl(name, sailors, coach);
}
}
@@ -28,7 +28,7 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.BoatClassJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.ColorDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.FleetDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.NationalityJsonDeserialzer;
import com.sap.sailing.server.gateway.deserialization.impl.NationalityJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.PersonJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.TeamJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogEventDeserializer;
@@ -46,7 +46,7 @@ public class LeaderboardGroupMasterDataJsonDeserializer implements JsonDeseriali
public static JsonDeserializer<LeaderboardGroupMasterData> create(DomainFactory domainFactory) {
JsonDeserializer<BoatClass> boatClassDeserializer = new BoatClassJsonDeserializer(domainFactory);
JsonDeserializer<Nationality> nationalityDeserializer = new NationalityJsonDeserialzer();
JsonDeserializer<Nationality> nationalityDeserializer = new NationalityJsonDeserializer(domainFactory);
JsonDeserializer<Person> personDeserializer = new PersonJsonDeserializer(nationalityDeserializer);
JsonDeserializer<Team> teamDeserializer = new TeamJsonDeserializer(personDeserializer);
JsonDeserializer<Competitor> competitorDeserializer = new CompetitorMasterDataDeserializer(
@@ -12,7 +12,7 @@ import com.sap.sailing.server.gateway.deserialization.coursedata.impl.CourseBase
import com.sap.sailing.server.gateway.deserialization.coursedata.impl.GateDeserializer;
import com.sap.sailing.server.gateway.deserialization.coursedata.impl.MarkDeserializer;
import com.sap.sailing.server.gateway.deserialization.coursedata.impl.WaypointDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.PositionJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.WindJsonDeserializer;
import com.sap.sailing.server.gateway.serialization.racelog.impl.BaseRaceLogEventSerializer;
@@ -33,7 +33,7 @@ import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogWindFixE
public class RaceLogEventDeserializer implements JsonDeserializer<RaceLogEvent> {
public static RaceLogEventDeserializer create(SharedDomainFactory domainFactory) {
JsonDeserializer<Competitor> competitorDeserializer = new CompetitorDeserializer(domainFactory);
JsonDeserializer<Competitor> competitorDeserializer = new CompetitorJsonDeserializer(domainFactory, null);
return new RaceLogEventDeserializer(
new RaceLogFlagEventDeserializer(competitorDeserializer),
new RaceLogStartTimeEventDeserializer(competitorDeserializer),
@@ -7,11 +7,13 @@ import com.sap.sailing.server.gateway.serialization.JsonSerializer;
public class BoatClassJsonSerializer implements JsonSerializer<BoatClass> {
public static final String FIELD_NAME = "name";
public static final String FIELD_TYPICALLY_STARTS_UPWIND = "typicallyStartsUpwind";
@Override
public JSONObject serialize(BoatClass boatClass) {
JSONObject result = new JSONObject();
result.put(FIELD_NAME, boatClass.getName());
result.put(FIELD_TYPICALLY_STARTS_UPWIND, boatClass.typicallyStartsUpwind());
return result;
}
}
@@ -0,0 +1,35 @@
package com.sap.sailing.server.gateway.serialization.impl;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
public class BoatJsonSerializer implements JsonSerializer<Boat> {
public static final String FIELD_NAME = "name";
public static final String FIELD_SAIL_ID = "sailId";
public static final String FIELD_BOAT_CLASS = "boatClass";
private final JsonSerializer<BoatClass> boatClassJsonSerializer;
public static BoatJsonSerializer create() {
return new BoatJsonSerializer(new BoatClassJsonSerializer());
}
public BoatJsonSerializer(JsonSerializer<BoatClass> boatClassJsonSerializer) {
this.boatClassJsonSerializer = boatClassJsonSerializer;
}
@Override
public JSONObject serialize(Boat boat) {
JSONObject result = new JSONObject();
result.put(FIELD_NAME, boat.getName());
result.put(FIELD_SAIL_ID, boat.getSailID());
if (boatClassJsonSerializer != null) {
result.put(FIELD_BOAT_CLASS, boatClassJsonSerializer.serialize(boat.getBoatClass()));
}
return result;
}
}
@@ -2,6 +2,7 @@ package com.sap.sailing.server.gateway.serialization.impl;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.Team;
@@ -16,15 +17,22 @@ public class CompetitorJsonSerializer implements JsonSerializer<Competitor> {
public static final String FIELD_NATIONALITY_ISO2 = "nationalityISO2";
public static final String FIELD_NATIONALITY_ISO3 = "nationalityISO3";
public static final String FIELD_TEAM = "team";
public static final String FIELD_BOAT = "boat";
private final JsonSerializer<Team> teamJsonSerializer;
private final JsonSerializer<Boat> boatJsonSerializer;
public CompetitorJsonSerializer() {
this(null);
public static CompetitorJsonSerializer create() {
return new CompetitorJsonSerializer(TeamJsonSerializer.create(), BoatJsonSerializer.create());
}
public CompetitorJsonSerializer(JsonSerializer<Team> teamJsonSerializer) {
public CompetitorJsonSerializer() {
this(null, null);
}
public CompetitorJsonSerializer(JsonSerializer<Team> teamJsonSerializer, JsonSerializer<Boat> teamBoatSerializer) {
this.teamJsonSerializer = teamJsonSerializer;
this.boatJsonSerializer = teamBoatSerializer;
}
@Override
@@ -42,6 +50,9 @@ public class CompetitorJsonSerializer implements JsonSerializer<Competitor> {
if(teamJsonSerializer != null) {
result.put(FIELD_TEAM, teamJsonSerializer.serialize(competitor.getTeam()));
}
if(boatJsonSerializer != null) {
result.put(FIELD_BOAT, boatJsonSerializer.serialize(competitor.getBoat()));
}
return result;
}
@@ -15,6 +15,10 @@ public class TeamJsonSerializer implements JsonSerializer<Team> {
private final JsonSerializer<Person> personJsonSerializer;
public static TeamJsonSerializer create() {
return new TeamJsonSerializer(new PersonJsonSerializer(new NationalityJsonSerializer()));
}
public TeamJsonSerializer(JsonSerializer<Person> personJsonSerializer) {
this.personJsonSerializer = personJsonSerializer;
}
@@ -35,9 +35,9 @@ public class RegattaEntryListJsonGetServlet extends AbstractJsonHttpServlet {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Regatta " + regattaName
+ " not found");
} else {
NationalityJsonSerializer nationalityJsonSerializer = new NationalityJsonSerializer();
NationalityJsonSerializer nationalityJsonSerializer = new NationalityJsonSerializer();
CompetitorJsonSerializer competitorJsonSerializer = new CompetitorJsonSerializer(
new TeamJsonSerializer(new PersonJsonSerializer(nationalityJsonSerializer)));
new TeamJsonSerializer(new PersonJsonSerializer(nationalityJsonSerializer)), null);
JsonSerializer<Regatta> regattaSerializer = new RegattaJsonSerializer(null, competitorJsonSerializer);
JSONObject serializedRegatta = regattaSerializer.serialize(regatta);
@@ -76,7 +76,8 @@ public class CompetitorsJsonExportServlet extends AbstractJsonHttpServlet {
JSONArray result = new JSONArray();
if (trackedRace != null) {
CompetitorJsonSerializer serializer = new CompetitorJsonSerializer(new TeamJsonSerializer(new PersonJsonSerializer(new NationalityJsonSerializer())));
CompetitorJsonSerializer serializer = new CompetitorJsonSerializer(new TeamJsonSerializer(
new PersonJsonSerializer(new NationalityJsonSerializer())), null);
for (Competitor competitor : raceColumn.getRaceDefinition(fleet).getCompetitors()) {
result.add(serializer.serialize(competitor));
@@ -90,7 +90,7 @@ public class RaceGroupJsonExportServlet extends AbstractJsonHttpServlet {
private static JsonSerializer<RaceLog> createRaceLogSerializer() {
return new RaceLogSerializer(RaceLogEventSerializer.create(new CompetitorJsonSerializer(new TeamJsonSerializer(
new PersonJsonSerializer(new NationalityJsonSerializer())))));
new PersonJsonSerializer(new NationalityJsonSerializer())), null)));
}
}
@@ -25,7 +25,8 @@ Require-Bundle: com.sap.sailing.domain,
com.sap.sailing.domain.common,
com.sap.sailing.udpconnector,
com.sap.sailing.operationaltransformation,
com.sap.sailing.domain.shared.android;bundle-version="1.0.0"
com.sap.sailing.domain.shared.android;bundle-version="1.0.0",
com.sap.sailing.server.gateway.serialization;bundle-version="1.0.0"
Bundle-ClassPath: .
Export-Package: com.sap.sailing.server,
com.sap.sailing.server.impl;
@@ -19,6 +19,8 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Fleet;
@@ -27,6 +29,7 @@ import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.RegattaRegistry;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.common.RaceFetcher;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaFetcher;
@@ -61,6 +64,7 @@ import com.sap.sailing.domain.tractracadapter.DomainFactory;
import com.sap.sailing.domain.tractracadapter.RaceRecord;
import com.sap.sailing.domain.tractracadapter.TracTracRaceTracker;
import com.sap.sailing.expeditionconnector.ExpeditionListener;
import com.sap.sailing.server.operationaltransformation.CreatePersistentCompetitor;
/**
* An OSGi service that can be used to track boat races using a TracTrac connector that pushes
@@ -553,4 +557,20 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
CourseArea addCourseAreaWithoutReplication(UUID eventId, UUID courseAreaId, String courseAreaName);
/**
* Creates a persistent competitor, that can then be used for smartphone tracking, as it will be available on
* all servers, even after restarting them.
*
* To replicate, use {@link CreatePersistentCompetitor}.
* @param id
* @param name
* @param team
* @param boat
* @return
*/
Competitor createPersistentCompetitor(Serializable id, String name, Team team, Boat boat);
public boolean isCompetitorPersistent(Competitor competitor);
public Collection<Competitor> getPersistentCompetitors();
}
@@ -6,6 +6,7 @@ import com.sap.sailing.operationaltransformation.Operation;
import com.sap.sailing.operationaltransformation.Transformer;
import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreatePersistentCompetitor;
import com.sap.sailing.server.operationaltransformation.CreateRegattaLeaderboard;
import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnDown;
import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnUp;
@@ -80,4 +81,8 @@ public interface RacingEventServiceOperation<ResultType> extends Operation<Racin
RacingEventServiceOperation<?> transformMoveLeaderboardColumnUpClientOp(MoveLeaderboardColumnUp moveLeaderboardColumnUp);
RacingEventServiceOperation<?> transformMoveLeaderboardColumnUpServerOp(MoveLeaderboardColumnUp moveLeaderboardColumnUp);
RacingEventServiceOperation<?> transformCreatePersistentCompetitorClientOp(CreatePersistentCompetitor createPersistentCompetitor);
RacingEventServiceOperation<?> transformCreatePersistentCompetitorServerOp(CreatePersistentCompetitor createPersistentCompetitor);
}
@@ -31,6 +31,7 @@ import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.CourseArea;
@@ -44,6 +45,7 @@ import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.RegattaListener;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.EventImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
@@ -192,6 +194,8 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
private final ConcurrentHashMap<String, LeaderboardGroup> leaderboardGroupsByName;
private final ConcurrentHashMap<Serializable, Competitor> persistentCompetitorCache;
private Set<DynamicTrackedRegatta> regattasObservedForDefaultLeaderboard = new HashSet<DynamicTrackedRegatta>();
private final MongoObjectFactory mongoObjectFactory;
@@ -263,6 +267,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
operationExecutionListeners = new ConcurrentHashMap<OperationExecutionListener, OperationExecutionListener>();
courseListeners = new ConcurrentHashMap<RaceDefinition, CourseChangeReplicator>();
persistentRegattasForRaceIDs = new ConcurrentHashMap<String, Regatta>();
persistentCompetitorCache = new ConcurrentHashMap<>();
delayToLiveInMillis = TrackedRace.DEFAULT_LIVE_DELAY_IN_MILLISECONDS;
this.raceLogReplicator = new RaceLogReplicator(this);
this.raceLogScoringReplicator = new RaceLogScoringReplicator(this);
@@ -277,10 +282,11 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
loadStoredRegattas();
loadRaceIDToRegattaAssociations();
loadStoredLeaderboardsAndGroups();
loadStoredCompetitors();
loadMediaLibary();
}
public RacingEventServiceImpl(MongoDBService mongoDBService) {
public RacingEventServiceImpl(MongoDBService mongoDBService) {
this(MongoFactory.INSTANCE.getDomainObjectFactory(mongoDBService), MongoFactory.INSTANCE
.getMongoObjectFactory(mongoDBService), MediaDBFactory.INSTANCE.getMediaDB(mongoDBService));
}
@@ -344,6 +350,12 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
}
}
private void loadStoredCompetitors() {
for (Competitor c : domainObjectFactory.loadAllCompetitors()) {
registerCompetitorAsPersistent(c);
}
}
@Override
public void addLeaderboard(Leaderboard leaderboard) {
synchronized (leaderboardsByName) {
@@ -1746,6 +1758,13 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
logoutput.append(String.format("%3s\n", lg.toString()));
}
logger.info("Serializing persisted competitors...");
oos.writeObject(persistentCompetitorCache);
logoutput.append("Serialized " + persistentCompetitorCache.size() + " persisted competitors\n");
for (Competitor c : persistentCompetitorCache.values()) {
logoutput.append(String.format("%3s\n", c.toString()));
}
logger.info(logoutput.toString());
}
@@ -1828,6 +1847,20 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
logoutput.append(String.format("%3s\n", mediatrack.toString()));
}
mediaLibrary.deserialize(ois);
logoutput.append("Received " + mediaLibrary.allTracks().size() + " NEW media tracks\n");
for (MediaTrack mediatrack : mediaLibrary.allTracks()) {
logoutput.append(String.format("%3s\n", mediatrack.toString()));
}
persistentCompetitorCache.putAll((Map<Serializable, Competitor>) ois.readObject());
logoutput.append("\nReceived " + persistentCompetitorCache.size() + " NEW competitors\n");
for (Competitor competitor : persistentCompetitorCache.values()) {
registerCompetitorAsPersistent(competitor);
logoutput.append(String.format("%3s\n", competitor.toString()));
}
logger.info(logoutput.toString());
logger.info("Done with initial replication on " + this);
} finally {
@@ -2073,4 +2106,26 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
}
}
private void registerCompetitorAsPersistent(Competitor competitor) {
persistentCompetitorCache.put(competitor.getId(), competitor);
}
@Override
public Competitor createPersistentCompetitor(Serializable id, String name,
Team team, Boat boat) {
Competitor c = getBaseDomainFactory().getOrCreateCompetitor(id, name, team, boat);
registerCompetitorAsPersistent(c);
return c;
}
@Override
public Collection<Competitor> getPersistentCompetitors() {
return persistentCompetitorCache.values();
}
@Override
public boolean isCompetitorPersistent(Competitor competitor) {
return persistentCompetitorCache.containsKey(competitor.getId());
}
}
@@ -125,6 +125,17 @@ public abstract class AbstractRacingEventServiceOperation<ResultType> implements
return moveLeaderboardColumnUp;
}
@Override
public RacingEventServiceOperation<?> transformCreatePersistentCompetitorClientOp(
CreatePersistentCompetitor createPersistentCompetitor) {
return createPersistentCompetitor;
}
@Override
public RacingEventServiceOperation<?> transformCreatePersistentCompetitorServerOp(
CreatePersistentCompetitor createPersistentCompetitor) {
return createPersistentCompetitor;
}
public static RacingEventServiceOperation<Void> getNoOp() {
return new AbstractRacingEventServiceOperation<Void>() {
private static final long serialVersionUID = -7203280393485688834L;
@@ -0,0 +1,47 @@
package com.sap.sailing.server.operationaltransformation;
import java.io.Serializable;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class CreatePersistentCompetitor extends
AbstractRacingEventServiceOperation<Competitor> {
private static final long serialVersionUID = 1538753300467120249L;
// private static final Logger logger =
// Logger.getLogger(CreatePersistentCompetitor.class.getName());
private final Serializable id;
private final String name;
private final Team team;
private final Boat boat;
public CreatePersistentCompetitor(Serializable id, String name, Team team,
Boat boat) {
this.id = id;
this.name = name;
this.team = team;
this.boat = boat;
}
@Override
public Competitor internalApplyTo(RacingEventService toState) {
return toState.createPersistentCompetitor(id, name, team, boat);
}
@Override
public RacingEventServiceOperation<?> transformClientOp(
RacingEventServiceOperation<?> serverOp) {
return serverOp.transformCreatePersistentCompetitorClientOp(this);
}
@Override
public RacingEventServiceOperation<?> transformServerOp(
RacingEventServiceOperation<?> clientOp) {
return clientOp.transformCreatePersistentCompetitorServerOp(this);
}
}