diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java index 22d3431570d..1bd49c6a10f 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java @@ -132,7 +132,7 @@ public interface DomainObjectFactory { RegattaLog loadRegattaLog(RegattaLikeIdentifier identifier); - Collection loadAllLegacyCompetitorsWithBoat(); + Collection renameCompetitorsCollectionAndloadAllLegacyCompetitors(); /** * Loads all competitors (with and without embedded boats) and resolves them via the domain factory. diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java index 37794a1fed8..19329ceb66f 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java @@ -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. diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 46c2ffe0657..b40d955cee6 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -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 loadAllCompetitors() { ArrayList 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 loadAllLegacyCompetitorsWithBoat() { + public Collection renameCompetitorsCollectionAndloadAllLegacyCompetitors() { + DBCollection orginalCompetitorCollection = database.getCollection(CollectionNames.COMPETITORS.name()); + orginalCompetitorCollection.rename(CollectionNames.COMPETITORS_BAK.name()); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_BAK.name()); ArrayList 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; } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index b24a3b703ea..146e66d2194 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -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 competitors) { if (!Util.isEmpty(competitors)) { - DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITH_BOAT_REFERENCES.name()); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); List 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 competitors) { if (!Util.isEmpty(competitors)) { - DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITH_BOAT_REFERENCES.name()); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); List 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); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index dbdfd8c976e..470fc65d9b5 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -341,10 +341,6 @@ public class MockedTrackedRace implements DynamicTrackedRace { return false; } - @Override - public void setCanBoatsOfCompetitorsChangePerRace(boolean canBoatsOfCompetitorsChangePerRace) { - } - @Override public void addRace(RaceDefinition race) { } diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index 9d113264216..609cff5a5b1 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -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 diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java index 48275efdd62..62bb9f38604 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java @@ -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 diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/MigratableRegattaImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/MigratableRegattaImpl.java new file mode 100644 index 00000000000..a2993f45c79 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/MigratableRegattaImpl.java @@ -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 MigratableRegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, String name, + BoatClass boatClass, boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, + Iterable 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); + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java index f893042b30f..aee24031634 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java @@ -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; } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java index 0228ccd345d..aafbfcec91f 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java @@ -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(); } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java index 64377ccfbec..424f1951b2b 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java @@ -78,7 +78,7 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl private void migrateCompetitorsIfRequired() { boolean migrationRequired = !storeTo.getDatabase().collectionExists(CollectionNames.BOATS.name()); if (migrationRequired) { - Collection allLegacyCompetitorsWithBoat = loadFrom.loadAllLegacyCompetitorsWithBoat(); + Collection allLegacyCompetitorsWithBoat = loadFrom.renameCompetitorsCollectionAndloadAllLegacyCompetitors(); List newCompetitors = new ArrayList<>(); List newBoats = new ArrayList<>();