Merge branch 'master' into search

Conflicts:
	java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java
	java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/racelog/tracking/impl/MongoGPSFixStoreImpl.java
	java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java
	java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java
	java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/servlet/RecordFixesPostServlet.java
	java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesImportServlet.java
This commit is contained in:
Axel Uhl committed 2014-06-03 01:10:25 +02:00
commit 2157f02c5b
28 files changed
+512 -281

No files matched your search

@@ -9,7 +9,7 @@ import java.util.Iterator;
import com.sap.sailing.domain.deckmanadapter.DeckmanAdapter;
import com.sap.sailing.domain.deckmanadapter.Record;
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifierImpl;
import com.sap.sailing.domain.trackimport.FormatNotSupportedException;
import com.sap.sailing.domain.trackimport.GPSFixImporter;
@@ -21,7 +21,7 @@ public class DeckmanGPSFixImporter implements GPSFixImporter {
public void importFixes(InputStream inputStream, Callback callback, boolean inferSpeedAndBearing, String sourceName)
throws FormatNotSupportedException, IOException {
DeckmanAdapter deckmanAdapter = DeckmanAdapterFactoryImpl.INSTANCE.createDeckmanAdapter();
DeviceIdentifier device = new TrackFileImportDeviceIdentifierImpl(sourceName, getType() + "@" + new Date());
TrackFileImportDeviceIdentifier device = new TrackFileImportDeviceIdentifierImpl(sourceName, getType() + "@" + new Date());
try {
for (Iterator<Record> i = deckmanAdapter.parseLogFile(new InputStreamReader(inputStream)); i.hasNext();) {
Record record = i.next();
@@ -82,4 +82,9 @@ public enum CollectionNames {
* Stores {@link GPSFix}es
*/
GPS_FIXES,
/**
* Metadata for the GPSFixes, grouped by Device Identifier.
*/
GPS_FIXES_METADATA,
}
@@ -71,6 +71,7 @@ import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.TimeRange;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType;
@@ -79,6 +80,7 @@ import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.RGBColor;
import com.sap.sailing.domain.common.impl.TimeRangeImpl;
import com.sap.sailing.domain.common.impl.WindSourceImpl;
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
import com.sap.sailing.domain.common.racelog.Flags;
@@ -164,26 +166,26 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
private RaceLogEventRestoreFactory raceLogEventFactory;
private final DomainFactory baseDomainFactory;
private final TypeBasedServiceFinder<DeviceIdentifierMongoHandler> deviceIdentifierServiceFinder;
private final TypeBasedServiceFinderFactory serviceFinderFactory;
private final TypeBasedServiceFinder<DeviceIdentifierMongoHandler> deviceIdentifierServiceFinder;
private final TypeBasedServiceFinderFactory serviceFinderFactory;
/**
* Uses <code>null</code> as the {@link TypeBasedServiceFinder}, meaning that no {@link DeviceIdentifier}s can be loaded
* using this instance of a {@link DomainObjectFactory}.
*/
/**
* Uses <code>null</code> as the {@link TypeBasedServiceFinder}, meaning that no {@link DeviceIdentifier}s can be loaded
* using this instance of a {@link DomainObjectFactory}.
*/
public DomainObjectFactoryImpl(DB db, DomainFactory baseDomainFactory) {
this(db, baseDomainFactory, /* deviceTypeServiceFinder */ null);
}
public DomainObjectFactoryImpl(DB db, DomainFactory baseDomainFactory, TypeBasedServiceFinderFactory serviceFinderFactory) {
this(db, baseDomainFactory, /* deviceTypeServiceFinder */ null);
}
public DomainObjectFactoryImpl(DB db, DomainFactory baseDomainFactory, TypeBasedServiceFinderFactory serviceFinderFactory) {
super();
this.serviceFinderFactory = serviceFinderFactory;
if (serviceFinderFactory != null) {
this.deviceIdentifierServiceFinder = serviceFinderFactory.createServiceFinder(DeviceIdentifierMongoHandler.class);
this.deviceIdentifierServiceFinder.setFallbackService(new PlaceHolderDeviceIdentifierMongoHandler());
} else {
this.deviceIdentifierServiceFinder = null;
}
this.serviceFinderFactory = serviceFinderFactory;
if (serviceFinderFactory != null) {
this.deviceIdentifierServiceFinder = serviceFinderFactory.createServiceFinder(DeviceIdentifierMongoHandler.class);
this.deviceIdentifierServiceFinder.setFallbackService(new PlaceHolderDeviceIdentifierMongoHandler());
} else {
this.deviceIdentifierServiceFinder = null;
}
this.baseDomainFactory = baseDomainFactory;
this.competitorDeserializer = CompetitorJsonDeserializer.create(baseDomainFactory);
this.database = db;
@@ -199,7 +201,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
return new WindImpl(loadPosition(object), loadTimePoint(object), loadSpeedWithBearing(object));
}
public Position loadPosition(DBObject object) {
public Position loadPosition(DBObject object) {
Number latNumber = (Number) object.get(FieldNames.LAT_DEG.name());
Double lat = latNumber == null ? null : latNumber.doubleValue();
Number lngNumber = (Number) object.get(FieldNames.LNG_DEG.name());
@@ -211,27 +213,36 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
}
public static TimePoint loadTimePoint(DBObject object, String fieldName) {
public static TimePoint loadTimePoint(DBObject object, String fieldName) {
TimePoint result = null;
Number timePointAsNumber = (Number) object.get(fieldName);
Number timePointAsNumber = (Number) object.get(fieldName);
if (timePointAsNumber != null) {
result = new MillisecondsTimePoint(timePointAsNumber.longValue());
}
return result;
}
public static TimePoint loadTimePoint(DBObject object, FieldNames field) {
return loadTimePoint(object, field.name());
}
public static TimePoint loadTimePoint(DBObject object, FieldNames field) {
return loadTimePoint(object, field.name());
}
public static TimeRange loadTimeRange(DBObject object, FieldNames field) {
DBObject timeRangeObj = (DBObject) object.get(field.name());
if (timeRangeObj == null) {
return null;
}
TimePoint from = loadTimePoint(timeRangeObj, FieldNames.FROM_MILLIS);
TimePoint to = loadTimePoint(timeRangeObj, FieldNames.TO_MILLIS);
return new TimeRangeImpl(from, to);
}
/**
* Loads a {@link TimePoint} on the given object at {@link FieldNames#TIME_AS_MILLIS}.
*/
public TimePoint loadTimePoint(DBObject object) {
public TimePoint loadTimePoint(DBObject object) {
return loadTimePoint(object, FieldNames.TIME_AS_MILLIS);
}
public SpeedWithBearing loadSpeedWithBearing(DBObject object) {
public SpeedWithBearing loadSpeedWithBearing(DBObject object) {
return new KnotSpeedWithBearingImpl(((Number) object.get(FieldNames.KNOT_SPEED.name())).doubleValue(),
new DegreeBearingImpl(((Number) object.get(FieldNames.DEGREE_BEARING.name())).doubleValue()));
}
@@ -1058,7 +1069,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
BasicDBList dbSeries = (BasicDBList) dbRegatta.get(FieldNames.REGATTA_SERIES.name());
Iterable<Series> series = loadSeries(dbSeries, trackedRegattaRegistry);
RaceLogStore raceLogStore = MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(
new MongoObjectFactoryImpl(database, serviceFinderFactory),
new MongoObjectFactoryImpl(database, serviceFinderFactory),
this);
Serializable courseAreaId = (Serializable) dbRegatta.get(FieldNames.COURSE_AREA_ID.name());
@@ -1221,7 +1232,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
List<RaceLogEvent> eventsToMigrate = loadRaceLogEvents(result, query);
if (!eventsToMigrate.isEmpty()) {
// ... migrate them...
MongoRaceLogStoreVisitor storeVisitor = new MongoRaceLogStoreVisitor(identifier, new MongoObjectFactoryImpl(database, serviceFinderFactory));
MongoRaceLogStoreVisitor storeVisitor = new MongoRaceLogStoreVisitor(identifier, new MongoObjectFactoryImpl(database, serviceFinderFactory));
for (RaceLogEvent event : eventsToMigrate) {
event.accept(storeVisitor);
}
@@ -1296,22 +1307,22 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
return loadRaceLogRaceLogProtestStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RaceLogWindFixEvent.class.getSimpleName())) {
return loadRaceLogRaceLogWindFixEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(DeviceCompetitorMappingEvent.class.getSimpleName())) {
return loadRaceLogDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(DeviceMarkMappingEvent.class.getSimpleName())) {
return loadRaceLogDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(DenoteForTrackingEvent.class.getSimpleName())) {
return loadRaceLogDenoteForTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(StartTrackingEvent.class.getSimpleName())) {
return loadRaceLogStartEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RevokeEvent.class.getSimpleName())) {
return loadRaceLogRevokeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RegisterCompetitorEvent.class.getSimpleName())) {
return loadRaceLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(DefineMarkEvent.class.getSimpleName())) {
return loadRaceLogDefineMarkEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(CloseOpenEndedDeviceMappingEvent.class.getSimpleName())) {
return loadRaceLogCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(DeviceCompetitorMappingEvent.class.getSimpleName())) {
return loadRaceLogDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(DeviceMarkMappingEvent.class.getSimpleName())) {
return loadRaceLogDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(DenoteForTrackingEvent.class.getSimpleName())) {
return loadRaceLogDenoteForTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(StartTrackingEvent.class.getSimpleName())) {
return loadRaceLogStartEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RevokeEvent.class.getSimpleName())) {
return loadRaceLogRevokeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(RegisterCompetitorEvent.class.getSimpleName())) {
return loadRaceLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(DefineMarkEvent.class.getSimpleName())) {
return loadRaceLogDefineMarkEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
} else if (eventClass.equals(CloseOpenEndedDeviceMappingEvent.class.getSimpleName())) {
return loadRaceLogCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject);
}
throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass));
@@ -1323,80 +1334,80 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
return raceLogEventFactory.createWindFixEvent(createdAt, author, logicalTimePoint, id, competitors, passId, wind);
}
private RaceLogEvent loadRaceLogDeviceCompetitorMappingEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
DeviceIdentifier device = null;
try {
device = loadDeviceId(deviceIdentifierServiceFinder,
(DBObject) dbObject.get(FieldNames.DEVICE_ID.name()));
} catch (Exception e) {
logger.log(Level.WARNING, "Could not load deviceId for RaceLogEvent", e);
e.printStackTrace();
}
Competitor mappedTo = baseDomainFactory.getExistingCompetitorById(
(Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name()));
TimePoint from = loadTimePoint(dbObject, FieldNames.RACE_LOG_FROM);
TimePoint to = loadTimePoint(dbObject, FieldNames.RACE_LOG_TO);
return raceLogEventFactory.createDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, device, mappedTo, passId, from, to);
}
private RaceLogEvent loadRaceLogDeviceMarkMappingEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
DeviceIdentifier device = null;
try {
device = loadDeviceId(deviceIdentifierServiceFinder,
(DBObject) dbObject.get(FieldNames.DEVICE_ID.name()));
} catch (Exception e) {
logger.log(Level.WARNING, "Could not load deviceId for RaceLogEvent", e);
e.printStackTrace();
}
Mark mappedTo = baseDomainFactory.getOrCreateMark(
(Serializable) dbObject.get(FieldNames.MARK_ID.name()), null);
TimePoint from = loadTimePoint(dbObject, FieldNames.RACE_LOG_FROM);
TimePoint to = loadTimePoint(dbObject, FieldNames.RACE_LOG_TO);
return raceLogEventFactory.createDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, device, mappedTo, passId, from, to);
}
private RaceLogEvent loadRaceLogDenoteForTrackingEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
String raceName = (String) dbObject.get(FieldNames.RACE_NAME.name());
BoatClass boatClass = baseDomainFactory.getOrCreateBoatClass((String) dbObject.get(FieldNames.BOAT_CLASS_NAME.name()));
Serializable raceId = (Serializable) dbObject.get(FieldNames.RACE_ID.name());
return raceLogEventFactory.createDenoteForTrackingEvent(createdAt, author, logicalTimePoint, id, passId, raceName, boatClass, raceId);
}
private RaceLogEvent loadRaceLogStartEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
return raceLogEventFactory.createStartTrackingEvent(createdAt, author, logicalTimePoint, id, passId);
}
private RaceLogEvent loadRaceLogRevokeEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
Serializable revokedEventId = Helpers.tryUuidConversion(
(Serializable) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_ID.name()));
return raceLogEventFactory.createRevokeEvent(createdAt, author, logicalTimePoint, id, passId, revokedEventId);
}
private RaceLogEvent loadRaceLogRegisterCompetitorEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
assert competitors.size() == 1 : "Should have exactly one competitor for RegisterCompetitorEvent";
return raceLogEventFactory.createRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors.get(0));
}
private RaceLogEvent loadRaceLogDefineMarkEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
Mark mark = loadMark((DBObject) dbObject.get(FieldNames.RACE_LOG_MARK.name()));
return raceLogEventFactory.createDefineMarkEvent(createdAt, author, logicalTimePoint, id, passId, mark);
}
private RaceLogEvent loadRaceLogCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
Serializable deviceMappingEventId = Helpers.tryUuidConversion((Serializable) dbObject.get(FieldNames.RACE_LOG_DEVICE_MAPPING_EVENT_ID.name()));
TimePoint closingTimePoint = loadTimePoint(dbObject, FieldNames.RACE_LOG_CLOSING_TIMEPOINT);
return raceLogEventFactory.createCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, passId,
deviceMappingEventId, closingTimePoint);
}
private RaceLogEvent loadRaceLogDeviceCompetitorMappingEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
DeviceIdentifier device = null;
try {
device = loadDeviceId(deviceIdentifierServiceFinder,
(DBObject) dbObject.get(FieldNames.DEVICE_ID.name()));
} catch (Exception e) {
logger.log(Level.WARNING, "Could not load deviceId for RaceLogEvent", e);
e.printStackTrace();
}
Competitor mappedTo = baseDomainFactory.getExistingCompetitorById(
(Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name()));
TimePoint from = loadTimePoint(dbObject, FieldNames.RACE_LOG_FROM);
TimePoint to = loadTimePoint(dbObject, FieldNames.RACE_LOG_TO);
return raceLogEventFactory.createDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, device, mappedTo, passId, from, to);
}
private RaceLogEvent loadRaceLogDeviceMarkMappingEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
DeviceIdentifier device = null;
try {
device = loadDeviceId(deviceIdentifierServiceFinder,
(DBObject) dbObject.get(FieldNames.DEVICE_ID.name()));
} catch (Exception e) {
logger.log(Level.WARNING, "Could not load deviceId for RaceLogEvent", e);
e.printStackTrace();
}
Mark mappedTo = baseDomainFactory.getOrCreateMark(
(Serializable) dbObject.get(FieldNames.MARK_ID.name()), null);
TimePoint from = loadTimePoint(dbObject, FieldNames.RACE_LOG_FROM);
TimePoint to = loadTimePoint(dbObject, FieldNames.RACE_LOG_TO);
return raceLogEventFactory.createDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, device, mappedTo, passId, from, to);
}
private RaceLogEvent loadRaceLogDenoteForTrackingEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
String raceName = (String) dbObject.get(FieldNames.RACE_NAME.name());
BoatClass boatClass = baseDomainFactory.getOrCreateBoatClass((String) dbObject.get(FieldNames.BOAT_CLASS_NAME.name()));
Serializable raceId = (Serializable) dbObject.get(FieldNames.RACE_ID.name());
return raceLogEventFactory.createDenoteForTrackingEvent(createdAt, author, logicalTimePoint, id, passId, raceName, boatClass, raceId);
}
private RaceLogEvent loadRaceLogStartEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
return raceLogEventFactory.createStartTrackingEvent(createdAt, author, logicalTimePoint, id, passId);
}
private RaceLogEvent loadRaceLogRevokeEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
Serializable revokedEventId = Helpers.tryUuidConversion(
(Serializable) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_ID.name()));
return raceLogEventFactory.createRevokeEvent(createdAt, author, logicalTimePoint, id, passId, revokedEventId);
}
private RaceLogEvent loadRaceLogRegisterCompetitorEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
assert competitors.size() == 1 : "Should have exactly one competitor for RegisterCompetitorEvent";
return raceLogEventFactory.createRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors.get(0));
}
private RaceLogEvent loadRaceLogDefineMarkEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
Mark mark = loadMark((DBObject) dbObject.get(FieldNames.RACE_LOG_MARK.name()));
return raceLogEventFactory.createDefineMarkEvent(createdAt, author, logicalTimePoint, id, passId, mark);
}
private RaceLogEvent loadRaceLogCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint,
Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
Serializable deviceMappingEventId = Helpers.tryUuidConversion((Serializable) dbObject.get(FieldNames.RACE_LOG_DEVICE_MAPPING_EVENT_ID.name()));
TimePoint closingTimePoint = loadTimePoint(dbObject, FieldNames.RACE_LOG_CLOSING_TIMEPOINT);
return raceLogEventFactory.createCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, passId,
deviceMappingEventId, closingTimePoint);
}
private RaceLogEvent loadRaceLogRaceLogProtestStartTimeEvent(TimePoint createdAt, RaceLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
TimePoint protestStartTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_START_TIME);
@@ -1705,19 +1716,19 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
return configuration;
}
private DeviceIdentifier loadDeviceId(
TypeBasedServiceFinder<DeviceIdentifierMongoHandler> deviceIdentifierServiceFinder, DBObject deviceId)
throws TransformationException, NoCorrespondingServiceRegisteredException {
String deviceType = (String) deviceId.get(FieldNames.DEVICE_TYPE.name());
Object deviceTypeId = deviceId.get(FieldNames.DEVICE_TYPE_SPECIFIC_ID.name());
String stringRepresentation = (String) deviceId.get(FieldNames.DEVICE_STRING_REPRESENTATION.name());
try {
return deviceIdentifierServiceFinder.findService(deviceType).deserialize(deviceTypeId, deviceType, stringRepresentation);
} catch (TransformationException e) {
return new PlaceHolderDeviceIdentifierSerializationHandler().deserialize(
stringRepresentation, deviceType, stringRepresentation);
}
}
private DeviceIdentifier loadDeviceId(
TypeBasedServiceFinder<DeviceIdentifierMongoHandler> deviceIdentifierServiceFinder, DBObject deviceId)
throws TransformationException, NoCorrespondingServiceRegisteredException {
String deviceType = (String) deviceId.get(FieldNames.DEVICE_TYPE.name());
Object deviceTypeId = deviceId.get(FieldNames.DEVICE_TYPE_SPECIFIC_ID.name());
String stringRepresentation = (String) deviceId.get(FieldNames.DEVICE_STRING_REPRESENTATION.name());
try {
return deviceIdentifierServiceFinder.findService(deviceType).deserialize(deviceTypeId, deviceType, stringRepresentation);
} catch (TransformationException e) {
return new PlaceHolderDeviceIdentifierSerializationHandler().deserialize(
stringRepresentation, deviceType, stringRepresentation);
}
}
}
@@ -98,4 +98,10 @@ public enum FieldNames {
// GPSFixes
DEVICE_TYPE_SPECIFIC_ID, DEVICE_ID, DEVICE_TYPE, GPSFIX_TYPE, GPSFIX, DEVICE_STRING_REPRESENTATION,
// GPSFixes metadata
TIMERANGE, NUM_FIXES,
// Timespan
FROM_MILLIS, TO_MILLIS,
}
@@ -47,6 +47,7 @@ import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.Speed;
import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.TimeRange;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WithID;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
@@ -147,6 +148,15 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
public static void storeTimePoint(TimePoint timePoint, DBObject result, FieldNames field) {
storeTimePoint(timePoint, result, field.name());
}
public static void storeTimeRange(TimeRange timeRange, DBObject result, FieldNames field) {
if (timeRange != null) {
DBObject timeRangeObj = new BasicDBObject();
storeTimePoint(timeRange.from(), timeRangeObj, FieldNames.FROM_MILLIS);
storeTimePoint(timeRange.to(), timeRangeObj, FieldNames.TO_MILLIS);
result.put(field.name(), timeRangeObj);
}
}
public void storeTimed(Timed timed, DBObject result) {
@@ -192,8 +202,17 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
DBCollection gpsFixCollection = database.getCollection(CollectionNames.GPS_FIXES.name());
DBObject index = new BasicDBObject();
index.put(FieldNames.DEVICE_ID.name(), null);
index.put(FieldNames.TIME_AS_MILLIS.name(), null);
index.put(FieldNames.TIME_AS_MILLIS.name(), null);
gpsFixCollection.ensureIndex(index);
return gpsFixCollection;
}
public DBCollection getGPSFixMetadataCollection() {
DBCollection collection = database.getCollection(CollectionNames.GPS_FIXES_METADATA.name());
DBObject index = new BasicDBObject();
index.put(FieldNames.DEVICE_ID.name(), null);
collection.ensureIndex(index);
return collection;
}
/**
@@ -8,6 +8,7 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
@@ -16,12 +17,15 @@ import com.mongodb.QueryBuilder;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.TimeRange;
import com.sap.sailing.domain.common.impl.TimeRangeImpl;
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinder;
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinderFactory;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl;
import com.sap.sailing.domain.persistence.impl.FieldNames;
import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl;
import com.sap.sailing.domain.persistence.racelog.tracking.DeviceIdentifierMongoHandler;
@@ -38,11 +42,18 @@ import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sse.common.Util;
/**
* At the moment, the timerange covered by the fixes for a device, and the number of
* fixes for a device are stored in a metadata collection. Should be changed, see bug 1982.
* @author Fredrik Teschke
*
*/
public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
private static final Logger logger = Logger.getLogger(MongoGPSFixStore.class.getName());
private final TypeBasedServiceFinder<GPSFixMongoHandler> fixServiceFinder;
private final TypeBasedServiceFinder<DeviceIdentifierMongoHandler> deviceServiceFinder;
private final DBCollection collection;
private final DBCollection fixesCollection;
private final DBCollection metadataCollection;
private final MongoObjectFactoryImpl mongoOF;
private final Map<DeviceIdentifier, Set<GPSFixReceivedListener>> listeners = new HashMap<>();
@@ -56,7 +67,8 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
fixServiceFinder = null;
deviceServiceFinder = null;
}
collection = mongoOF.getGPSFixCollection();
fixesCollection = mongoOF.getGPSFixCollection();
metadataCollection = mongoOF.getGPSFixMetadataCollection();
}
private GPSFix loadGPSFix(DBObject object) throws TransformationException, NoCorrespondingServiceRegisteredException {
@@ -66,23 +78,18 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
}
private <FixT extends GPSFix> void loadTrack(DynamicGPSFixTrack<?, FixT> track, DeviceIdentifier device,
TimePoint from, TimePoint to, boolean inclusive) throws NoCorrespondingServiceRegisteredException {
TimePoint from, TimePoint to, boolean inclusive) throws NoCorrespondingServiceRegisteredException,
TransformationException {
long fromMillis = from.asMillis() - (inclusive ? 1 : 0);
long toMillis = to.asMillis() + (inclusive ? 1 : 0);
Object dbDeviceId = null;
try {
dbDeviceId = MongoObjectFactoryImpl.storeDeviceId(deviceServiceFinder, device);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not serialize Device ID for MongoDB: " + e.getMessage());
return;
}
Object dbDeviceId = MongoObjectFactoryImpl.storeDeviceId(deviceServiceFinder, device);
DBObject query = QueryBuilder.start(FieldNames.DEVICE_ID.name()).is(dbDeviceId)
.and(FieldNames.TIME_AS_MILLIS.name()).greaterThan(fromMillis)
.and(FieldNames.TIME_AS_MILLIS.name()).lessThan(toMillis).get();
DBCursor result = collection.find(query);
DBCursor result = fixesCollection.find(query);
for (DBObject fixObject : result) {
try {
@SuppressWarnings("unchecked")
@@ -98,7 +105,8 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
}
@Override
public void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, RaceLog raceLog, Competitor competitor) {
public void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, RaceLog raceLog, Competitor competitor)
throws NoCorrespondingServiceRegisteredException, TransformationException{
List<DeviceMapping<Competitor>> mappings = new DeviceCompetitorMappingFinder(raceLog).analyze().get(competitor);
if (mappings != null) {
@@ -109,7 +117,8 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
}
@Override
public void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, RaceLog raceLog, Mark mark) {
public void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, RaceLog raceLog, Mark mark)
throws NoCorrespondingServiceRegisteredException, TransformationException{
List<DeviceMapping<Mark>> mappings = new DeviceMarkMappingFinder(raceLog).analyze().get(mark);
if (mappings != null) {
@@ -129,7 +138,28 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
.add(FieldNames.GPSFIX_TYPE.name(), type).add(FieldNames.GPSFIX.name(), fixObject).get();
mongoOF.storeTimed(fix, entry);
collection.insert(entry);
fixesCollection.insert(entry);
TimeRange oldTimeRange = getTimeRangeCoveredByFixes(device);
long oldNumFixes = getNumberOfFixes(device);
DBObject newMetadata = new BasicDBObject();
newMetadata.put(FieldNames.DEVICE_ID.name(), MongoObjectFactoryImpl.storeDeviceId(deviceServiceFinder, device));
newMetadata.put(FieldNames.NUM_FIXES.name(), oldNumFixes + 1);
TimePoint newFrom = fix.getTimePoint();
TimePoint newTo = fix.getTimePoint();
if (oldTimeRange != null) {
if (oldTimeRange.from().before(newFrom)) {
newFrom = oldTimeRange.from();
}
if (oldTimeRange.to().after(newTo)) {
newTo = oldTimeRange.to();
}
}
MongoObjectFactoryImpl.storeTimeRange(new TimeRangeImpl(newFrom, newTo), newMetadata, FieldNames.TIMERANGE);
metadataCollection.update(getDeviceQuery(device), newMetadata, /*create if not existent*/ true,
/*update multiple*/ false);
} catch (TransformationException e) {
logger.log(Level.WARNING, "Could not store fix in MongoDB");
e.printStackTrace();
@@ -156,12 +186,47 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
}
@Override
public void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, DeviceMapping<Competitor> mapping) {
public void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, DeviceMapping<Competitor> mapping)
throws TransformationException, NoCorrespondingServiceRegisteredException {
loadTrack(track, mapping.getDevice(), mapping.getTimeRange().from(), mapping.getTimeRange().to(), true /*inclusive*/);
}
@Override
public void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, DeviceMapping<Mark> mapping) {
public void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, DeviceMapping<Mark> mapping)
throws TransformationException, NoCorrespondingServiceRegisteredException {
loadTrack(track, mapping.getDevice(), mapping.getTimeRange().from(), mapping.getTimeRange().to(), true /*inclusive*/);
}
private DBObject getDeviceQuery(DeviceIdentifier device)
throws TransformationException, NoCorrespondingServiceRegisteredException {
Object dbDeviceId = MongoObjectFactoryImpl.storeDeviceId(deviceServiceFinder, device);
DBObject query = QueryBuilder.start(FieldNames.DEVICE_ID.name()).is(dbDeviceId).get();
return query;
}
private DBObject findMetadataObject(DeviceIdentifier device)
throws TransformationException, NoCorrespondingServiceRegisteredException {
DBObject query = getDeviceQuery(device);
DBObject result = metadataCollection.findOne(query);
return result;
}
@Override
public TimeRange getTimeRangeCoveredByFixes(DeviceIdentifier device)
throws TransformationException, NoCorrespondingServiceRegisteredException {
DBObject result = findMetadataObject(device);
if (result == null) {
return null;
}
return DomainObjectFactoryImpl.loadTimeRange(result, FieldNames.TIMERANGE);
}
@Override
public long getNumberOfFixes(DeviceIdentifier device) throws TransformationException, NoCorrespondingServiceRegisteredException {
DBObject result = findMetadataObject(device);
if (result == null) {
return 0;
}
return ((Number) result.get(FieldNames.NUM_FIXES.name())).longValue();
}
}
@@ -62,6 +62,7 @@ public class AbstractGPSFixStoreTest {
public void after() {
MongoObjectFactoryImpl mongoOF = (MongoObjectFactoryImpl) service.getMongoObjectFactory();
mongoOF.getGPSFixCollection().drop();
mongoOF.getGPSFixMetadataCollection().drop();
}
protected void map(Competitor comp, DeviceIdentifier device, long from, long to) {
@@ -1,5 +1,7 @@
package com.sap.sailing.domain.racelogtracking.test.impl;
import static junit.framework.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collections;
@@ -18,6 +20,7 @@ import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.WaypointImpl;
import com.sap.sailing.domain.common.impl.TimeRangeImpl;
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
@@ -29,7 +32,7 @@ import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.domain.tracking.impl.TrackedRegattaImpl;
public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
@Test
@Ignore
public void areFixesStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException {
@@ -65,4 +68,18 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest {
testLength(trackedRace.getOrCreateTrack(mark), 1);
testLength(trackedRace.getOrCreateTrack(mark2), 1);
}
@Test
public void metadataStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException {
assertEquals(0, store.getNumberOfFixes(device));
assertEquals(null, store.getTimeRangeCoveredByFixes(device));
map(comp, device, 0, 600);
store.storeFix(device, createFix(100, 10, 20, 30, 40));
store.storeFix(device, createFix(200, 10, 20, 30, 40));
assertEquals(2, store.getNumberOfFixes(device));
assertEquals(TimeRangeImpl.create(100, 200), store.getTimeRangeCoveredByFixes(device));
}
}
@@ -31,9 +31,11 @@ import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
import com.sap.sailing.domain.common.WithID;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
import com.sap.sailing.domain.common.racelog.tracking.NotRevokableException;
import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState;
import com.sap.sailing.domain.common.racelog.tracking.RaceNotCreatedException;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent;
@@ -258,7 +260,11 @@ public class RaceLogRaceTracker extends BaseRaceLogEventVisitor implements RaceT
if (oldMappings != null) {
for (DeviceMapping<Mark> newMapping : newMappings.get(mark)) {
if (!hasMappingAlreadyBeenLoaded(newMapping, oldMappings)) {
gpsFixStore.loadMarkTrack(track, newMapping);
try {
gpsFixStore.loadMarkTrack(track, newMapping);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not load mark track " + newMapping.getMappedTo());
}
}
}
}
@@ -297,7 +303,11 @@ public class RaceLogRaceTracker extends BaseRaceLogEventVisitor implements RaceT
for (DeviceMapping<Competitor> newMapping : newMappings.get(competitor)) {
if (!hasMappingAlreadyBeenLoaded(newMapping, oldMappings)) {
gpsFixStore.loadCompetitorTrack(track, newMapping);
try {
gpsFixStore.loadCompetitorTrack(track, newMapping);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not load competitor track " + newMapping.getMappedTo());
}
}
}
}
@@ -25,11 +25,13 @@ import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException;
import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException;
import com.sap.sailing.domain.common.racelog.tracking.NotRevokableException;
import com.sap.sailing.domain.common.racelog.tracking.RaceLogRaceTrackerExistsException;
import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
@@ -250,7 +252,11 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
RaceLogEvent mapping = RaceLogEventFactory.INSTANCE.createDeviceMarkMappingEvent(time,
service.getServerAuthor(), device, mark, raceLog.getCurrentPassId(), time, time);
raceLog.add(mapping);
service.getGPSFixStore().storeFix(device, gpsFix);
try {
service.getGPSFixStore().storeFix(device, gpsFix);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not pint mark " + mark);
}
}
@Override
@@ -3,10 +3,13 @@ package com.sap.sailing.domain.racelogtracking.servlet;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinder;
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
import com.sap.sailing.domain.tracking.GPSFix;
@@ -55,7 +58,11 @@ public class RecordFixesPostServlet extends
List<GPSFix> fixes = domainObject.getC();
for (GPSFix fix : fixes) {
getService().getGPSFixStore().storeFix(device, fix);
try {
getService().getGPSFixStore().storeFix(device, fix);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not load store fix from device " + device);
}
}
return null;
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.racelog.tracking;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.common.TimeRange;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.GPSFix;
@@ -44,4 +45,14 @@ public enum EmptyGPSFixStore implements GPSFixStore {
DeviceMapping<Mark> mapping) {
}
@Override
public TimeRange getTimeRangeCoveredByFixes(DeviceIdentifier device) {
return null;
}
@Override
public long getNumberOfFixes(DeviceIdentifier device) {
return 0;
}
}
@@ -2,6 +2,9 @@ package com.sap.sailing.domain.racelog.tracking;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.common.TimeRange;
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.GPSFix;
@@ -13,24 +16,27 @@ public interface GPSFixStore {
* Load all fixes that correspond to the {@link DeviceCompetitorMappingEvent}s found in the {@code raceLog}.
*/
void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, RaceLog raceLog,
Competitor competitor);
Competitor competitor) throws TransformationException;
/**
* Load all fixes that correspond to the {@link DeviceMarkMappingEvent}s found in the {@code raceLog}.
*/
void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, RaceLog raceLog, Mark mark);
void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, RaceLog raceLog, Mark mark) throws TransformationException,
NoCorrespondingServiceRegisteredException;
/**
* Load all fixes that correspond to the {@code mapping}.
*/
void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, DeviceMapping<Competitor> mapping);
void loadCompetitorTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track, DeviceMapping<Competitor> mapping)
throws TransformationException, NoCorrespondingServiceRegisteredException;
/**
* Load all fixes that correspond to the {@code mapping}.
*/
void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, DeviceMapping<Mark> mapping);
void loadMarkTrack(DynamicGPSFixTrack<Mark, GPSFix> track, DeviceMapping<Mark> mapping) throws TransformationException,
NoCorrespondingServiceRegisteredException;
void storeFix(DeviceIdentifier device, GPSFix fix);
void storeFix(DeviceIdentifier device, GPSFix fix) throws TransformationException, NoCorrespondingServiceRegisteredException;
/**
* Listeners are notified, whenever a {@link GPSFix} submitted by the {@code device}
@@ -42,4 +48,9 @@ public interface GPSFixStore {
* Remove the registrations of the listener for all devices.
*/
void removeListener(GPSFixReceivedListener listener);
TimeRange getTimeRangeCoveredByFixes(DeviceIdentifier device) throws TransformationException,
NoCorrespondingServiceRegisteredException;
long getNumberOfFixes(DeviceIdentifier device) throws TransformationException, NoCorrespondingServiceRegisteredException;
}
@@ -5,6 +5,7 @@ import java.io.InputStream;
import java.util.Map;
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
import com.sap.sailing.domain.tracking.GPSFix;
/**
@@ -38,7 +39,7 @@ public interface GPSFixImporter {
*
*/
interface Callback {
void addFix(GPSFix fix, DeviceIdentifier device);
void addFix(GPSFix fix, TrackFileImportDeviceIdentifier device);
}
/**
@@ -72,6 +72,8 @@ import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.NauticalMileDistance;
import com.sap.sailing.domain.common.impl.WindSourceImpl;
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.confidence.ConfidenceBasedWindAverager;
import com.sap.sailing.domain.confidence.ConfidenceFactory;
import com.sap.sailing.domain.confidence.HasConfidence;
@@ -2473,15 +2475,23 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
try {
logger.info("Started loading competitor tracks for " + getRace().getName());
for (Competitor competitor : race.getCompetitors()) {
gpsFixStore.loadCompetitorTrack(
(DynamicGPSFixTrack<Competitor, GPSFixMoving>) tracks.get(competitor), raceLog,
competitor);
try {
gpsFixStore.loadCompetitorTrack(
(DynamicGPSFixTrack<Competitor, GPSFixMoving>) tracks.get(competitor), raceLog,
competitor);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not load track for " + competitor);
}
}
logger.info("Finished loading competitor tracks for " + getRace().getName());
logger.info("Started loading mark tracks for " + getRace().getName());
for (Mark mark : getMarks()) {
gpsFixStore.loadMarkTrack((DynamicGPSFixTrack<Mark, GPSFix>) markTracks.get(mark), raceLog,
mark);
try {
gpsFixStore.loadMarkTrack((DynamicGPSFixTrack<Mark, GPSFix>) markTracks.get(mark), raceLog,
mark);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not load track for " + mark);
}
}
logger.info("Finished loading mark tracks for " + getRace().getName());
@@ -15,13 +15,13 @@ import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.gwt.ui.adminconsole.TrackFileImportDeviceIdentifierTableWrapper.TrackFileImportDeviceIdentifier;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO;
import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO;
import com.sap.sailing.gwt.ui.shared.MarkDTO;
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
public class ImportFixesAndAddMappingsDialog extends DataEntryDialog<Collection<DeviceMappingDTO>> {
@@ -31,9 +31,9 @@ public class ImportFixesAndAddMappingsDialog extends DataEntryDialog<Collection<
private final MarkTableWrapper<SingleSelectionModel<MarkDTO>> markTable;
private final StringMessages stringMessages;
private final Map<TrackFileImportDeviceIdentifier, Serializable> mappings = new HashMap<>();
private final Map<TrackFileImportDeviceIdentifierDTO, Serializable> mappings = new HashMap<>();
private TrackFileImportDeviceIdentifier deviceToSelect;
private TrackFileImportDeviceIdentifierDTO deviceToSelect;
private CompetitorDTO compToSelect;
private MarkDTO markToSelect;
private boolean inInstableTransitionState = false;
@@ -132,7 +132,7 @@ public class ImportFixesAndAddMappingsDialog extends DataEntryDialog<Collection<
private void mappedToSelectionChanged(Serializable mappedTo) {
if (! inInstableTransitionState) {
TrackFileImportDeviceIdentifier device = deviceIdTable.getSelectionModel().getSelectedObject();
TrackFileImportDeviceIdentifierDTO device = deviceIdTable.getSelectionModel().getSelectedObject();
if (device != null) {
mappings.put(device, mappedTo);
}
@@ -148,7 +148,7 @@ public class ImportFixesAndAddMappingsDialog extends DataEntryDialog<Collection<
select();
}
private void deviceSelectionChanged(TrackFileImportDeviceIdentifier deviceId) {
private void deviceSelectionChanged(TrackFileImportDeviceIdentifierDTO deviceId) {
if (! inInstableTransitionState) {
deviceToSelect = deviceId;
compToSelect = null;
@@ -190,8 +190,8 @@ public class ImportFixesAndAddMappingsDialog extends DataEntryDialog<Collection<
@Override
protected Collection<DeviceMappingDTO> getResult() {
List<DeviceMappingDTO> result = new ArrayList<>();
for (TrackFileImportDeviceIdentifier device : mappings.keySet()) {
DeviceIdentifierDTO deviceIdDto = new DeviceIdentifierDTO("FILE", device.uuid);
for (TrackFileImportDeviceIdentifierDTO device : mappings.keySet()) {
DeviceIdentifierDTO deviceIdDto = new DeviceIdentifierDTO("FILE", device.uuidAsString);
Serializable mappedTo = mappings.get(device);
DeviceMappingDTO mapping = new DeviceMappingDTO(deviceIdDto, device.from, device.to,
mappedTo, null);
@@ -1,77 +1,68 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.Date;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.view.client.SingleSelectionModel;
import com.sap.sailing.gwt.ui.adminconsole.TrackFileImportDeviceIdentifierTableWrapper.TrackFileImportDeviceIdentifier;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
public class TrackFileImportDeviceIdentifierTableWrapper extends TableWrapper<TrackFileImportDeviceIdentifier, SingleSelectionModel<TrackFileImportDeviceIdentifier>> {
public static class TrackFileImportDeviceIdentifier {
public String uuid;
public String fileName;
public String trackName;
public Date from;
public Date to;
public long numberOfFixes;
public TrackFileImportDeviceIdentifier(String uuid, String fileName, String trackName, Date from, Date to, long numberOfFixes) {
this.fileName = fileName;
this.trackName = trackName;
this.from = from;
this.to = to;
this.numberOfFixes = numberOfFixes;
this.uuid = uuid;
}
}
public class TrackFileImportDeviceIdentifierTableWrapper extends TableWrapper<TrackFileImportDeviceIdentifierDTO,
SingleSelectionModel<TrackFileImportDeviceIdentifierDTO>> {
public TrackFileImportDeviceIdentifierTableWrapper(SailingServiceAsync sailingService, StringMessages stringMessages,
ErrorReporter errorReporter) {
super(sailingService, stringMessages, errorReporter, new SingleSelectionModel<TrackFileImportDeviceIdentifier>());
super(sailingService, stringMessages, errorReporter, new SingleSelectionModel<TrackFileImportDeviceIdentifierDTO>());
TextColumn<TrackFileImportDeviceIdentifier> fileNameColumn = new TextColumn<TrackFileImportDeviceIdentifier>() {
TextColumn<TrackFileImportDeviceIdentifierDTO> uuidColumn = new TextColumn<TrackFileImportDeviceIdentifierDTO>() {
@Override
public String getValue(TrackFileImportDeviceIdentifier object) {
public String getValue(TrackFileImportDeviceIdentifierDTO object) {
return object.uuidAsString;
}
};
TextColumn<TrackFileImportDeviceIdentifierDTO> fileNameColumn = new TextColumn<TrackFileImportDeviceIdentifierDTO>() {
@Override
public String getValue(TrackFileImportDeviceIdentifierDTO object) {
return object.fileName;
}
};
TextColumn<TrackFileImportDeviceIdentifier> trackNameColumn = new TextColumn<TrackFileImportDeviceIdentifier>() {
TextColumn<TrackFileImportDeviceIdentifierDTO> trackNameColumn = new TextColumn<TrackFileImportDeviceIdentifierDTO>() {
@Override
public String getValue(TrackFileImportDeviceIdentifier object) {
public String getValue(TrackFileImportDeviceIdentifierDTO object) {
return object.trackName;
}
};
// TextColumn<TrackFileImportDeviceIdentifier> fromColumn = new TextColumn<TrackFileImportDeviceIdentifier>() {
// @Override
// public String getValue(TrackFileImportDeviceIdentifier object) {
// return DateAndTimeFormatterUtil.formatDateAndTime(object.from);
// }
// };
//
// TextColumn<TrackFileImportDeviceIdentifier> toColumn = new TextColumn<TrackFileImportDeviceIdentifier>() {
// @Override
// public String getValue(TrackFileImportDeviceIdentifier object) {
// return DateAndTimeFormatterUtil.formatDateAndTime(object.to);
// }
// };
//
// TextColumn<TrackFileImportDeviceIdentifier> numberOfFixesColumn = new TextColumn<TrackFileImportDeviceIdentifier>() {
// @Override
// public String getValue(TrackFileImportDeviceIdentifier object) {
// return "" + object.numberOfFixes;
// }
// };
TextColumn<TrackFileImportDeviceIdentifierDTO> fromColumn = new TextColumn<TrackFileImportDeviceIdentifierDTO>() {
@Override
public String getValue(TrackFileImportDeviceIdentifierDTO object) {
return DateAndTimeFormatterUtil.formatDateAndTime(object.from);
}
};
TextColumn<TrackFileImportDeviceIdentifierDTO> toColumn = new TextColumn<TrackFileImportDeviceIdentifierDTO>() {
@Override
public String getValue(TrackFileImportDeviceIdentifierDTO object) {
return DateAndTimeFormatterUtil.formatDateAndTime(object.to);
}
};
TextColumn<TrackFileImportDeviceIdentifierDTO> numberOfFixesColumn = new TextColumn<TrackFileImportDeviceIdentifierDTO>() {
@Override
public String getValue(TrackFileImportDeviceIdentifierDTO object) {
return "" + object.numFixes;
}
};
table.addColumn(uuidColumn, "UUID");
table.addColumn(fileNameColumn, "Filename");
table.addColumn(trackNameColumn, "Trackname");
// table.addColumn(fromColumn, stringMessages.from());
// table.addColumn(toColumn, stringMessages.to());
// table.addColumn(numberOfFixesColumn, "# fixes");
table.addColumn(fromColumn, stringMessages.from());
table.addColumn(toColumn, stringMessages.to());
table.addColumn(numberOfFixesColumn, "# fixes");
}
}
@@ -1,13 +1,11 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FileUpload;
@@ -20,33 +18,36 @@ import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.adminconsole.TrackFileImportDeviceIdentifierTableWrapper.TrackFileImportDeviceIdentifier;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
public class TrackFileImportWidget implements IsWidget {
private final Panel mainPanel = new VerticalPanel();
public TrackFileImportWidget(final TrackFileImportDeviceIdentifierTableWrapper table, StringMessages stringMessages,
SailingServiceAsync sailingService, ErrorReporter errorReporter) {
final SailingServiceAsync sailingService, final ErrorReporter errorReporter) {
this(new SubmitCompleteHandler() {
@Override
public void onSubmitComplete(SubmitCompleteEvent event) {
JSONArray json = JSONParser.parseLenient(event.getResults()).isArray();
table.getDataProvider().getList().clear();
for (int i=0; i<json.size(); i++) {
JSONObject obj = json.get(i).isObject();
JSONObject deviceIdJson = obj.get("id").isObject();
String uuid = deviceIdJson.get("UUID").isString().stringValue();
String fileName = deviceIdJson.get("FILE_NAME").isString().stringValue();
String trackName = deviceIdJson.get("TRACK_NAME").isString().stringValue();
long fromMillis = (long) obj.get("FROM_MILLIS").isNumber().doubleValue();
long toMillis = (long) obj.get("TO_MILLIS").isNumber().doubleValue();
TrackFileImportDeviceIdentifier deviceId = new TrackFileImportDeviceIdentifier(uuid, fileName,
trackName, new Date(fromMillis), new Date(toMillis), /* number of fixes */ 0);
table.getDataProvider().getList().add(deviceId);
}
String[] uuids = event.getResults().split("\\n");
sailingService.getTrackFileImportDeviceIds(Arrays.asList(uuids),
new AsyncCallback<List<TrackFileImportDeviceIdentifierDTO>>() {
@Override
public void onSuccess(List<TrackFileImportDeviceIdentifierDTO> result) {
table.getDataProvider().getList().addAll(result);
}
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Could not load TrackFileImportDeviceIds: " + caught.getMessage());
}
});
}
}, stringMessages, sailingService, errorReporter);
}
@@ -77,6 +77,7 @@ import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingReplayRaceDTO;
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDTO;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO;
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
import com.sap.sailing.gwt.ui.shared.VenueDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO;
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
@@ -476,5 +477,8 @@ public interface SailingService extends RemoteService {
void revokeRaceLogEvents(String leaderboardName, String raceColumnName, String fleetName, List<Serializable> eventIds)
throws NotRevokableException;
Collection<String> getGPSFixImporterTypes();
Collection<String> getGPSFixImporterTypes();
List<TrackFileImportDeviceIdentifierDTO> getTrackFileImportDeviceIds(List<String> uuids)
throws NoCorrespondingServiceRegisteredException, TransformationException;
}
@@ -68,6 +68,7 @@ import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingReplayRaceDTO;
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDTO;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO;
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
import com.sap.sailing.gwt.ui.shared.VenueDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO;
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
@@ -595,4 +596,6 @@ public interface SailingServiceAsync {
Set<Util.Triple<String, String, String>> raceLogsTo, AsyncCallback<Void> callback);
void getGPSFixImporterTypes(AsyncCallback<Collection<String>> callback);
void getTrackFileImportDeviceIds(List<String> uuids, AsyncCallback<List<TrackFileImportDeviceIdentifierDTO>> callback);
}
@@ -222,6 +222,8 @@ import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterP
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayRace;
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayService;
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayServiceFactory;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifierImpl;
import com.sap.sailing.domain.trackimport.GPSFixImporter;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
@@ -306,6 +308,7 @@ import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingReplayRaceDTO;
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDTO;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO;
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
import com.sap.sailing.gwt.ui.shared.VenueDTO;
import com.sap.sailing.gwt.ui.shared.WaypointDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO;
@@ -4321,7 +4324,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
DynamicGPSFixTrackImpl<Mark> track = new DynamicGPSFixTrackImpl<Mark>(mark, 0);
DeviceMappingEvent<Mark> lastPingMappingEvent = new LastPingMappingEventFinder<Mark>(raceLog, mark).analyze();
if (lastPingMappingEvent != null) {
getService().getGPSFixStore().loadMarkTrack(track, DeviceMappingImpl.convertToDeviceMapping(lastPingMappingEvent));
try {
getService().getGPSFixStore().loadMarkTrack(track, DeviceMappingImpl.convertToDeviceMapping(lastPingMappingEvent));
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not convert to Mark DTO: " + mark);
}
}
Position lastPos = track.getLastRawFix() == null ? null : track.getLastRawFix().getPosition();
dtos.add(convertToMarkDTO(mark, lastPos));
@@ -4601,4 +4608,21 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
return result;
}
@Override
public List<TrackFileImportDeviceIdentifierDTO> getTrackFileImportDeviceIds(List<String> uuids)
throws NoCorrespondingServiceRegisteredException, TransformationException {
List<TrackFileImportDeviceIdentifierDTO> result = new ArrayList<>();
for (String uuidAsString : uuids) {
UUID uuid = UUID.fromString(uuidAsString);
TrackFileImportDeviceIdentifier device = TrackFileImportDeviceIdentifierImpl.getOrCreate(uuid);
long numFixes = getService().getGPSFixStore().getNumberOfFixes(device);
TimeRange timeRange = getService().getGPSFixStore().getTimeRangeCoveredByFixes(device);
Date from = timeRange == null ? null : timeRange.from().asDate();
Date to = timeRange == null ? null : timeRange.to().asDate();
result.add(new TrackFileImportDeviceIdentifierDTO(uuidAsString, device.getFileName(), device.getTrackName(),
numFixes, from, to));
}
return result;
}
}
@@ -0,0 +1,28 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.Date;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
public class TrackFileImportDeviceIdentifierDTO extends DeviceIdentifierDTO {
private static final long serialVersionUID = 5409142940941055516L;
public String uuidAsString;
public String fileName;
public String trackName;
public long numFixes;
public Date from;
public Date to;
protected TrackFileImportDeviceIdentifierDTO() {}
public TrackFileImportDeviceIdentifierDTO(String uuidAsString, String fileName, String trackName,
long numFixes, Date from, Date to) {
super(TrackFileImportDeviceIdentifier.TYPE, uuidAsString);
this.uuidAsString = uuidAsString;
this.fileName = fileName;
this.trackName = trackName;
this.numFixes = numFixes;
this.from = from;
this.to = to;
}
}
@@ -24,30 +24,25 @@ import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.json.simple.JSONArray;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.TimeRangeImpl;
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinder;
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
import com.sap.sailing.domain.racelog.tracking.DeviceWithTimeRange;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
import com.sap.sailing.domain.trackimport.FormatNotSupportedException;
import com.sap.sailing.domain.trackimport.GPSFixImporter;
import com.sap.sailing.domain.trackimport.GPSFixImporter.Callback;
import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.server.gateway.AbstractJsonHttpServlet;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.DeviceIdentifierJsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.DeviceWithTimeRangeJsonSerializer;
import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler;
import com.sap.sse.common.Util;
/**
* Servlet that processes uploaded track files by adding their fixes to the GPSFixStore.
* Returns a JSON array of generated device identifiers.<p>
* Returns a newline-separated list of the device identifiers genearted by the import.<p>
*
* The available importers are tried one by one in the following order, until the first
* one is found that does not fail with an {@link FormatNotSupportedException}:
@@ -68,7 +63,11 @@ public class TrackFilesImportServlet extends AbstractJsonHttpServlet {
private static final int READ_BUFFER_SIZE = 1024 * 1024 * 1024;
public void storeFix(GPSFix fix, DeviceIdentifier deviceIdentifier) {
getService().getGPSFixStore().storeFix(deviceIdentifier, fix);
try {
getService().getGPSFixStore().storeFix(deviceIdentifier, fix);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not store fix for " + deviceIdentifier);
}
}
public Collection<GPSFixImporter> getGPSFixImporters(String fileExtension) {
@@ -90,9 +89,9 @@ public class TrackFilesImportServlet extends AbstractJsonHttpServlet {
return result;
}
public Iterable<DeviceWithTimeRange> importFiles(Iterable<Util.Pair<String, InputStream>> files, GPSFixImporter preferredImporter)
public Iterable<TrackFileImportDeviceIdentifier> importFiles(Iterable<Pair<String, InputStream>> files, GPSFixImporter preferredImporter)
throws IOException {
final Set<DeviceIdentifier> deviceIds = new HashSet<>();
final Set<TrackFileImportDeviceIdentifier> deviceIds = new HashSet<>();
final Map<DeviceIdentifier, TimePoint> from = new HashMap<>();
final Map<DeviceIdentifier, TimePoint> to = new HashMap<>();
@@ -134,7 +133,7 @@ public class TrackFilesImportServlet extends AbstractJsonHttpServlet {
try {
importer.importFixes(in, new Callback() {
@Override
public void addFix(GPSFix fix, DeviceIdentifier device) {
public void addFix(GPSFix fix, TrackFileImportDeviceIdentifier device) {
deviceIds.add(device);
storeFix(fix, device);
@@ -160,11 +159,7 @@ public class TrackFilesImportServlet extends AbstractJsonHttpServlet {
}
}
}
List<DeviceWithTimeRange> result = new ArrayList<>();
for (DeviceIdentifier deviceId : deviceIds) {
result.add(new DeviceWithTimeRangeImpl(deviceId, new TimeRangeImpl(from.get(deviceId), to.get(deviceId))));
}
return result;
return deviceIds;
}
@SuppressWarnings("unchecked")
@@ -201,20 +196,16 @@ public class TrackFilesImportServlet extends AbstractJsonHttpServlet {
findService(prefImporterType);
}
final Iterable<DeviceWithTimeRange> mappingList = importFiles(files, preferredImporter);
final Iterable<TrackFileImportDeviceIdentifier> mappingList = importFiles(files, preferredImporter);
//setJsonResponseHeader(resp);
//DO NOT set a JSON response header. This causes the browser to wrap the response in a
//<pre> tag when uploading from GWT, as this is an AJAX-request inside an iFrame.
resp.setContentType("text/html");
TypeBasedServiceFinder<DeviceIdentifierJsonHandler> serviceFinder =
getServiceFinderFactory().createServiceFinder(DeviceIdentifierJsonHandler.class);
JsonSerializer<DeviceWithTimeRange> serializer = new DeviceWithTimeRangeJsonSerializer(new DeviceIdentifierJsonSerializer(serviceFinder));
JSONArray array = new JSONArray();
for (DeviceWithTimeRange mapping : mappingList) {
array.add(serializer.serialize(mapping));
for (TrackFileImportDeviceIdentifier mapping : mappingList) {
String stringRep = mapping.getId().toString();
resp.getWriter().println(stringRep);
}
array.writeJSONString(resp.getWriter());
}
}
@@ -16,7 +16,7 @@ import org.w3c.dom.Element;
import slash.navigation.base.BaseNavigationPosition;
import slash.navigation.gpx.binding11.WptType;
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.server.trackfiles.impl.BaseRouteConverterGPSFixImporterImpl;
import com.sap.sailing.server.trackfiles.impl.RouteConverterGPSFixImporterImpl;
@@ -49,7 +49,7 @@ public class RouteConverterGpx11ExtensionsTest {
importer.importFixes(in, new com.sap.sailing.domain.trackimport.GPSFixImporter.Callback() {
@Override
public void addFix(GPSFix fix, DeviceIdentifier device) {
public void addFix(GPSFix fix, TrackFileImportDeviceIdentifier device) {
}
}, false, "source");
@@ -8,7 +8,7 @@ import java.io.InputStream;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
import com.sap.sailing.domain.trackimport.FormatNotSupportedException;
import com.sap.sailing.domain.trackimport.GPSFixImporter.Callback;
import com.sap.sailing.domain.tracking.GPSFix;
@@ -28,7 +28,7 @@ public class TrackFileImportTest {
InputStream in = getClass().getResourceAsStream("/Cardiff Race17 - COMPETITORS.gpx");
new RouteConverterGPSFixImporterImpl().importFixes(in, new Callback() {
@Override
public void addFix(GPSFix fix, DeviceIdentifier device) {
public void addFix(GPSFix fix, TrackFileImportDeviceIdentifier device) {
if (fix instanceof GPSFixMoving) {
callbackCalled = true;
}
@@ -42,7 +42,7 @@ public class TrackFileImportTest {
InputStream in = getClass().getResourceAsStream("/sam002903 - COMPETITORS.kml");
new RouteConverterGPSFixImporterImpl().importFixes(in, new Callback() {
@Override
public void addFix(GPSFix fix, DeviceIdentifier device) {
public void addFix(GPSFix fix, TrackFileImportDeviceIdentifier device) {
if (fix instanceof GPSFix) {
callbackCalled = true;
}
@@ -1,7 +1,7 @@
package com.sap.sailing.server.trackfiles.common;
import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
import com.sap.sailing.domain.trackimport.GPSFixImporter;
import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.domain.tracking.GPSFixMoving;
@@ -24,10 +24,12 @@ import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
public abstract class BaseGPSFixImporterImpl implements GPSFixImporter {
private GPSFix previousFix;
protected void addFixAndInfer(Callback callback, boolean inferSpeedAndBearing, GPSFix fix, DeviceIdentifier device) {
protected void addFixAndInfer(Callback callback, boolean inferSpeedAndBearing, GPSFix fix,
TrackFileImportDeviceIdentifier device) {
if (inferSpeedAndBearing && ! (fix instanceof GPSFixMoving)) {
if (previousFix == null) {
//have to infer speed and bearing, but this is the first fix -> drop it
previousFix = fix;
return;
}
SpeedWithBearing speedWithBearing = previousFix.getSpeedAndBearingRequiredToReach(fix);
@@ -13,7 +13,7 @@ import slash.navigation.base.NavigationFormat;
import slash.navigation.base.NavigationFormatParser;
import slash.navigation.base.ParserResult;
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifierImpl;
import com.sap.sailing.domain.trackimport.FormatNotSupportedException;
import com.sap.sailing.domain.tracking.GPSFix;
@@ -74,7 +74,7 @@ public abstract class BaseRouteConverterGPSFixImporterImpl extends BaseGPSFixImp
for (BaseRoute route : routes) {
List<? extends BaseNavigationPosition> positions = (List<? extends BaseNavigationPosition>) route.getPositions();
String routeName = route.getName();
DeviceIdentifier device = new TrackFileImportDeviceIdentifierImpl(sourceName, routeName);
TrackFileImportDeviceIdentifier device = new TrackFileImportDeviceIdentifierImpl(sourceName, routeName);
for (BaseNavigationPosition p : positions) {
try {
addFixAndInfer(callback, inferSpeedAndBearing, convertToGPSFix(p), device);
@@ -4,6 +4,7 @@ import java.util.Arrays;
import java.util.Date;
import java.util.List;
import slash.common.type.CompactCalendar;
import slash.navigation.base.BaseNavigationPosition;
import slash.navigation.base.NavigationFormat;
import slash.navigation.base.NavigationFormats;
@@ -190,7 +191,13 @@ public class RouteConverterGPSFixImporterImpl extends BaseRouteConverterGPSFixIm
}
public GPSFix convertToGPSFix(BaseNavigationPosition position) throws Exception {
Date t = position.getTime().getTime();
final CompactCalendar time = position.getTime();
final Date t;
if (time == null) {
t = new Date(); // use "now" as the time for the fix which otherwise would be lacking a time stamp
} else {
t = time.getTime();
}
Double heading = null;
if (position instanceof Wgs84Position) {
heading = ((Wgs84Position) position).getHeading();