mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-25 06:58:39 +00:00
- Changed the way a regatta is migrated from a 'without changing boats' regatta to 'with changing boats' regatta by removing the public setter and using a special derived MigratableRegattaImpl type which provides the actual migration function
- Change COMPETITOR collection migration by renaming the old COMPETITOR collection to COMPETITOR_BAK and creating all migrated competitors in the now empty COMPETITORS collection
This commit is contained in:
+1
-1
@@ -132,7 +132,7 @@ public interface DomainObjectFactory {
|
||||
|
||||
RegattaLog loadRegattaLog(RegattaLikeIdentifier identifier);
|
||||
|
||||
Collection<CompetitorWithBoat> loadAllLegacyCompetitorsWithBoat();
|
||||
Collection<CompetitorWithBoat> renameCompetitorsCollectionAndloadAllLegacyCompetitors();
|
||||
|
||||
/**
|
||||
* Loads all competitors (with and without embedded boats) and resolves them via the domain factory.
|
||||
|
||||
+4
-4
@@ -72,14 +72,14 @@ public enum CollectionNames {
|
||||
|
||||
/**
|
||||
* Legacy store for competitors before implementation of bug2822
|
||||
* Stores competitors with contained boats.
|
||||
* Contains the old competitors with contained boats.
|
||||
*/
|
||||
COMPETITORS,
|
||||
COMPETITORS_BAK,
|
||||
|
||||
/**
|
||||
* Stores competitors with boat references.
|
||||
* Stores competitors with or without boat references.
|
||||
*/
|
||||
COMPETITORS_WITH_BOAT_REFERENCES,
|
||||
COMPETITORS,
|
||||
|
||||
/**
|
||||
* Stores boats.
|
||||
|
||||
+29
-13
@@ -129,8 +129,8 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEv
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnTimeFactorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl;
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.anniversary.DetailedRaceInfo;
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorWithBoat;
|
||||
@@ -159,6 +159,7 @@ import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl;
|
||||
import com.sap.sailing.domain.base.impl.CourseDataImpl;
|
||||
import com.sap.sailing.domain.base.impl.EventImpl;
|
||||
import com.sap.sailing.domain.base.impl.FleetImpl;
|
||||
import com.sap.sailing.domain.base.impl.MigratableRegattaImpl;
|
||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||
import com.sap.sailing.domain.base.impl.RemoteSailingServerReferenceImpl;
|
||||
import com.sap.sailing.domain.base.impl.SailingServerConfigurationImpl;
|
||||
@@ -1264,18 +1265,31 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
Boolean canBoatsOfCompetitorsChangePerRace = (Boolean) dbRegatta
|
||||
.get(FieldNames.REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE.name());
|
||||
// for backward compatibility
|
||||
boolean createMigratableRegatta = false;
|
||||
if (canBoatsOfCompetitorsChangePerRace == null) {
|
||||
canBoatsOfCompetitorsChangePerRace = false;
|
||||
createMigratableRegatta = true;
|
||||
}
|
||||
final RankingMetricConstructor rankingMetricConstructor = loadRankingMetricConstructor(dbRegatta);
|
||||
result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, boatClass,
|
||||
canBoatsOfCompetitorsChangePerRace, startDate, endDate, series, /* persistent */true,
|
||||
loadScoringScheme(dbRegatta), id, courseArea,
|
||||
buoyZoneRadiusInHullLengths == null ? Regatta.DEFAULT_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS
|
||||
: buoyZoneRadiusInHullLengths,
|
||||
useStartTimeInference == null ? true : useStartTimeInference,
|
||||
controlTrackingFromStartAndFinishTimes == null ? false : controlTrackingFromStartAndFinishTimes,
|
||||
rankingMetricConstructor);
|
||||
if (createMigratableRegatta) {
|
||||
result = new MigratableRegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, boatClass,
|
||||
canBoatsOfCompetitorsChangePerRace, startDate, endDate, series, /* persistent */true,
|
||||
loadScoringScheme(dbRegatta), id, courseArea,
|
||||
buoyZoneRadiusInHullLengths == null ? Regatta.DEFAULT_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS
|
||||
: buoyZoneRadiusInHullLengths,
|
||||
useStartTimeInference == null ? true : useStartTimeInference,
|
||||
controlTrackingFromStartAndFinishTimes == null ? false : controlTrackingFromStartAndFinishTimes,
|
||||
rankingMetricConstructor);
|
||||
} else {
|
||||
result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, boatClass,
|
||||
canBoatsOfCompetitorsChangePerRace, startDate, endDate, series, /* persistent */true,
|
||||
loadScoringScheme(dbRegatta), id, courseArea,
|
||||
buoyZoneRadiusInHullLengths == null ? Regatta.DEFAULT_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS
|
||||
: buoyZoneRadiusInHullLengths,
|
||||
useStartTimeInference == null ? true : useStartTimeInference,
|
||||
controlTrackingFromStartAndFinishTimes == null ? false : controlTrackingFromStartAndFinishTimes,
|
||||
rankingMetricConstructor);
|
||||
}
|
||||
result.setRegattaConfiguration(configuration);
|
||||
}
|
||||
return result;
|
||||
@@ -2371,7 +2385,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
@Override
|
||||
public Collection<Competitor> loadAllCompetitors() {
|
||||
ArrayList<Competitor> result = new ArrayList<>();
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITH_BOAT_REFERENCES.name());
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
try {
|
||||
for (DBObject o : collection.find()) {
|
||||
JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(o)));
|
||||
@@ -2386,9 +2400,11 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<CompetitorWithBoat> loadAllLegacyCompetitorsWithBoat() {
|
||||
public Collection<CompetitorWithBoat> renameCompetitorsCollectionAndloadAllLegacyCompetitors() {
|
||||
DBCollection orginalCompetitorCollection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
orginalCompetitorCollection.rename(CollectionNames.COMPETITORS_BAK.name());
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_BAK.name());
|
||||
ArrayList<CompetitorWithBoat> result = new ArrayList<>();
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
try {
|
||||
for (DBObject o : collection.find()) {
|
||||
JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(o)));
|
||||
@@ -2397,7 +2413,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load competitors.");
|
||||
logger.log(Level.SEVERE, "loadLegacyCompetitors", e);
|
||||
logger.log(Level.SEVERE, "renameCompetitorsCollectionAndloadAllLegacyCompetitors", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+6
-6
@@ -1352,7 +1352,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
}
|
||||
|
||||
private void storeCompetitorWithoutBoat(Competitor competitor) {
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITH_BOAT_REFERENCES.name());
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
JSONObject json = competitorSerializer.serialize(competitor);
|
||||
DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString());
|
||||
DBObject entry = (DBObject) JSON.parse(json.toString());
|
||||
@@ -1360,7 +1360,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
}
|
||||
|
||||
private void storeCompetitorWithBoat(CompetitorWithBoat competitor) {
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITH_BOAT_REFERENCES.name());
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
JSONObject json = competitorWithBoatRefSerializer.serialize(competitor);
|
||||
DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString());
|
||||
DBObject entry = (DBObject) JSON.parse(json.toString());
|
||||
@@ -1386,7 +1386,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
|
||||
private void storeCompetitorsWithoutBoat(Iterable<Competitor> competitors) {
|
||||
if (!Util.isEmpty(competitors)) {
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITH_BOAT_REFERENCES.name());
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
List<DBObject> competitorsDB = new ArrayList<>();
|
||||
for (Competitor competitor : competitors) {
|
||||
JSONObject json = competitorSerializer.serialize(competitor);
|
||||
@@ -1399,7 +1399,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
|
||||
private void storeCompetitorsWithBoat(Iterable<CompetitorWithBoat> competitors) {
|
||||
if (!Util.isEmpty(competitors)) {
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITH_BOAT_REFERENCES.name());
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
List<DBObject> competitorsDB = new ArrayList<>();
|
||||
for (CompetitorWithBoat competitor : competitors) {
|
||||
JSONObject json = competitorWithBoatRefSerializer.serialize(competitor);
|
||||
@@ -1413,14 +1413,14 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
@Override
|
||||
public void removeAllCompetitors() {
|
||||
logger.info("Removing all persistent competitors");
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITH_BOAT_REFERENCES.name());
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
collection.drop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCompetitor(Competitor competitor) {
|
||||
logger.info("Removing persistent competitor info for competitor "+competitor.getName()+" with ID "+competitor.getId());
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITH_BOAT_REFERENCES.name());
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString());
|
||||
collection.remove(query, WriteConcern.SAFE);
|
||||
}
|
||||
|
||||
-4
@@ -341,10 +341,6 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCanBoatsOfCompetitorsChangePerRace(boolean canBoatsOfCompetitorsChangePerRace) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRace(RaceDefinition race) {
|
||||
}
|
||||
|
||||
+15
-6
@@ -44,6 +44,7 @@ import com.sap.sailing.domain.base.impl.DynamicBoat;
|
||||
import com.sap.sailing.domain.base.impl.DynamicPerson;
|
||||
import com.sap.sailing.domain.base.impl.DynamicTeam;
|
||||
import com.sap.sailing.domain.base.impl.KilometersPerHourSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.base.impl.MigratableRegattaImpl;
|
||||
import com.sap.sailing.domain.base.impl.PersonImpl;
|
||||
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
|
||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||
@@ -693,19 +694,27 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
|
||||
// If the tractrac race contains boat metadata we assume the regatta can have changing boats per race.
|
||||
// As the attribute 'canBoatsOfCompetitorsChangePerRace' is new and 'false' is the default value
|
||||
// we need to set it's value to true for the regatta
|
||||
if (competitorBoatInfo != null && trackedRegatta.getRegatta().canBoatsOfCompetitorsChangePerRace() == false) {
|
||||
// we need to set this to true for the regatta to make it possible to edit the boat/competitor mappings
|
||||
trackedRegatta.getRegatta().setCanBoatsOfCompetitorsChangePerRace(true);
|
||||
// we need to set it's value to true for the regatta, but only if the regatta is of type MigratableRegattaImpl
|
||||
Regatta regatta = trackedRegatta.getRegatta();
|
||||
if (competitorBoatInfo != null && regatta.canBoatsOfCompetitorsChangePerRace() == false) {
|
||||
// we need to set this to true for the regatta to make it possible to create the boat/competitor mappings
|
||||
if (regatta instanceof MigratableRegattaImpl) {
|
||||
MigratableRegattaImpl migratableRegatta = (MigratableRegattaImpl) regatta;
|
||||
migratableRegatta.migrateCanBoatsOfCompetitorsChangePerRace(true);
|
||||
logger.log(Level.INFO, "Successful migration of regatta " + regatta.getName() +
|
||||
" to be of type 'canBoatsOfCompetitorsChangePerRace=true'");
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "Regatta " + regatta.getName() +
|
||||
" has wrong type 'canBoatsOfCompetitorsChangePerRace' but can't be migrated because it is not of type MigratableRegattaImpl");
|
||||
}
|
||||
}
|
||||
|
||||
// Case 1
|
||||
if (trackedRegatta.getRegatta().canBoatsOfCompetitorsChangePerRace()) {
|
||||
if (regatta.canBoatsOfCompetitorsChangePerRace()) {
|
||||
// create an unique identifier for the boat and try to find it in the boatStore
|
||||
Serializable boatId;
|
||||
String sailId;
|
||||
if (competitorBoatInfo != null) {
|
||||
Regatta regatta = trackedRegatta.getRegatta();
|
||||
LeaderboardGroup leaderboardGroup = leaderboardGroupResolver.resolveLeaderboardGroupByRegattaName(regatta.getName());
|
||||
boatId = createUniqueBoatIdentifierFromBoatMetadata(regatta, leaderboardGroup, competitorBoatInfo);
|
||||
sailId = competitorBoatInfo.getId(); // we take here the boatId as sailID which is a number like 1, 2, 3
|
||||
|
||||
@@ -146,12 +146,6 @@ public interface Regatta extends NamedWithID, IsRegattaLike, HasRaceColumnsAndRe
|
||||
|
||||
RegattaIdentifier getRegattaIdentifier();
|
||||
|
||||
/**
|
||||
* Changes whether the competitors use the same boat for the whole regatta or change the boat used during the competition.
|
||||
* Actually this should never be called as this should not change once set, but we need it to migrate older regattas to the new model.
|
||||
*/
|
||||
void setCanBoatsOfCompetitorsChangePerRace(boolean canBoatsOfCompetitorsChangePerRace);
|
||||
|
||||
/**
|
||||
* Regattas may be constructed as implicit default regattas in which case they won't need to be stored durably and
|
||||
* don't contain valuable information worth being preserved; or they are constructed explicitly with series and race
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.CourseArea;
|
||||
import com.sap.sailing.domain.base.Series;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.racelog.RaceLogStore;
|
||||
import com.sap.sailing.domain.ranking.RankingMetricConstructor;
|
||||
import com.sap.sailing.domain.regattalog.RegattaLogStore;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class MigratableRegattaImpl extends RegattaImpl {
|
||||
private static final long serialVersionUID = -3545488249832218320L;
|
||||
|
||||
public <S extends Series> MigratableRegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, String name,
|
||||
BoatClass boatClass, boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate,
|
||||
Iterable<S> series, boolean persistent, ScoringScheme scoringScheme, Serializable id, CourseArea courseArea,
|
||||
Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference,
|
||||
boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor) {
|
||||
super(raceLogStore, regattaLogStore, name, boatClass, canBoatsOfCompetitorsChangePerRace, startDate, endDate, series,
|
||||
persistent, scoringScheme, id, courseArea, buoyZoneRadiusInHullLengths, useStartTimeInference,
|
||||
controlTrackingFromStartAndFinishTimes, rankingMetricConstructor);
|
||||
}
|
||||
|
||||
public void migrateCanBoatsOfCompetitorsChangePerRace(boolean canBoatsOfCompetitorsChangePerRace) {
|
||||
super.setCanBoatsOfCompetitorsChangePerRace(canBoatsOfCompetitorsChangePerRace);
|
||||
}
|
||||
}
|
||||
@@ -744,8 +744,11 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
return canBoatsOfCompetitorsChangePerRace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCanBoatsOfCompetitorsChangePerRace(boolean canBoatsOfCompetitorsChangePerRace) {
|
||||
/**
|
||||
* Changes whether the competitors use the same boat for the whole regatta or change the boat used during the competition.
|
||||
* Actually this should never be called as this should not change once set, but we need it to migrate older regattas to the new model.
|
||||
*/
|
||||
protected void setCanBoatsOfCompetitorsChangePerRace(boolean canBoatsOfCompetitorsChangePerRace) {
|
||||
this.canBoatsOfCompetitorsChangePerRace = canBoatsOfCompetitorsChangePerRace;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest {
|
||||
|
||||
private void dropCompetitorCollection() {
|
||||
DB db = getMongoService().getDB();
|
||||
DBCollection competitorCollection = db.getCollection(CollectionNames.COMPETITORS.name());
|
||||
DBCollection competitorCollection = db.getCollection(CollectionNames.COMPETITORS_BAK.name());
|
||||
competitorCollection.setWriteConcern(WriteConcern.SAFE); // ensure that the drop() has happened
|
||||
competitorCollection.drop();
|
||||
}
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl
|
||||
private void migrateCompetitorsIfRequired() {
|
||||
boolean migrationRequired = !storeTo.getDatabase().collectionExists(CollectionNames.BOATS.name());
|
||||
if (migrationRequired) {
|
||||
Collection<CompetitorWithBoat> allLegacyCompetitorsWithBoat = loadFrom.loadAllLegacyCompetitorsWithBoat();
|
||||
Collection<CompetitorWithBoat> allLegacyCompetitorsWithBoat = loadFrom.renameCompetitorsCollectionAndloadAllLegacyCompetitors();
|
||||
List<Competitor> newCompetitors = new ArrayList<>();
|
||||
List<Boat> newBoats = new ArrayList<>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user